Skip to content

Commit d5da9d8

Browse files
ed255ax0
andauthored
Display point in base58 (#305)
* Compress EC subgroup points before serialising * serialize and display point in base58 * Use Display for Points --------- Co-authored-by: Ahmad <root@ahmadafuni.com>
1 parent 151419e commit d5da9d8

File tree

4 files changed

+87
-8
lines changed

4 files changed

+87
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ plonky2 = { git = "https://github.com/0xPolygonZero/plonky2", optional = true }
2323
serde = "1.0.219"
2424
serde_json = "1.0.140"
2525
base64 = "0.22.1"
26+
bs58 = "0.5.1"
2627
schemars = "0.8.22"
2728
num = { version = "0.4.3", features = ["num-bigint"] }
2829
num-bigint = { version = "0.4.6", features = ["rand"] }

examples/signed_pod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
1515
// Create a schnorr key pair to sign the pod
1616
let sk = SecretKey::new_rand();
1717
let pk = sk.public_key();
18-
println!("Public key: {:?}\n", pk);
18+
println!("Public key: {}\n", pk);
1919

2020
let mut signer = Signer(sk);
2121

src/backends/plonky2/primitives/ec/curve.rs

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! We roughly follow pornin/ecgfp5.
44
use core::ops::{Add, Mul};
55
use std::{
6-
array,
6+
array, fmt,
77
ops::{AddAssign, Neg, Sub},
88
sync::LazyLock,
99
};
@@ -23,7 +23,7 @@ use plonky2::{
2323
util::serialization::{Read, Write},
2424
};
2525
use rand::rngs::OsRng;
26-
use serde::{Deserialize, Serialize};
26+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
2727

2828
use crate::backends::plonky2::{
2929
circuits::common::ValueTarget,
@@ -94,12 +94,65 @@ fn ec_field_from_bytes(b: &[u8]) -> Result<ECField, Error> {
9494
Ok(QuinticExtension(array::from_fn(|i| fields[i])))
9595
}
9696

97-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
97+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9898
pub struct Point {
9999
pub x: ECField,
100100
pub u: ECField,
101101
}
102102

103+
impl fmt::Display for Point {
104+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105+
#[allow(clippy::collapsible_else_if)]
106+
if f.alternate() {
107+
write!(f, "({}, {})", self.x, self.u)
108+
} else {
109+
if self.is_in_subgroup() {
110+
// Compressed
111+
let u_bytes = self.as_bytes_from_subgroup().expect("point in subgroup");
112+
let u_b58 = bs58::encode(u_bytes).into_string();
113+
write!(f, "{}", u_b58)
114+
} else {
115+
// Non-compressed
116+
let xu_bytes = [ec_field_to_bytes(&self.x), ec_field_to_bytes(&self.u)].concat();
117+
let xu_b58 = bs58::encode(xu_bytes).into_string();
118+
write!(f, "{}", xu_b58)
119+
}
120+
}
121+
}
122+
}
123+
124+
impl Serialize for Point {
125+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
126+
where
127+
S: Serializer,
128+
{
129+
let point_b58 = format!("{}", self);
130+
serializer.serialize_str(&point_b58)
131+
}
132+
}
133+
134+
impl<'de> Deserialize<'de> for Point {
135+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
136+
where
137+
D: Deserializer<'de>,
138+
{
139+
let point_b58 = String::deserialize(deserializer)?;
140+
let point_bytes: Vec<u8> = bs58::decode(point_b58)
141+
.into_vec()
142+
.map_err(serde::de::Error::custom)?;
143+
if point_bytes.len() == 80 {
144+
// Non-compressed
145+
Ok(Point {
146+
x: ec_field_from_bytes(&point_bytes[..40]).map_err(serde::de::Error::custom)?,
147+
u: ec_field_from_bytes(&point_bytes[40..]).map_err(serde::de::Error::custom)?,
148+
})
149+
} else {
150+
// Compressed
151+
Self::from_bytes_into_subgroup(&point_bytes).map_err(serde::de::Error::custom)
152+
}
153+
}
154+
}
155+
103156
impl Point {
104157
pub fn new_rand_from_subgroup() -> Self {
105158
&OsRng.gen_biguint_below(&GROUP_ORDER) * Self::generator()
@@ -111,8 +164,8 @@ impl Point {
111164
match self.is_in_subgroup() {
112165
true => Ok(self.u),
113166
false => Err(Error::custom(format!(
114-
"Point must lie in EC subgroup: ({}, {})",
115-
self.x, self.u
167+
"Point must lie in EC subgroup: {}",
168+
self
116169
))),
117170
}
118171
}
@@ -810,7 +863,7 @@ mod test {
810863
match p == q {
811864
true => Ok(()),
812865
false => Err(Error::custom(format!(
813-
"Roundtrip compression failed: {:?} ≠ {:?}",
866+
"Roundtrip compression failed: {} ≠ {}",
814867
p, q
815868
))),
816869
}
@@ -897,4 +950,28 @@ mod test {
897950
assert!(data.prove(pw).is_err());
898951
Ok(())
899952
}
953+
954+
#[test]
955+
fn test_point_serialize_deserialize() -> Result<(), anyhow::Error> {
956+
// In subgroup
957+
let g = Point::generator();
958+
959+
let serialized = serde_json::to_string_pretty(&g)?;
960+
println!("g = {}", serialized);
961+
let deserialized = serde_json::from_str(&serialized)?;
962+
assert_eq!(g, deserialized);
963+
964+
// Not in subgroup
965+
let not_sub = Point {
966+
x: Point::b() / g.x,
967+
u: g.u,
968+
};
969+
970+
let serialized = serde_json::to_string_pretty(&not_sub)?;
971+
println!("not_sub = {}", serialized);
972+
let deserialized = serde_json::from_str(&serialized)?;
973+
assert_eq!(not_sub, deserialized);
974+
975+
Ok(())
976+
}
900977
}

src/middleware/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ impl fmt::Display for TypedValue {
180180
TypedValue::Set(s) => write!(f, "set:{}", s.commitment()),
181181
TypedValue::Array(a) => write!(f, "arr:{}", a.commitment()),
182182
TypedValue::Raw(v) => write!(f, "{}", v),
183-
TypedValue::PublicKey(p) => write!(f, "ecGFp5_pt:({},{})", p.x, p.u),
183+
TypedValue::PublicKey(p) => write!(f, "pk:{}", p),
184184
TypedValue::PodId(id) => write!(f, "pod_id:{}", id),
185185
}
186186
}
@@ -849,6 +849,7 @@ pub struct MainPodInputs<'a> {
849849
/// Statements that need to be made public (they can come from input pods or input
850850
/// statements)
851851
pub public_statements: &'a [Statement],
852+
// TODO: REMOVE THIS
852853
pub vd_set: VDSet,
853854
}
854855

0 commit comments

Comments
 (0)