diff --git a/src/backends/plonky2/basetypes.rs b/src/backends/plonky2/basetypes.rs index 5c32189..3a09cff 100644 --- a/src/backends/plonky2/basetypes.rs +++ b/src/backends/plonky2/basetypes.rs @@ -4,10 +4,11 @@ use plonky2::{ field::{extension::quadratic::QuadraticExtension, goldilocks_field::GoldilocksField}, - hash::poseidon::PoseidonHash, + hash::{hash_types, poseidon::PoseidonHash}, plonk::{circuit_builder, circuit_data, config::GenericConfig, proof}, }; -use serde::Serialize; +use schemars::JsonSchema; +use serde::{Deserialize, Deserializer, Serialize}; /// F is the native field we use everywhere. Currently it's Goldilocks from plonky2 pub type F = GoldilocksField; @@ -36,12 +37,10 @@ pub type VerifierCircuitData = circuit_data::VerifierCircuitData; pub type CircuitBuilder = circuit_builder::CircuitBuilder; pub type Proof = proof::Proof; pub type ProofWithPublicInputs = proof::ProofWithPublicInputs; +pub type HashOut = hash_types::HashOut; use std::{collections::HashMap, sync::LazyLock}; -use itertools::Itertools; -use plonky2::hash::hash_types::HashOut; - use crate::{ backends::plonky2::{ emptypod::STANDARD_EMPTY_POD_DATA, primitives::merkletree::MerkleClaimAndProof, @@ -65,38 +64,32 @@ pub static DEFAULT_VD_SET: LazyLock = LazyLock::new(|| { /// verifying the recursive proofs of previous PODs appears in the VDSet. /// The VDSet struct that allows to get the specific merkle proofs for the given /// verifier_data. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, JsonSchema)] pub struct VDSet { + #[serde(skip)] + #[schemars(skip)] root: Hash, // (verifier_data's hash, merkleproof) - proofs_map: HashMap, MerkleClaimAndProof>, + #[serde(skip)] + #[schemars(skip)] + proofs_map: HashMap, + tree_depth: usize, + vds_hashes: Vec, } -impl VDSet { - /// builds the verifier_datas tree, and returns the root and the proofs - pub fn new(tree_depth: usize, vds: &[VerifierOnlyCircuitData]) -> Result { - // compute the verifier_data's hashes - let vds_hashes: Vec> = vds - .iter() - .map(crate::backends::plonky2::recursion::circuit::hash_verifier_data) - .collect::>(); +impl VDSet { + fn new_from_vds_hashes(tree_depth: usize, mut vds_hashes: Vec) -> Result { // before using the hash values, sort them, so that each set of // verifier_datas gets the same VDSet root - let vds_hashes: Vec<&HashOut> = vds_hashes - .iter() - .sorted_by_key(|vd| RawValue(vd.elements)) - .collect::>(); + vds_hashes.sort(); let array = Array::new( tree_depth, - vds_hashes - .iter() - .map(|vd| Value::from(RawValue(vd.elements))) - .collect(), + vds_hashes.iter().map(|vd| Value::from(*vd)).collect(), )?; let root = array.commitment(); - let mut proofs_map = HashMap::, MerkleClaimAndProof>::new(); + let mut proofs_map = HashMap::::new(); for (i, vd) in vds_hashes.iter().enumerate() { let (value, proof) = array.prove(i)?; @@ -106,9 +99,29 @@ impl VDSet { value: value.raw(), proof, }; - proofs_map.insert(**vd, p); + proofs_map.insert(*vd, p); } - Ok(Self { root, proofs_map }) + Ok(Self { + root, + proofs_map, + tree_depth, + vds_hashes, + }) + } + /// builds the verifier_datas tree, and returns the root and the proofs + pub fn new(tree_depth: usize, vds: &[VerifierOnlyCircuitData]) -> Result { + // compute the verifier_data's hashes + let vds_hashes: Vec = vds + .iter() + .map(crate::backends::plonky2::recursion::circuit::hash_verifier_data) + .collect::>(); + + let vds_hashes: Vec = vds_hashes + .into_iter() + .map(|h| Hash(h.elements)) + .collect::>(); + + Self::new_from_vds_hashes(tree_depth, vds_hashes) } pub fn root(&self) -> Hash { self.root @@ -120,9 +133,11 @@ impl VDSet { ) -> Result> { let mut proofs: Vec = vec![]; for vd in vds { + let verifier_data_hash = + crate::backends::plonky2::recursion::circuit::hash_verifier_data(vd); let p = self .proofs_map - .get(&crate::backends::plonky2::recursion::circuit::hash_verifier_data(vd)) + .get(&Hash(verifier_data_hash.elements)) .ok_or(crate::middleware::Error::custom( "verifier_data not found in VDSet".to_string(), ))?; @@ -130,4 +145,24 @@ impl VDSet { } Ok(proofs) } + /// Returns true if the `verifier_data_hash` is in the set + pub fn contains(&self, verifier_data_hash: HashOut) -> bool { + self.proofs_map + .contains_key(&Hash(verifier_data_hash.elements)) + } +} + +impl<'de> Deserialize<'de> for VDSet { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + struct Aux { + tree_depth: usize, + vds_hashes: Vec, + } + let aux = Aux::deserialize(deserializer)?; + VDSet::new_from_vds_hashes(aux.tree_depth, aux.vds_hashes).map_err(serde::de::Error::custom) + } } diff --git a/src/backends/plonky2/circuits/mainpod.rs b/src/backends/plonky2/circuits/mainpod.rs index a7a2f42..d740365 100644 --- a/src/backends/plonky2/circuits/mainpod.rs +++ b/src/backends/plonky2/circuits/mainpod.rs @@ -1528,7 +1528,7 @@ impl InnerCircuit for MainPodVerifyTarget { } // Padding if input.recursive_pods_pub_self_statements.len() != self.params.max_input_recursive_pods { - let empty_pod = EmptyPod::new_boxed(&self.params, input.vds_set.root()); + let empty_pod = EmptyPod::new_boxed(&self.params, input.vds_set.clone()); let empty_pod_statements = empty_pod.pub_statements(); for i in input.recursive_pods_pub_self_statements.len()..self.params.max_input_recursive_pods diff --git a/src/backends/plonky2/emptypod.rs b/src/backends/plonky2/emptypod.rs index eeae2c9..b8b15a3 100644 --- a/src/backends/plonky2/emptypod.rs +++ b/src/backends/plonky2/emptypod.rs @@ -29,8 +29,8 @@ use crate::{ serialize_proof, DEFAULT_PARAMS, STANDARD_REC_MAIN_POD_CIRCUIT_DATA, }, middleware::{ - self, AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, - ToFields, Value, VerifierOnlyCircuitData, F, HASH_SIZE, KEY_TYPE, SELF, + self, AnchoredKey, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, ToFields, + VDSet, Value, VerifierOnlyCircuitData, F, HASH_SIZE, KEY_TYPE, SELF, }, timed, }; @@ -77,7 +77,7 @@ impl EmptyPodVerifyTarget { pub struct EmptyPod { params: Params, id: PodId, - vds_root: Hash, + vd_set: VDSet, proof: Proof, } @@ -106,34 +106,45 @@ static EMPTY_POD_CACHE: LazyLock>> = LazyLock::new(|| Mutex::new(HashMap::new())); impl EmptyPod { - pub fn _prove(params: &Params, vds_root: Hash) -> Result { + pub fn new(params: &Params, vd_set: VDSet) -> Result { let (empty_pod_verify_target, data) = &*STANDARD_EMPTY_POD_DATA; let mut pw = PartialWitness::::new(); - empty_pod_verify_target.set_targets(&mut pw, vds_root)?; + empty_pod_verify_target.set_targets(&mut pw, vd_set.root())?; let proof = timed!("EmptyPod prove", data.prove(pw)?); let id = &proof.public_inputs[PI_OFFSET_ID..PI_OFFSET_ID + HASH_SIZE]; let id = PodId(Hash([id[0], id[1], id[2], id[3]])); Ok(EmptyPod { params: params.clone(), id, - vds_root, + vd_set, proof: proof.proof, }) } - pub fn new_boxed(params: &Params, vds_root: Hash) -> Box { + pub fn new_boxed(params: &Params, vd_set: VDSet) -> Box { let default_params = &*DEFAULT_PARAMS; assert_eq!(default_params.id_params(), params.id_params()); let empty_pod = EMPTY_POD_CACHE .lock() .unwrap() - .entry(vds_root) - .or_insert_with(|| Self::_prove(params, vds_root).expect("prove EmptyPod")) + .entry(vd_set.root()) + .or_insert_with(|| Self::new(params, vd_set).expect("prove EmptyPod")) .clone(); Box::new(empty_pod) } - fn _verify(&self) -> Result<()> { +} + +#[derive(Serialize, Deserialize)] +struct Data { + proof: String, +} + +impl Pod for EmptyPod { + fn params(&self) -> &Params { + &self.params + } + fn verify(&self) -> Result<()> { let statements = self .pub_self_statements() .into_iter() @@ -147,7 +158,7 @@ impl EmptyPod { let public_inputs = id .to_fields(&self.params) .iter() - .chain(self.vds_root.0.iter()) + .chain(self.vd_set.root().0.iter()) .cloned() .collect_vec(); @@ -156,21 +167,7 @@ impl EmptyPod { proof: self.proof.clone(), public_inputs, }) - .map_err(|e| Error::custom(format!("EmptyPod proof verification failure: {:?}", e))) - } -} - -#[derive(Serialize, Deserialize)] -struct Data { - proof: String, -} - -impl Pod for EmptyPod { - fn params(&self) -> &Params { - &self.params - } - fn verify(&self) -> Result<(), Box> { - Ok(self._verify()?) + .map_err(|e| Error::plonky2_proof_fail("EmptyPod", e)) } fn id(&self) -> PodId { @@ -200,22 +197,22 @@ impl RecursivePod for EmptyPod { fn proof(&self) -> Proof { self.proof.clone() } - fn vds_root(&self) -> Hash { - self.vds_root + fn vd_set(&self) -> &VDSet { + &self.vd_set } fn deserialize_data( params: Params, data: serde_json::Value, - vds_root: Hash, + vd_set: VDSet, id: PodId, - ) -> Result, Box> { + ) -> Result> { let data: Data = serde_json::from_value(data)?; let circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA; let proof = deserialize_proof(&circuit_data.common, &data.proof)?; Ok(Box::new(Self { params, id, - vds_root, + vd_set, proof, })) } @@ -224,13 +221,12 @@ impl RecursivePod for EmptyPod { #[cfg(test)] pub mod tests { use super::*; - use crate::middleware::EMPTY_HASH; #[test] fn test_empty_pod() { let params = Params::default(); - let empty_pod = EmptyPod::new_boxed(¶ms, EMPTY_HASH); + let empty_pod = EmptyPod::new_boxed(¶ms, VDSet::new(8, &[]).unwrap()); empty_pod.verify().unwrap(); } } diff --git a/src/backends/plonky2/error.rs b/src/backends/plonky2/error.rs index e561164..bd5d29d 100644 --- a/src/backends/plonky2/error.rs +++ b/src/backends/plonky2/error.rs @@ -39,8 +39,8 @@ pub enum Error { }, #[error("anyhow::Error: {0}")] Anyhow(#[from] anyhow::Error), - #[error("Plonky2 proof failed to verify: {0}")] - Plonky2ProofFail(anyhow::Error), + #[error("Plonky2 proof failed to verify {0}: {1}")] + Plonky2ProofFail(String, anyhow::Error), #[error("base64::DecodeError: {0}")] Base64Decode(#[from] base64::DecodeError), #[error("serde_json::Error: {0}")] @@ -70,8 +70,8 @@ impl Error { pub fn custom(s: String) -> Self { new!(Custom(s)) } - pub fn plonky2_proof_fail(e: anyhow::Error) -> Self { - Self::Plonky2ProofFail(e) + pub fn plonky2_proof_fail(context: impl Into, e: anyhow::Error) -> Self { + Self::Plonky2ProofFail(context.into(), e) } pub fn key_not_found() -> Self { new!(KeyNotFound) diff --git a/src/backends/plonky2/mainpod/mod.rs b/src/backends/plonky2/mainpod/mod.rs index a0b590a..a31a11f 100644 --- a/src/backends/plonky2/mainpod/mod.rs +++ b/src/backends/plonky2/mainpod/mod.rs @@ -20,15 +20,15 @@ use crate::{ error::{Error, Result}, mock::{emptypod::MockEmptyPod, signedpod::MockSignedPod}, primitives::merkletree::MerkleClaimAndProof, - recursion::{RecursiveCircuit, RecursiveParams}, + recursion::{hash_verifier_data, RecursiveCircuit, RecursiveParams}, serialize_proof, signedpod::SignedPod, STANDARD_REC_MAIN_POD_CIRCUIT_DATA, }, middleware::{ - self, resolve_wildcard_values, value_from_op, AnchoredKey, CustomPredicateBatch, DynError, - Hash, MainPodInputs, NativeOperation, OperationType, Params, Pod, PodId, PodProver, - PodType, RecursivePod, StatementArg, ToFields, VDSet, F, KEY_TYPE, SELF, + self, resolve_wildcard_values, value_from_op, AnchoredKey, CustomPredicateBatch, Hash, + MainPodInputs, NativeOperation, OperationType, Params, Pod, PodId, PodProver, PodType, + RecursivePod, StatementArg, ToFields, VDSet, F, KEY_TYPE, SELF, }, timed, }; @@ -294,9 +294,9 @@ pub(crate) fn layout_statements( let empty_pod_box: Box = if mock || inputs.recursive_pods.len() == params.max_input_recursive_pods { // We mocking or we don't need padding so we skip creating an EmptyPod - MockEmptyPod::new_boxed(params) + MockEmptyPod::new_boxed(params, inputs.vd_set.clone()) } else { - EmptyPod::new_boxed(params, inputs.vds_set.root()) + EmptyPod::new_boxed(params, inputs.vd_set.clone()) }; let empty_pod = empty_pod_box.as_ref(); assert!(inputs.recursive_pods.len() <= params.max_input_recursive_pods); @@ -432,8 +432,13 @@ pub(crate) fn process_public_statements_operations( pub struct Prover {} -impl Prover { - fn _prove(&self, params: &Params, vd_set: &VDSet, inputs: MainPodInputs) -> Result { +impl PodProver for Prover { + fn prove( + &self, + params: &Params, + vd_set: &VDSet, + inputs: MainPodInputs, + ) -> Result> { let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA; let (main_pod_target, circuit_data) = RecursiveCircuit::::target_and_circuit_data_padded( @@ -466,9 +471,9 @@ impl Prover { // Pad input recursive pods with empty pods if necessary let empty_pod = if inputs.recursive_pods.len() == params.max_input_recursive_pods { // We don't need padding so we skip creating an EmptyPod - MockEmptyPod::new_boxed(params) + MockEmptyPod::new_boxed(params, inputs.vd_set.clone()) } else { - EmptyPod::new_boxed(params, inputs.vds_set.root()) + EmptyPod::new_boxed(params, inputs.vd_set.clone()) }; let inputs = MainPodInputs { recursive_pods: &inputs @@ -515,10 +520,10 @@ impl Prover { .recursive_pods .iter() .map(|pod| { - assert_eq!(inputs.vds_set.root(), pod.vds_root()); + assert_eq!(inputs.vd_set.root(), pod.vd_set().root()); ProofWithPublicInputs { proof: pod.proof(), - public_inputs: [pod.id().0 .0, inputs.vds_set.root().0].concat(), + public_inputs: [pod.id().0 .0, inputs.vd_set.root().0].concat(), } }) .collect_vec(); @@ -531,7 +536,7 @@ impl Prover { let vd_mt_proofs = vd_set.get_vds_proofs(&verifier_datas)?; let input = MainPodVerifyInput { - vds_set: inputs.vds_set.clone(), + vds_set: inputs.vd_set.clone(), vd_mt_proofs, signed_pods: signed_pods_input, recursive_pods_pub_self_statements, @@ -546,24 +551,13 @@ impl Prover { main_pod.prove(&input, proofs, verifier_datas)? ); - Ok(MainPod { + Ok(Box::new(MainPod { params: params.clone(), id, - vds_root: inputs.vds_set.root(), + vd_set: inputs.vd_set, public_statements, proof: proof_with_pis.proof, - }) - } -} - -impl PodProver for Prover { - fn prove( - &self, - params: &Params, - vd_set: &VDSet, - inputs: MainPodInputs, - ) -> Result, Box> { - Ok(self._prove(params, vd_set, inputs).map(Box::new)?) + })) } } @@ -576,7 +570,7 @@ pub struct MainPod { /// the succession of recursive MainPods, which when proving the POD, it is /// proven that all the recursive proofs that are being verified in-circuit /// use one of the verifier_data's contained in the VDSet. - vds_root: Hash, + vd_set: VDSet, public_statements: Vec, proof: Proof, } @@ -605,13 +599,37 @@ struct Data { } impl MainPod { - fn _verify(&self) -> Result<()> { + pub fn proof(&self) -> Proof { + self.proof.clone() + } + + pub fn params(&self) -> &Params { + &self.params + } +} + +impl Pod for MainPod { + fn params(&self) -> &Params { + &self.params + } + fn verify(&self) -> Result<()> { // 2. get the id out of the public statements let id = PodId(calculate_id(&self.public_statements, &self.params)); if id != self.id { return Err(Error::id_not_equal(self.id, id)); } + // 7. verifier_data_hash is in the VDSet + let verifier_data = self.verifier_data(); + let verifier_data_hash = hash_verifier_data(&verifier_data); + if !self.vd_set.contains(verifier_data_hash) { + return Err(Error::custom(format!( + "vds_root in input recursive pod not in the set: {} not in {}", + Hash(verifier_data_hash.elements), + self.vd_set.root(), + ))); + } + // 1, 3, 4, 5 verification via the zkSNARK proof let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA; // TODO: cache these artefacts @@ -625,7 +643,7 @@ impl MainPod { let public_inputs = id .to_fields(&self.params) .iter() - .chain(self.vds_root.0.iter()) + .chain(self.vd_set.root().0.iter()) .cloned() .collect_vec(); circuit_data @@ -633,28 +651,7 @@ impl MainPod { proof: self.proof.clone(), public_inputs, }) - .map_err(|e| Error::custom(format!("MainPod proof verification failure: {:?}", e))) - } - - pub fn proof(&self) -> Proof { - self.proof.clone() - } - - pub fn vds_root(&self) -> Hash { - self.vds_root - } - - pub fn params(&self) -> &Params { - &self.params - } -} - -impl Pod for MainPod { - fn params(&self) -> &Params { - &self.params - } - fn verify(&self) -> Result<(), Box> { - Ok(self._verify()?) + .map_err(|e| Error::plonky2_proof_fail("MainPod", e)) } fn id(&self) -> PodId { @@ -689,22 +686,22 @@ impl RecursivePod for MainPod { fn proof(&self) -> Proof { self.proof.clone() } - fn vds_root(&self) -> Hash { - self.vds_root + fn vd_set(&self) -> &VDSet { + &self.vd_set } fn deserialize_data( params: Params, data: serde_json::Value, - vds_root: Hash, + vd_set: VDSet, id: PodId, - ) -> Result, Box> { + ) -> Result> { let data: Data = serde_json::from_value(data)?; let common = get_common_data(¶ms)?; let proof = deserialize_proof(&common, &data.proof)?; Ok(Box::new(Self { params, id, - vds_root, + vd_set, proof, public_statements: data.public_statements, })) diff --git a/src/backends/plonky2/mock/emptypod.rs b/src/backends/plonky2/mock/emptypod.rs index c8488a0..0b72c68 100644 --- a/src/backends/plonky2/mock/emptypod.rs +++ b/src/backends/plonky2/mock/emptypod.rs @@ -7,8 +7,8 @@ use crate::{ mainpod::{self, calculate_id}, }, middleware::{ - AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, Value, - KEY_TYPE, SELF, + AnchoredKey, Params, Pod, PodId, PodType, RecursivePod, Statement, VDSet, Value, KEY_TYPE, + SELF, }, }; @@ -16,6 +16,7 @@ use crate::{ pub struct MockEmptyPod { params: Params, id: PodId, + vd_set: VDSet, } fn type_statement() -> Statement { @@ -26,15 +27,22 @@ fn type_statement() -> Statement { } impl MockEmptyPod { - pub fn new_boxed(params: &Params) -> Box { + pub fn new_boxed(params: &Params, vd_set: VDSet) -> Box { let statements = [mainpod::Statement::from(type_statement())]; let id = PodId(calculate_id(&statements, params)); Box::new(Self { params: params.clone(), id, + vd_set, }) } - fn _verify(&self) -> Result<()> { +} + +impl Pod for MockEmptyPod { + fn params(&self) -> &Params { + &self.params + } + fn verify(&self) -> Result<()> { let statements = self .pub_self_statements() .into_iter() @@ -46,15 +54,6 @@ impl MockEmptyPod { } Ok(()) } -} - -impl Pod for MockEmptyPod { - fn params(&self) -> &Params { - &self.params - } - fn verify(&self) -> Result<(), Box> { - Ok(self._verify()?) - } fn id(&self) -> PodId { self.id } @@ -77,16 +76,16 @@ impl RecursivePod for MockEmptyPod { fn proof(&self) -> Proof { panic!("MockEmptyPod can't be verified in a recursive MainPod circuit"); } - fn vds_root(&self) -> Hash { - panic!("MockEmptyPod can't be verified in a recursive MainPod circuit"); + fn vd_set(&self) -> &VDSet { + &self.vd_set } fn deserialize_data( params: Params, _data: serde_json::Value, - _vds_root: Hash, + vd_set: VDSet, id: PodId, - ) -> Result, Box> { - Ok(Box::new(Self { params, id })) + ) -> Result> { + Ok(Box::new(Self { params, id, vd_set })) } } @@ -98,7 +97,7 @@ pub mod tests { fn test_mock_empty_pod() { let params = Params::default(); - let empty_pod = MockEmptyPod::new_boxed(¶ms); + let empty_pod = MockEmptyPod::new_boxed(¶ms, VDSet::new(8, &[]).unwrap()); empty_pod.verify().unwrap(); } } diff --git a/src/backends/plonky2/mock/mainpod.rs b/src/backends/plonky2/mock/mainpod.rs index 8c25177..016d298 100644 --- a/src/backends/plonky2/mock/mainpod.rs +++ b/src/backends/plonky2/mock/mainpod.rs @@ -2,7 +2,7 @@ // MainPod // -use std::fmt; +use std::{fmt, iter}; use itertools::Itertools; use serde::{Deserialize, Serialize}; @@ -16,12 +16,14 @@ use crate::{ process_private_statements_operations, process_public_statements_operations, Operation, Statement, }, + mock::{emptypod::MockEmptyPod, signedpod::MockSignedPod}, primitives::merkletree::MerkleClaimAndProof, + recursion::hash_verifier_data, }, middleware::{ - self, hash_str, AnchoredKey, DynError, Hash, MainPodInputs, NativeOperation, - NativePredicate, OperationType, Params, Pod, PodId, PodProver, PodType, Predicate, - RecursivePod, StatementArg, VDSet, KEY_TYPE, SELF, + self, deserialize_pod, deserialize_signed_pod, hash_str, AnchoredKey, Hash, MainPodInputs, + NativeOperation, NativePredicate, OperationType, Params, Pod, PodId, PodProver, PodType, + Predicate, RecursivePod, StatementArg, VDSet, Value, KEY_TYPE, SELF, }, }; @@ -33,58 +35,65 @@ impl PodProver for MockProver { params: &Params, _vd_set: &VDSet, inputs: MainPodInputs, - ) -> Result, Box> { + ) -> Result> { Ok(Box::new(MockMainPod::new(params, inputs)?)) } } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug)] pub struct MockMainPod { params: Params, id: PodId, - vds_root: Hash, - // input_signed_pods: Vec>, - // input_main_pods: Vec>, - // New statements introduced by this pod - // input_statements: Vec, - public_statements: Vec, - operations: Vec, - // All statements (inherited + new) + vd_set: VDSet, + input_signed_pods: Vec>, + input_recursive_pods: Vec>, + // All statements (inherited + newly introduced by this pod) statements: Vec, + operations: Vec, + // public subset of the `statements` vector + public_statements: Vec, // All Merkle proofs - // TODO: Use a backend-specific representation - merkle_proofs: Vec, - // TODO: Add input pods + merkle_proofs_containers: Vec, } impl fmt::Display for MockMainPod { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { writeln!(f, "MockMainPod ({}):", self.id)?; - // TODO print input signed pods id and type - // TODO print input main pods id and type let offset_input_signed_pods = Self::offset_input_signed_pods(); - let offset_input_main_pods = self.offset_input_main_pods(); + let offset_input_recursive_pods = self.offset_input_recursive_pods(); let offset_input_statements = self.offset_input_statements(); let offset_public_statements = self.offset_public_statements(); for (i, st) in self.statements.iter().enumerate() { - if (i >= offset_input_signed_pods && i < offset_input_main_pods) + if self.params.max_input_signed_pods > 0 + && (i >= offset_input_signed_pods && i < offset_input_recursive_pods) && ((i - offset_input_signed_pods) % self.params.max_signed_pod_values == 0) { + let index = (i - offset_input_signed_pods) / self.params.max_signed_pod_values; + let pod = &self.input_signed_pods[index]; + let id = pod.id(); + let pod_type = pod.pod_type(); writeln!( f, - " from input SignedPod {}:", - i / self.params.max_signed_pod_values + " from input SignedPod {} (id={}, type={:?}):", + index, id, pod_type )?; } - if (i >= offset_input_main_pods) + if self.params.max_input_recursive_pods > 0 + && (i >= offset_input_recursive_pods) && (i < offset_input_statements) - && ((i - offset_input_main_pods) % self.params.max_input_pods_public_statements + && ((i - offset_input_recursive_pods) + % self.params.max_input_pods_public_statements == 0) { + let index = (i - offset_input_recursive_pods) + / self.params.max_input_pods_public_statements; + let pod = &self.input_recursive_pods[index]; + let id = pod.id(); + let pod_type = pod.pod_type(); writeln!( f, - " from input MainPod {}:", - (i - offset_input_main_pods) / self.params.max_signed_pod_values + " from input recursive Pod {} (id={}, type={:?}):", + index, id, pod_type )?; } if i == offset_input_statements { @@ -134,6 +143,8 @@ struct Data { operations: Vec, statements: Vec, merkle_proofs: Vec, + input_signed_pods: Vec<(usize, PodId, serde_json::Value)>, + input_recursive_pods: Vec<(usize, Params, PodId, VDSet, serde_json::Value)>, } /// Inputs are sorted as: @@ -145,12 +156,12 @@ impl MockMainPod { fn offset_input_signed_pods() -> usize { 1 } - fn offset_input_main_pods(&self) -> usize { + fn offset_input_recursive_pods(&self) -> usize { Self::offset_input_signed_pods() + self.params.max_input_signed_pods * self.params.max_signed_pod_values } fn offset_input_statements(&self) -> usize { - self.offset_input_main_pods() + self.offset_input_recursive_pods() + self.params.max_input_recursive_pods * self.params.max_input_pods_public_statements } fn offset_public_statements(&self) -> usize { @@ -158,8 +169,6 @@ impl MockMainPod { } pub fn new(params: &Params, inputs: MainPodInputs) -> Result { - // TODO: Insert a new public statement of ValueOf with `key=KEY_TYPE, - // value=PodType::MockMainPod` let (statements, public_statements) = layout_statements(params, true, &inputs)?; // Extract Merkle proofs and pad. let merkle_proofs = extract_merkle_proofs(params, inputs.operations, inputs.statements)?; @@ -176,38 +185,100 @@ impl MockMainPod { // get the id out of the public statements let id: PodId = PodId(calculate_id(&public_statements, params)); + let pad_signed_pod: Box = Box::new(MockSignedPod::dummy()); + let input_signed_pods: Vec> = inputs + .signed_pods + .iter() + .map(|p| dyn_clone::clone_box(*p)) + .chain(iter::repeat_with(|| pad_signed_pod.clone())) + .take(params.max_input_signed_pods) + .collect(); + let pad_pod = MockEmptyPod::new_boxed(params, inputs.vd_set.clone()); + let input_recursive_pods: Vec> = inputs + .recursive_pods + .iter() + .map(|p| dyn_clone::clone_box(*p)) + .chain(iter::repeat_with(|| pad_pod.clone())) + .take(params.max_input_recursive_pods) + .collect(); Ok(Self { params: params.clone(), id, - vds_root: inputs.vds_set.root(), - // input_signed_pods, - // input_main_pods, - // input_statements, + vd_set: inputs.vd_set, + input_signed_pods, + input_recursive_pods, public_statements, statements, operations, - merkle_proofs, + merkle_proofs_containers: merkle_proofs, }) } - fn _verify(&self) -> Result<()> { - // 1. TODO: Verify input pods + pub fn params(&self) -> &Params { + &self.params + } +} + +impl Pod for MockMainPod { + fn params(&self) -> &Params { + &self.params + } + + fn verify(&self) -> Result<()> { + // 1. Verify input pods + for pod in &self.input_signed_pods { + pod.verify()?; + } + for pod in &self.input_recursive_pods { + pod.verify()?; + if pod.vd_set().root() != self.vd_set.root() { + return Err(Error::custom(format!( + "vds_root in input recursive pod doesn't match MockMainPod vds_root: {} != {}", + pod.vd_set().root(), + self.vd_set.root(), + ))); + } + let (pod_type, _) = pod.pod_type(); + // If the pod is not mock, check that its verifier data is in the set + if pod_type != PodType::MockMain as usize && pod_type != PodType::MockEmpty as usize { + let verifier_data = pod.verifier_data(); + let verifier_data_hash = hash_verifier_data(&verifier_data); + if !self.vd_set.contains(verifier_data_hash) { + return Err(Error::custom(format!( + "vds_root in input recursive pod not in the set: {} not in {}", + Hash(verifier_data_hash.elements), + self.vd_set.root(), + ))); + } + } + } let input_statement_offset = self.offset_input_statements(); // get the input_statements from the self.statements let input_statements = &self.statements[input_statement_offset..]; // 2. get the id out of the public statements, and ensure it is equal to self.id - let ids_match = self.id == PodId(calculate_id(&self.public_statements, &self.params)); + if self.id != PodId(calculate_id(&self.public_statements, &self.params)) { + return Err(Error::pod_id_invalid()); + } + // 4. Verify type // find a ValueOf statement from the public statements with key=KEY_TYPE and check that the // value is PodType::MockMainPod - let has_type_statement = self.public_statements.iter().any(|s| { - s.0 == Predicate::Native(NativePredicate::Equal) && { - if let [StatementArg::Key(AnchoredKey { pod_id, ref key }), StatementArg::Literal(_)] = &s.1[..2] { - pod_id == &SELF && key.hash() == hash_str(KEY_TYPE) + let type_statement = &self.public_statements[0]; + let type_statement_ok = type_statement.0 == Predicate::Native(NativePredicate::Equal) + && { + if let [StatementArg::Key(AnchoredKey { pod_id, ref key }), StatementArg::Literal(pod_type)] = + &type_statement.1[..2] + { + pod_id == &SELF + && key.hash() == hash_str(KEY_TYPE) + && *pod_type == Value::from(PodType::MockMain) } else { false } - }}); + }; + if !type_statement_ok { + return Err(Error::not_type_statement()); + } // 3. check that all `NewEntry` operations have unique keys // (no duplicates) let value_ofs_unique = input_statements @@ -225,7 +296,9 @@ impl MockMainPod { } }) .all_unique(); - // 4. TODO: Verify type + if !value_ofs_unique { + return Err(Error::repeated_value_of()); + } // 5. verify that all `input_statements` are correctly generated // by `self.operations` (where each operation can only access previous statements) @@ -236,40 +309,19 @@ impl MockMainPod { self.operations[i] .deref( &self.statements[..input_statement_offset + i], - &self.merkle_proofs, + &self.merkle_proofs_containers, ) .unwrap() .check_and_log(&self.params, &s.clone().try_into().unwrap()) }) .collect::, middleware::Error>>() .unwrap(); - if !ids_match { - return Err(Error::pod_id_invalid()); - } - if !has_type_statement { - return Err(Error::not_type_statement()); - } - if !value_ofs_unique { - return Err(Error::repeated_value_of()); - } if !statement_check.iter().all(|b| *b) { return Err(Error::statement_not_check()); } Ok(()) } - pub fn params(&self) -> &Params { - &self.params - } -} - -impl Pod for MockMainPod { - fn params(&self) -> &Params { - &self.params - } - fn verify(&self) -> Result<(), Box> { - Ok(self._verify()?) - } fn id(&self) -> PodId { self.id } @@ -285,11 +337,31 @@ impl Pod for MockMainPod { } fn serialize_data(&self) -> serde_json::Value { + let input_signed_pods = self + .input_signed_pods + .iter() + .map(|p| (p.pod_type().0, p.id(), p.serialize_data())) + .collect(); + let input_recursive_pods = self + .input_recursive_pods + .iter() + .map(|p| { + ( + p.pod_type().0, + p.params().clone(), + p.id(), + p.vd_set().clone(), + p.serialize_data(), + ) + }) + .collect(); serde_json::to_value(Data { public_statements: self.public_statements.clone(), operations: self.operations.clone(), statements: self.statements.clone(), - merkle_proofs: self.merkle_proofs.clone(), + merkle_proofs: self.merkle_proofs_containers.clone(), + input_signed_pods, + input_recursive_pods, }) .expect("serialization to json") } @@ -302,8 +374,8 @@ impl RecursivePod for MockMainPod { fn proof(&self) -> Proof { panic!("MockMainPod can't be verified in a recursive MainPod circuit"); } - fn vds_root(&self) -> Hash { - self.vds_root + fn vd_set(&self) -> &VDSet { + &self.vd_set } // MockMainPods include some internal private state which is necessary // for verification. In non-mock Pods, this state will not be necessary, @@ -311,23 +383,37 @@ impl RecursivePod for MockMainPod { fn deserialize_data( params: Params, data: serde_json::Value, - vds_root: Hash, + vd_set: VDSet, id: PodId, - ) -> Result, Box> { + ) -> Result> { let Data { public_statements, operations, statements, merkle_proofs, + input_signed_pods, + input_recursive_pods, } = serde_json::from_value(data)?; + let input_signed_pods = input_signed_pods + .into_iter() + .map(|(pod_type, id, data)| deserialize_signed_pod(pod_type, id, data)) + .collect::>>()?; + let input_recursive_pods = input_recursive_pods + .into_iter() + .map(|(pod_type, params, id, vd_set, data)| { + deserialize_pod(pod_type, params, id, vd_set, data) + }) + .collect::>>()?; Ok(Box::new(Self { params, id, - vds_root, + vd_set, + input_signed_pods, + input_recursive_pods, public_statements, operations, statements, - merkle_proofs, + merkle_proofs_containers: merkle_proofs, })) } } @@ -341,16 +427,16 @@ pub mod tests { backends::plonky2::mock::signedpod::MockSigner, examples::{ great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder, - zu_kyc_sign_pod_builders, + zu_kyc_sign_pod_builders, MOCK_VD_SET, }, frontend, - middleware::{self, DEFAULT_VD_SET}, + middleware::{self}, }; #[test] fn test_mock_main_zu_kyc() -> frontend::Result<()> { let params = middleware::Params::default(); - let vd_set = &*DEFAULT_VD_SET; + let vd_set = &*MOCK_VD_SET; let (gov_id_builder, pay_stub_builder, sanction_list_builder) = zu_kyc_sign_pod_builders(¶ms); let mut signer = MockSigner { @@ -381,9 +467,7 @@ pub mod tests { println!("{:#}", pod); - pod.verify()?; // TODO - // println!("id: {}", pod.id()); - // println!("pub_statements: {:?}", pod.pub_statements()); + pod.verify()?; Ok(()) } diff --git a/src/backends/plonky2/mock/signedpod.rs b/src/backends/plonky2/mock/signedpod.rs index d1d088a..c42f6e0 100644 --- a/src/backends/plonky2/mock/signedpod.rs +++ b/src/backends/plonky2/mock/signedpod.rs @@ -10,9 +10,8 @@ use crate::{ }, constants::MAX_DEPTH, middleware::{ - containers::Dictionary, hash_str, serialization::ordered_map, AnchoredKey, DynError, Key, - Params, Pod, PodId, PodSigner, PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE, - SELF, + containers::Dictionary, hash_str, serialization::ordered_map, AnchoredKey, Key, Params, + Pod, PodId, PodSigner, PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE, SELF, }, }; @@ -41,11 +40,7 @@ impl MockSigner { } impl PodSigner for MockSigner { - fn sign( - &mut self, - params: &Params, - kvs: &HashMap, - ) -> Result, Box> { + fn sign(&mut self, params: &Params, kvs: &HashMap) -> Result> { Ok(self._sign(params, kvs).map(Box::new)?) } } @@ -69,7 +64,30 @@ impl MockSignedPod { self.signature.clone() } - fn _verify(&self) -> Result<()> { + pub(crate) fn deserialize(id: PodId, data: serde_json::Value) -> Result> { + let data: Data = serde_json::from_value(data)?; + Ok(Box::new(Self { + id, + signature: data.signature, + kvs: data.kvs, + })) + } + /// Generate a valid MockSignedPod with a public deterministic public key and no other + /// key-values than the default ones. This is used for padding. + pub fn dummy() -> MockSignedPod { + MockSigner { + pk: "dummy".to_string(), + } + ._sign(&Params::default(), &HashMap::new()) + .expect("valid") + } +} + +impl Pod for MockSignedPod { + fn params(&self) -> &Params { + panic!("MockSignedPod doesn't have params"); + } + fn verify(&self) -> Result<()> { // 1. Verify id let mt = MerkleTree::new( MAX_DEPTH, @@ -112,33 +130,6 @@ impl MockSignedPod { Ok(()) } - pub(crate) fn deserialize(id: PodId, data: serde_json::Value) -> Result> { - let data: Data = serde_json::from_value(data)?; - Ok(Box::new(Self { - id, - signature: data.signature, - kvs: data.kvs, - })) - } - /// Generate a valid MockSignedPod with a public deterministic public key and no other - /// key-values than the default ones. This is used for padding. - pub fn dummy() -> MockSignedPod { - MockSigner { - pk: "dummy".to_string(), - } - ._sign(&Params::default(), &HashMap::new()) - .expect("valid") - } -} - -impl Pod for MockSignedPod { - fn params(&self) -> &Params { - panic!("MockSignedPod doesn't have params"); - } - fn verify(&self) -> Result<(), Box> { - Ok(self._verify()?) - } - fn id(&self) -> PodId { self.id } @@ -195,7 +186,7 @@ pub mod tests { .downcast::() .unwrap(); - pod._verify()?; + pod.verify()?; println!("id: {}", pod.id()); println!("kvs: {:?}", pod.kvs()); diff --git a/src/backends/plonky2/recursion/circuit.rs b/src/backends/plonky2/recursion/circuit.rs index 72a784f..0126510 100644 --- a/src/backends/plonky2/recursion/circuit.rs +++ b/src/backends/plonky2/recursion/circuit.rs @@ -517,7 +517,7 @@ fn hash_verifier_data_gadget( } // compatible with hash_verifier_data_gadget. -pub(crate) fn hash_verifier_data(verifier_only_data: &VerifierOnlyCircuitData) -> HashOut { +pub fn hash_verifier_data(verifier_only_data: &VerifierOnlyCircuitData) -> HashOut { let f: Vec = [ verifier_only_data.circuit_digest.elements.to_vec(), verifier_only_data diff --git a/src/backends/plonky2/recursion/mod.rs b/src/backends/plonky2/recursion/mod.rs index fcf679b..e9492a7 100644 --- a/src/backends/plonky2/recursion/mod.rs +++ b/src/backends/plonky2/recursion/mod.rs @@ -1,5 +1,5 @@ pub mod circuit; pub use circuit::{ - common_data_for_recursion, new_params, new_params_padded, pad_circuit, InnerCircuit, - RecursiveCircuit, RecursiveParams, VerifiedProofTarget, + common_data_for_recursion, hash_verifier_data, new_params, new_params_padded, pad_circuit, + InnerCircuit, RecursiveCircuit, RecursiveParams, VerifiedProofTarget, }; diff --git a/src/backends/plonky2/signedpod.rs b/src/backends/plonky2/signedpod.rs index 9937548..cedb14b 100644 --- a/src/backends/plonky2/signedpod.rs +++ b/src/backends/plonky2/signedpod.rs @@ -20,8 +20,8 @@ use crate::{ }, constants::MAX_DEPTH, middleware::{ - containers::Dictionary, AnchoredKey, DynError, Hash, Key, Params, Pod, PodId, PodSigner, - PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE, SELF, + containers::Dictionary, AnchoredKey, Hash, Key, Params, Pod, PodId, PodSigner, PodType, + RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE, SELF, }, timed, }; @@ -62,11 +62,7 @@ impl Signer { } impl PodSigner for Signer { - fn sign( - &mut self, - params: &Params, - kvs: &HashMap, - ) -> Result, Box> { + fn sign(&mut self, params: &Params, kvs: &HashMap) -> Result> { Ok(self._sign(params, kvs).map(Box::new)?) } } @@ -96,44 +92,6 @@ fn dummy() -> SignedPod { } impl SignedPod { - fn _verify(&self) -> Result<()> { - // 1. Verify type - let value_at_type = self.dict.get(&Key::from(KEY_TYPE))?; - if Value::from(PodType::Signed) != *value_at_type { - return Err(Error::type_not_equal( - PodType::Signed, - value_at_type.clone(), - )); - } - - // 2. Verify id - let mt = MerkleTree::new( - MAX_DEPTH, - &self - .dict - .kvs() - .iter() - .map(|(k, v)| (k.raw(), v.raw())) - .collect::>(), - )?; - let id = PodId(mt.root()); - if id != self.id { - return Err(Error::id_not_equal(self.id, id)); - } - - // 3. Verify signature - let embedded_pk_value = self.dict.get(&Key::from(KEY_SIGNER))?; - let pk = self.signer; - let pk_value = Value::from(pk); - if &pk_value != embedded_pk_value { - return Err(Error::signer_not_equal(embedded_pk_value.clone(), pk_value)); - } - self.signature - .verify(pk, RawValue::from(id.0)) - .then_some(()) - .ok_or(Error::custom("Invalid signature!".into())) - } - pub(crate) fn deserialize(id: PodId, data: serde_json::Value) -> Result> { let data: Data = serde_json::from_value(data)?; let signer_bytes = deserialize_bytes(&data.signer)?; @@ -172,8 +130,42 @@ impl Pod for SignedPod { fn params(&self) -> &Params { panic!("SignedPod doesn't have params"); } - fn verify(&self) -> Result<(), Box> { - Ok(self._verify().map_err(Box::new)?) + fn verify(&self) -> Result<()> { + // 1. Verify type + let value_at_type = self.dict.get(&Key::from(KEY_TYPE))?; + if Value::from(PodType::Signed) != *value_at_type { + return Err(Error::type_not_equal( + PodType::Signed, + value_at_type.clone(), + )); + } + + // 2. Verify id + let mt = MerkleTree::new( + MAX_DEPTH, + &self + .dict + .kvs() + .iter() + .map(|(k, v)| (k.raw(), v.raw())) + .collect::>(), + )?; + let id = PodId(mt.root()); + if id != self.id { + return Err(Error::id_not_equal(self.id, id)); + } + + // 3. Verify signature + let embedded_pk_value = self.dict.get(&Key::from(KEY_SIGNER))?; + let pk = self.signer; + let pk_value = Value::from(pk); + if &pk_value != embedded_pk_value { + return Err(Error::signer_not_equal(embedded_pk_value.clone(), pk_value)); + } + self.signature + .verify(pk, RawValue::from(id.0)) + .then_some(()) + .ok_or(Error::custom("Invalid signature!".into())) } fn id(&self) -> PodId { @@ -234,7 +226,7 @@ pub mod tests { let pod = pod.sign(&mut signer).unwrap(); let pod = (pod.pod as Box).downcast::().unwrap(); - pod._verify()?; + pod.verify()?; println!("id: {}", pod.id()); println!("kvs: {:?}", pod.kvs()); diff --git a/src/frontend/error.rs b/src/frontend/error.rs index 2341300..e38b740 100644 --- a/src/frontend/error.rs +++ b/src/frontend/error.rs @@ -1,6 +1,6 @@ use std::{backtrace::Backtrace, fmt::Debug}; -use crate::middleware::{DynError, Statement, StatementTmpl, Value}; +use crate::middleware::{BackendError, Statement, StatementTmpl, Value}; pub type Result = core::result::Result; @@ -41,7 +41,7 @@ pub enum Error { #[error(transparent)] Infallible(#[from] std::convert::Infallible), #[error(transparent)] - Backend(#[from] Box), + Backend(#[from] BackendError), #[error(transparent)] Middleware(#[from] crate::middleware::Error), } diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 090134f..4111854 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -564,7 +564,7 @@ impl MainPodBuilder { statements: &statements, operations: &operations, public_statements: &public_statements, - vds_set: self.vd_set.clone(), + vd_set: self.vd_set.clone(), }; let pod = prover.prove(&self.params, &self.vd_set, inputs)?; diff --git a/src/frontend/serialization.rs b/src/frontend/serialization.rs index a7bb9b1..fa3cd63 100644 --- a/src/frontend/serialization.rs +++ b/src/frontend/serialization.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use super::Error; use crate::{ frontend::{MainPod, SignedPod}, - middleware::{deserialize_pod, deserialize_signed_pod, Hash, Params, PodId}, + middleware::{deserialize_pod, deserialize_signed_pod, Params, PodId, VDSet}, }; #[derive(Serialize, Deserialize, JsonSchema)] @@ -29,7 +29,7 @@ pub struct SerializedMainPod { params: Params, pod_type: (usize, String), id: PodId, - vds_root: Hash, + vd_set: VDSet, data: serde_json::Value, } @@ -62,7 +62,7 @@ impl From for SerializedMainPod { SerializedMainPod { pod_type: (pod_type, pod_type_name_str.to_string()), id: pod.id(), - vds_root: pod.pod.vds_root(), + vd_set: pod.pod.vd_set().clone(), params: pod.params.clone(), data, } @@ -77,7 +77,7 @@ impl TryFrom for MainPod { serialized.pod_type.0, serialized.params.clone(), serialized.id, - serialized.vds_root, + serialized.vd_set, serialized.data, )?; let public_statements = pod.pub_statements(); diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 8576fa5..d921dc0 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -774,11 +774,9 @@ pub fn normalize_statement(statement: &Statement, self_id: PodId) -> Statement { Statement::from_args(predicate, args).expect("statement was valid before normalization") } -pub type DynError = dyn std::error::Error + Send + Sync; - pub trait Pod: fmt::Debug + DynClone + Any { fn params(&self) -> &Params; - fn verify(&self) -> Result<(), Box>; + fn verify(&self) -> Result<(), BackendError>; fn id(&self) -> PodId; /// Return a uuid of the pod type and its name. The name is only used as metadata. fn pod_type(&self) -> (usize, &'static str); @@ -807,18 +805,6 @@ pub trait Pod: fmt::Debug + DynClone + Any { }) .collect() } - - // Front-end Pods keep references to middleware Pods. Most of the - // middleware data can be derived directly from front-end data, but the - // "proof" data is only created at the point of proving/signing, and - // cannot be reconstructed. As such, we need to serialize it whenever - // we serialize a front-end Pod. Since the front-end does not understand - // the implementation details of the middleware, this method allows the - // middleware to provide some serialized data that can be used to - // reconstruct the proof. - // It is an important principle that this data is opaque to the front-end - // and any third-party code. - // fn serialized_proof(&self) -> String; } // impl Clone for Box @@ -830,15 +816,15 @@ dyn_clone::clone_trait_object!(Pod); pub trait RecursivePod: Pod { fn verifier_data(&self) -> VerifierOnlyCircuitData; fn proof(&self) -> Proof; - fn vds_root(&self) -> Hash; + fn vd_set(&self) -> &VDSet; /// Returns the deserialized RecursivePod. fn deserialize_data( params: Params, data: serde_json::Value, - vds_root: Hash, + vd_set: VDSet, id: PodId, - ) -> Result, Box> + ) -> Result, BackendError> where Self: Sized; } @@ -851,7 +837,7 @@ pub trait PodSigner { &mut self, params: &Params, kvs: &HashMap, - ) -> Result, Box>; + ) -> Result, BackendError>; } #[derive(Debug)] @@ -863,7 +849,7 @@ pub struct MainPodInputs<'a> { /// Statements that need to be made public (they can come from input pods or input /// statements) pub public_statements: &'a [Statement], - pub vds_set: VDSet, + pub vd_set: VDSet, } pub trait PodProver { @@ -872,7 +858,7 @@ pub trait PodProver { params: &Params, vd_set: &VDSet, inputs: MainPodInputs, - ) -> Result, Box>; + ) -> Result, BackendError>; } pub trait ToFields { diff --git a/src/middleware/pod_deserialization.rs b/src/middleware/pod_deserialization.rs index 76a70c0..ee936da 100644 --- a/src/middleware/pod_deserialization.rs +++ b/src/middleware/pod_deserialization.rs @@ -3,14 +3,14 @@ use std::{ sync::{LazyLock, Mutex}, }; -use crate::middleware::{DynError, Error, Hash, Params, Pod, PodId, PodType, RecursivePod, Result}; +use crate::middleware::{BackendError, Params, Pod, PodId, PodType, RecursivePod, Result, VDSet}; type DeserializeFn = fn( params: Params, data: serde_json::Value, - vds_root: Hash, + vd_set: VDSet, id: PodId, -) -> Result, Box>; +) -> Result, BackendError>; static DESERIALIZERS: LazyLock>> = LazyLock::new(backend::deserializers_default); @@ -26,28 +26,27 @@ pub fn deserialize_pod( pod_type: usize, params: Params, id: PodId, - vds_root: Hash, + vd_set: VDSet, data: serde_json::Value, -) -> Result> { +) -> Result, BackendError> { let deserialize_fn: DeserializeFn = *DESERIALIZERS .lock() .unwrap() .get(&pod_type) - .ok_or(Error::custom(format!( + .ok_or(BackendError::custom(format!( "pod deserializer for pod_type={} not registered. See https://github.com/0xPARC/pod2/wiki/PodType for pod type assignments.", pod_type )))?; - deserialize_fn(params, data, vds_root, id) - .map_err(|e| Error::custom(format!("deserialize error: {:?}", e))) + deserialize_fn(params, data, vd_set, id) } pub fn deserialize_signed_pod( pod_type: usize, id: PodId, data: serde_json::Value, -) -> Result> { +) -> Result, BackendError> { backend::deserialize_signed_pod(pod_type, id, data) } @@ -74,15 +73,13 @@ mod backend { pod_type: usize, id: PodId, data: serde_json::Value, - ) -> Result> { + ) -> Result, BackendError> { if pod_type == PodType::MockSigned as usize { MockSignedPod::deserialize(id, data) - .map_err(|e| Error::custom(format!("deserialize error: {:?}", e))) } else if pod_type == PodType::Signed as usize { SignedPod::deserialize(id, data) - .map_err(|e| Error::custom(format!("deserialize error: {:?}", e))) } else { - Err(Error::custom(format!( + Err(BackendError::custom(format!( "unexpected pod_type={} for deserialize_signed_pod", pod_type )))