Skip to content

Commit bb53259

Browse files
committed
Working MainPod serialization (but might need a code re-org now)
1 parent 0cfd277 commit bb53259

File tree

12 files changed

+205
-47
lines changed

12 files changed

+205
-47
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dyn-clone = "1.0.18"
1818
plonky2 = { git = "https://github.com/0xPolygonZero/plonky2", optional = true }
1919
serde = "1.0.219"
2020
serde_json = "1.0.140"
21+
base64 = "0.22.1"
2122

2223
[features]
2324
default = ["backend_plonky2"]

src/backends/plonky2/basetypes.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
//! `backend_plonky2` feature is enabled.
33
//! See src/middleware/basetypes.rs for more details.
44
5+
use crate::frontend::serialization::{
6+
deserialize_hash_tuple, deserialize_value_tuple, serialize_hash_tuple, serialize_value_tuple,
7+
};
8+
use crate::middleware::{Params, ToFields};
59
use anyhow::{anyhow, Error, Result};
610
use hex::{FromHex, FromHexError};
711
use plonky2::field::goldilocks_field::GoldilocksField;
@@ -10,11 +14,10 @@ use plonky2::hash::poseidon::PoseidonHash;
1014
use plonky2::plonk::config::Hasher;
1115
use plonky2::plonk::config::PoseidonGoldilocksConfig;
1216
use plonky2::plonk::proof::Proof as Plonky2Proof;
17+
use serde::{Deserialize, Serialize};
1318
use std::cmp::{Ord, Ordering};
1419
use std::fmt;
1520

16-
use crate::middleware::{Params, ToFields};
17-
1821
/// F is the native field we use everywhere. Currently it's Goldilocks from plonky2
1922
pub type F = GoldilocksField;
2023
/// C is the Plonky2 config used in POD2 to work with Plonky2 recursion.
@@ -32,8 +35,14 @@ pub const EMPTY: Value = Value([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
3235
pub const SELF_ID_HASH: Hash = Hash([F::ONE, F::ZERO, F::ZERO, F::ZERO]);
3336
pub const NULL: Hash = Hash([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
3437

35-
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
36-
pub struct Value(pub [F; VALUE_SIZE]);
38+
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, Serialize, Deserialize)]
39+
pub struct Value(
40+
#[serde(
41+
serialize_with = "serialize_value_tuple",
42+
deserialize_with = "deserialize_value_tuple"
43+
)]
44+
pub [F; VALUE_SIZE],
45+
);
3746

3847
impl ToFields for Value {
3948
fn to_fields(&self, _params: &Params) -> (Vec<F>, usize) {
@@ -115,8 +124,14 @@ impl fmt::Display for Value {
115124
}
116125
}
117126

118-
#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq)]
119-
pub struct Hash(pub [F; HASH_SIZE]);
127+
#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq, Serialize, Deserialize)]
128+
pub struct Hash(
129+
#[serde(
130+
serialize_with = "serialize_hash_tuple",
131+
deserialize_with = "deserialize_hash_tuple"
132+
)]
133+
pub [F; HASH_SIZE],
134+
);
120135

121136
pub fn hash_value(input: &Value) -> Hash {
122137
Hash(PoseidonHash::hash_no_pad(&input.0).elements)

src/backends/plonky2/mock_main/mod.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use plonky2::hash::poseidon::PoseidonHash;
44
use plonky2::plonk::config::Hasher;
55
use std::any::Any;
66
use std::fmt;
7+
use serde::{Deserialize, Serialize};
8+
use base64::prelude::*;
79

810
use crate::middleware::{
911
self, hash_str, AnchoredKey, Hash, MainPodInputs, NativeOperation, NativePredicate, NonePod,
@@ -26,14 +28,14 @@ impl PodProver for MockProver {
2628
}
2729
}
2830

29-
#[derive(Clone, Debug)]
31+
#[derive(Clone, Debug, Serialize, Deserialize)]
3032
pub struct MockMainPod {
3133
params: Params,
3234
id: PodId,
33-
input_signed_pods: Vec<Box<dyn Pod>>,
34-
input_main_pods: Vec<Box<dyn Pod>>,
35+
// input_signed_pods: Vec<Box<dyn Pod>>,
36+
// input_main_pods: Vec<Box<dyn Pod>>,
3537
// New statements introduced by this pod
36-
input_statements: Vec<Statement>,
38+
// input_statements: Vec<Statement>,
3739
public_statements: Vec<Statement>,
3840
operations: Vec<Operation>,
3941
// All statements (inherited + new)
@@ -331,9 +333,9 @@ impl MockMainPod {
331333
Ok(Self {
332334
params: params.clone(),
333335
id,
334-
input_signed_pods,
335-
input_main_pods,
336-
input_statements,
336+
// input_signed_pods,
337+
// input_main_pods,
338+
// input_statements,
337339
public_statements,
338340
statements,
339341
operations,
@@ -470,7 +472,7 @@ impl Pod for MockMainPod {
470472
}
471473

472474
fn serialized_proof(&self) -> String {
473-
"".to_string()
475+
BASE64_STANDARD.encode(serde_json::to_string(self).unwrap())
474476
}
475477
}
476478

src/backends/plonky2/mock_main/operation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use anyhow::Result;
22
use std::fmt;
3-
3+
use serde::{Deserialize, Serialize};
44
use super::Statement;
55
use crate::middleware::{self, OperationType};
66

7-
#[derive(Clone, Debug, PartialEq, Eq)]
7+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
88
pub enum OperationArg {
99
None,
1010
Index(usize),
@@ -16,7 +16,7 @@ impl OperationArg {
1616
}
1717
}
1818

19-
#[derive(Clone, Debug, PartialEq, Eq)]
19+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
2020
pub struct Operation(pub OperationType, pub Vec<OperationArg>);
2121

2222
impl Operation {

src/backends/plonky2/mock_main/statement.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use anyhow::{anyhow, Result};
22
use std::fmt;
3+
use serde::{Deserialize, Serialize};
34

45
use crate::middleware::{
56
self, AnchoredKey, NativePredicate, Params, Predicate, StatementArg, ToFields,
67
};
78

8-
#[derive(Clone, Debug, PartialEq, Eq)]
9+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
910
pub struct Statement(pub Predicate, pub Vec<StatementArg>);
1011

1112
impl Statement {

src/frontend/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,22 @@ use crate::middleware::{OperationType, Predicate, KEY_SIGNER, KEY_TYPE};
1818
pub mod containers;
1919
mod custom;
2020
mod operation;
21-
mod serialization;
21+
pub mod serialization;
2222
mod statement;
2323
pub use custom::*;
2424
pub use operation::*;
2525
pub use statement::*;
2626

2727
/// This type is just for presentation purposes.
28-
#[derive(Clone, Debug, Default, h::Hash, PartialEq, Eq)]
28+
#[derive(Clone, Debug, Default, h::Hash, PartialEq, Eq, Serialize, Deserialize)]
2929
pub enum PodClass {
3030
#[default]
3131
Signed,
3232
Main,
3333
}
3434

3535
// An Origin, which represents a reference to an ancestor POD.
36-
#[derive(Clone, Debug, PartialEq, Eq, h::Hash, Default)]
36+
#[derive(Clone, Debug, PartialEq, Eq, h::Hash, Default, Serialize, Deserialize)]
3737
pub struct Origin(pub PodClass, pub PodId);
3838

3939
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -238,7 +238,7 @@ impl SignedPod {
238238
}
239239
}
240240

241-
#[derive(Clone, Debug, PartialEq, Eq, h::Hash)]
241+
#[derive(Clone, Debug, PartialEq, Eq, h::Hash, Serialize, Deserialize)]
242242
pub struct AnchoredKey(pub Origin, pub String);
243243

244244
impl From<AnchoredKey> for middleware::AnchoredKey {

src/frontend/serialization.rs

Lines changed: 143 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
use std::collections::HashMap;
22

3+
use base64::prelude::*;
34
use serde::ser::{SerializeStruct, Serializer};
45
use serde::{Deserialize, Serialize};
56

7+
use crate::backends::plonky2::mock_main::MockMainPod;
68
use crate::backends::plonky2::mock_signed::MockSignedPod;
79
use crate::frontend::containers::Dictionary;
8-
use crate::middleware::{PodId, F};
9-
use crate::middleware;
10+
use crate::frontend::Statement;
11+
use crate::middleware::{self, HASH_SIZE, VALUE_SIZE};
12+
use crate::middleware::{Hash, PodId, F};
1013
use plonky2::field::types::Field;
1114

12-
use super::SignedPod;
1315
use super::Value;
16+
use super::{MainPod, SignedPod};
1417

1518
impl Serialize for SignedPod {
1619
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -44,9 +47,13 @@ impl<'de> Deserialize<'de> for SignedPod {
4447
struct SignedPodHelper {
4548
entries: HashMap<String, Value>,
4649
proof: String,
50+
pod_type: String,
4751
}
4852

4953
let helper = SignedPodHelper::deserialize(deserializer)?;
54+
if helper.pod_type != "signed" {
55+
return Err(serde::de::Error::custom("pod_type is not signed"));
56+
}
5057
let kvs = helper.entries;
5158
let dict = Dictionary::new(kvs.clone()).middleware_dict().clone();
5259
let pod = MockSignedPod::new(PodId(dict.commitment()), helper.proof, dict);
@@ -57,6 +64,45 @@ impl<'de> Deserialize<'de> for SignedPod {
5764
}
5865
}
5966

67+
impl Serialize for MainPod {
68+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
69+
where
70+
S: Serializer,
71+
{
72+
let mut state = serializer.serialize_struct("MainPod", 2)?;
73+
state.serialize_field("public_statements", &self.public_statements)?;
74+
state.serialize_field("proof", &self.pod.serialized_proof())?;
75+
state.serialize_field("pod_type", "main")?;
76+
state.end()
77+
}
78+
}
79+
80+
impl<'de> Deserialize<'de> for MainPod {
81+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82+
where
83+
D: serde::Deserializer<'de>,
84+
{
85+
#[derive(Deserialize)]
86+
struct MainPodHelper {
87+
public_statements: Vec<Statement>,
88+
proof: String,
89+
pod_type: String,
90+
}
91+
92+
let helper = MainPodHelper::deserialize(deserializer)?;
93+
if helper.pod_type != "main" {
94+
return Err(serde::de::Error::custom("pod_type is not main"));
95+
}
96+
let proof = String::from_utf8(BASE64_STANDARD.decode(&helper.proof).unwrap()).unwrap();
97+
let pod: MockMainPod = serde_json::from_str(&proof).unwrap();
98+
99+
Ok(MainPod {
100+
pod: Box::new(pod),
101+
public_statements: helper.public_statements,
102+
})
103+
}
104+
}
105+
60106
pub fn serialize_i64<S>(value: &i64, serializer: S) -> Result<S::Ok, S::Error>
61107
where
62108
S: serde::Serializer,
@@ -100,12 +146,70 @@ where
100146
Ok(middleware::Value(v))
101147
}
102148

149+
pub fn serialize_hash_tuple<S>(value: &[F; HASH_SIZE], serializer: S) -> Result<S::Ok, S::Error>
150+
where
151+
S: serde::Serializer,
152+
{
153+
serializer.serialize_str(&format!(
154+
"{:016x}{:016x}{:016x}{:016x}",
155+
value[0].0, value[1].0, value[2].0, value[3].0
156+
))
157+
}
158+
159+
pub fn deserialize_hash_tuple<'de, D>(deserializer: D) -> Result<[F; HASH_SIZE], D::Error>
160+
where
161+
D: serde::Deserializer<'de>,
162+
{
163+
let hex_str = String::deserialize(deserializer)?;
164+
let mut v = [F::ZERO; 4];
165+
for i in 0..4 {
166+
let start = i * 16;
167+
let end = start + 16;
168+
let hex_part = &hex_str[start..end];
169+
v[i] = F::from_canonical_u64(
170+
u64::from_str_radix(hex_part, 16).map_err(serde::de::Error::custom)?,
171+
);
172+
}
173+
Ok(v)
174+
}
175+
176+
pub fn serialize_value_tuple<S>(value: &[F; VALUE_SIZE], serializer: S) -> Result<S::Ok, S::Error>
177+
where
178+
S: serde::Serializer,
179+
{
180+
serializer.serialize_str(&format!(
181+
"{:016x}{:016x}{:016x}{:016x}",
182+
value[0].0, value[1].0, value[2].0, value[3].0
183+
))
184+
}
185+
186+
pub fn deserialize_value_tuple<'de, D>(deserializer: D) -> Result<[F; VALUE_SIZE], D::Error>
187+
where
188+
D: serde::Deserializer<'de>,
189+
{
190+
let hex_str = String::deserialize(deserializer)?;
191+
let mut v = [F::ZERO; VALUE_SIZE];
192+
for i in 0..VALUE_SIZE {
193+
let start = i * 16;
194+
let end = start + 16;
195+
let hex_part = &hex_str[start..end];
196+
v[i] = F::from_canonical_u64(
197+
u64::from_str_radix(hex_part, 16).map_err(serde::de::Error::custom)?,
198+
);
199+
}
200+
Ok(v)
201+
}
202+
103203
#[cfg(test)]
104204
mod tests {
105205
use crate::{
106-
backends::plonky2::mock_signed::MockSigner,
107-
frontend::{containers::{Dictionary, Array, Set}, SignedPodBuilder},
108-
middleware::Params,
206+
backends::plonky2::{mock_main::MockProver, mock_signed::MockSigner},
207+
examples::{zu_kyc_pod_builder, zu_kyc_sign_pod_builders},
208+
frontend::{
209+
containers::{Array, Dictionary, Set},
210+
MainPodBuilder, Operation, OperationArg, SignedPodBuilder,
211+
},
212+
middleware::{NativeOperation, OperationType, Params},
109213
};
110214

111215
use super::*;
@@ -172,4 +276,37 @@ mod tests {
172276
assert_eq!(pod.verify(), deserialized.verify());
173277
assert_eq!(pod.id(), deserialized.id())
174278
}
279+
280+
#[test]
281+
fn test_main_pod_serialization() {
282+
let params = middleware::Params::default();
283+
284+
let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
285+
zu_kyc_sign_pod_builders(&params);
286+
let mut signer = MockSigner {
287+
pk: "ZooGov".into(),
288+
};
289+
let gov_id_pod = gov_id_builder.sign(&mut signer).unwrap();
290+
let mut signer = MockSigner {
291+
pk: "ZooDeel".into(),
292+
};
293+
let pay_stub_pod = pay_stub_builder.sign(&mut signer).unwrap();
294+
let mut signer = MockSigner {
295+
pk: "ZooOFAC".into(),
296+
};
297+
let sanction_list_pod = sanction_list_builder.sign(&mut signer).unwrap();
298+
let kyc_builder =
299+
zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod, &sanction_list_pod).unwrap();
300+
301+
let mut prover = MockProver {};
302+
let kyc_pod = kyc_builder.prove(&mut prover, &params).unwrap();
303+
304+
let serialized = serde_json::to_string(&kyc_pod).unwrap();
305+
println!("serialized: {}", serialized);
306+
let deserialized: MainPod = serde_json::from_str(&serialized).unwrap();
307+
308+
assert_eq!(kyc_pod.public_statements, deserialized.public_statements);
309+
assert_eq!(kyc_pod.pod.id(), deserialized.pod.id());
310+
assert_eq!(kyc_pod.pod.verify(), deserialized.pod.verify());
311+
}
175312
}

0 commit comments

Comments
 (0)