-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unify & optimise serialization in v0.7 #141
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use std::fmt; | ||
|
||
use serde::de::Visitor; | ||
use serde::{Deserialize, Deserializer, Serialize, Serializer}; | ||
|
||
use super::traits::Converter; | ||
use super::BigInt; | ||
|
||
impl Serialize for BigInt { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: Serializer, | ||
{ | ||
let bytes = self.to_bytes(); | ||
serializer.serialize_bytes(&bytes) | ||
} | ||
} | ||
|
||
impl<'de> Deserialize<'de> for BigInt { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
struct BigintVisitor; | ||
|
||
impl<'de> Visitor<'de> for BigintVisitor { | ||
type Value = BigInt; | ||
|
||
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "bigint") | ||
} | ||
|
||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> | ||
where | ||
E: serde::de::Error, | ||
{ | ||
Ok(BigInt::from_bytes(v)) | ||
} | ||
} | ||
|
||
deserializer.deserialize_bytes(BigintVisitor) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -543,9 +543,8 @@ impl Serialize for Secp256k1Point { | |||||||||||||||
where | ||||||||||||||||
S: Serializer, | ||||||||||||||||
{ | ||||||||||||||||
let mut state = serializer.serialize_struct("Secp256k1Point", 2)?; | ||||||||||||||||
state.serialize_field("x", &self.x_coor().unwrap().to_hex())?; | ||||||||||||||||
state.serialize_field("y", &self.y_coor().unwrap().to_hex())?; | ||||||||||||||||
let mut state = serializer.serialize_struct("Secp256k1Point", 1)?; | ||||||||||||||||
state.serialize_field("p", &self.bytes_compressed_to_big_int().to_hex())?; | ||||||||||||||||
state.end() | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
@@ -555,7 +554,7 @@ impl<'de> Deserialize<'de> for Secp256k1Point { | |||||||||||||||
where | ||||||||||||||||
D: Deserializer<'de>, | ||||||||||||||||
{ | ||||||||||||||||
let fields = &["x", "y"]; | ||||||||||||||||
let fields = &["p"]; | ||||||||||||||||
deserializer.deserialize_struct("Secp256k1Point", fields, Secp256k1PointVisitor) | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
@@ -573,38 +572,25 @@ impl<'de> Visitor<'de> for Secp256k1PointVisitor { | |||||||||||||||
where | ||||||||||||||||
V: SeqAccess<'de>, | ||||||||||||||||
{ | ||||||||||||||||
let x = seq | ||||||||||||||||
let p = seq | ||||||||||||||||
.next_element()? | ||||||||||||||||
.ok_or_else(|| V::Error::invalid_length(0, &"a single element"))?; | ||||||||||||||||
let y = seq | ||||||||||||||||
.next_element()? | ||||||||||||||||
.ok_or_else(|| V::Error::invalid_length(0, &"a single element"))?; | ||||||||||||||||
|
||||||||||||||||
let bx = BigInt::from_hex(x).map_err(V::Error::custom)?; | ||||||||||||||||
let by = BigInt::from_hex(y).map_err(V::Error::custom)?; | ||||||||||||||||
|
||||||||||||||||
Ok(Secp256k1Point::from_coor(&bx, &by)) | ||||||||||||||||
let bp = BigInt::from_hex(p).map_err(V::Error::custom)?; | ||||||||||||||||
Ok(Secp256k1Point::from_bytes(&bp.to_bytes()[1..33]).unwrap()) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same as
|
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
fn visit_map<E: MapAccess<'de>>(self, mut map: E) -> Result<Secp256k1Point, E::Error> { | ||||||||||||||||
let mut x = String::new(); | ||||||||||||||||
let mut y = String::new(); | ||||||||||||||||
|
||||||||||||||||
let mut p = String::new(); | ||||||||||||||||
while let Some(ref key) = map.next_key::<String>()? { | ||||||||||||||||
let v = map.next_value::<String>()?; | ||||||||||||||||
if key == "x" { | ||||||||||||||||
x = v | ||||||||||||||||
} else if key == "y" { | ||||||||||||||||
y = v | ||||||||||||||||
if key == "p" { | ||||||||||||||||
p = v | ||||||||||||||||
} else { | ||||||||||||||||
return Err(E::Error::unknown_field(key, &["x", "y"])); | ||||||||||||||||
return Err(E::Error::unknown_field(key, &["p"])); | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
let bx = BigInt::from_hex(&x).map_err(E::Error::custom)?; | ||||||||||||||||
let by = BigInt::from_hex(&y).map_err(E::Error::custom)?; | ||||||||||||||||
|
||||||||||||||||
Ok(Secp256k1Point::from_coor(&bx, &by)) | ||||||||||||||||
let bp = BigInt::from_hex(&p).map_err(E::Error::custom)?; | ||||||||||||||||
Ok(Secp256k1Point::from_bytes(&bp.to_bytes()[1..33]).unwrap()) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Malformed input that comes from untrusted source may cause this method to panic.
Something like that should work:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit (not important): I think BigInt can be removed from this function by using |
||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
|
@@ -673,13 +659,12 @@ mod tests { | |||||||||||||||
fn serialize_pk() { | ||||||||||||||||
let pk = Secp256k1Point::generator(); | ||||||||||||||||
let x = pk.x_coor().unwrap(); | ||||||||||||||||
let y = pk.y_coor().unwrap(); | ||||||||||||||||
let s = serde_json::to_string(&pk).expect("Failed in serialization"); | ||||||||||||||||
|
||||||||||||||||
let expected = format!("{{\"x\":\"{}\",\"y\":\"{}\"}}", x.to_hex(), y.to_hex()); | ||||||||||||||||
let expected = format!("{{\"p\":\"{}{}\"}}", 2, x.to_hex()); | ||||||||||||||||
assert_eq!(s, expected); | ||||||||||||||||
|
||||||||||||||||
let des_pk: Secp256k1Point = serde_json::from_str(&s).expect("Failed in serialization"); | ||||||||||||||||
let des_pk: Secp256k1Point = serde_json::from_str(&s).expect("Failed in deserialization"); | ||||||||||||||||
assert_eq!(des_pk.ge, pk.ge); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
Secp256k1Point
consist of only one field, maybe just serialize it as string, not as structure? Ie. simpleserializer.serialize_str(...)
can be used herebincode
. Simply saying, it reduces size of serialized point by half. Do you prefer hex format?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.