Add verifier-datas tree (set) & in-circuit verification (#274)

* containers: add method to create new {Dict,Set,Array} with custom max_depth

* add vds_tree computation, update tree circuit interface

* add VDTree struct, add DEFAULT_VD_TREE, integrate it with MainPod,EmptyPod,frontend,etc.

* adapt frontend/serialization tests to new containers field (max_depth)

* adapt interfaces to allow using custom vd_tree in frontend & backend constructors

* rename VDTree to VDSet (and derivate namings too)

* containers 'new' always with param 'max_depth', use params.max_depth_mt_containers instead of the global constant MAX_DEPTH

* adapt after rebasing the branch to main latest changes

* apply review suggestions from @ed255

* use emptypod vd_mt_proofs (using vd_set as circuit input), merge the two existing set_targets methods of MainPodVerifyTarget

* document VDSet & vds_root
This commit is contained in:
arnaucube 2025-06-11 13:08:39 +02:00 committed by GitHub
parent 6258e52e1a
commit 273d803ebd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 486 additions and 259 deletions

View file

@ -36,3 +36,91 @@ pub type VerifierCircuitData = circuit_data::VerifierCircuitData<F, C, D>;
pub type CircuitBuilder = circuit_builder::CircuitBuilder<F, D>; pub type CircuitBuilder = circuit_builder::CircuitBuilder<F, D>;
pub type Proof = proof::Proof<F, C, D>; pub type Proof = proof::Proof<F, C, D>;
pub type ProofWithPublicInputs = proof::ProofWithPublicInputs<F, C, D>; pub type ProofWithPublicInputs = proof::ProofWithPublicInputs<F, C, D>;
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,
DEFAULT_PARAMS, STANDARD_REC_MAIN_POD_CIRCUIT_DATA,
},
middleware::{containers::Array, Hash, RawValue, Result, Value},
};
pub static DEFAULT_VD_SET: LazyLock<VDSet> = LazyLock::new(|| {
let params = &*DEFAULT_PARAMS;
let vds = vec![
STANDARD_REC_MAIN_POD_CIRCUIT_DATA.verifier_only.clone(),
STANDARD_EMPTY_POD_DATA.1.verifier_only.clone(),
];
VDSet::new(params.max_depth_mt_vds, &vds).unwrap()
});
/// VDSet is the set of the allowed verifier_data hashes. When proving a
/// MainPod, the circuit will enforce that all the used verifier_datas for
/// 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)]
pub struct VDSet {
root: Hash,
// (verifier_data, merkleproof)
proofs_map: HashMap<HashOut<F>, MerkleClaimAndProof>,
}
impl VDSet {
/// builds the verifier_datas tree, and returns the root and the proofs
pub fn new(tree_depth: usize, vds: &[VerifierOnlyCircuitData]) -> Result<Self> {
// first of all, sort the vds, so that each set of verifier_datas gets
// the same root
let vds: Vec<&VerifierOnlyCircuitData> = vds
.iter()
.sorted_by_key(|vd| RawValue(vd.circuit_digest.elements))
.collect::<Vec<_>>();
let array = Array::new(
tree_depth,
vds.iter()
.map(|vd| Value::from(RawValue(vd.circuit_digest.elements)))
.collect(),
)?;
let root = array.commitment();
let mut proofs_map = HashMap::<HashOut<F>, MerkleClaimAndProof>::new();
for (i, vd) in vds.iter().enumerate() {
let (value, proof) = array.prove(i)?;
let p = MerkleClaimAndProof {
root,
key: RawValue::from(i as i64),
value: value.raw(),
proof,
};
proofs_map.insert(vd.circuit_digest, p);
}
Ok(Self { root, proofs_map })
}
pub fn root(&self) -> Hash {
self.root
}
/// returns the vector of merkle proofs corresponding to the given verifier_datas
pub fn get_vds_proofs(
&self,
vds: &[VerifierOnlyCircuitData],
) -> Result<Vec<MerkleClaimAndProof>> {
let mut proofs: Vec<MerkleClaimAndProof> = vec![];
for vd in vds {
let p =
self.proofs_map
.get(&vd.circuit_digest)
.ok_or(crate::middleware::Error::custom(
"verifier_data not found in VDSet".to_string(),
))?;
proofs.push(p.clone());
}
Ok(proofs)
}
}

View file

@ -40,7 +40,7 @@ use crate::{
pub const CODE_SIZE: usize = HASH_SIZE + 2; pub const CODE_SIZE: usize = HASH_SIZE + 2;
const NUM_BITS: usize = 32; const NUM_BITS: usize = 32;
#[derive(Copy, Clone)] #[derive(Copy, Clone, Debug)]
pub struct ValueTarget { pub struct ValueTarget {
pub elements: [Target; VALUE_SIZE], pub elements: [Target; VALUE_SIZE],
} }

View file

@ -17,7 +17,7 @@ use plonky2::{
use crate::{ use crate::{
backends::plonky2::{ backends::plonky2::{
basetypes::CircuitBuilder, basetypes::{CircuitBuilder, VDSet},
circuits::{ circuits::{
common::{ common::{
CircuitBuilderPod, CustomPredicateBatchTarget, CustomPredicateEntryTarget, CircuitBuilderPod, CustomPredicateBatchTarget, CustomPredicateEntryTarget,
@ -28,7 +28,7 @@ use crate::{
}, },
signedpod::{SignedPodVerifyGadget, SignedPodVerifyTarget}, signedpod::{SignedPodVerifyGadget, SignedPodVerifyTarget},
}, },
emptypod::EmptyPod, emptypod::{EmptyPod, STANDARD_EMPTY_POD_DATA},
error::Result, error::Result,
mainpod::{self, pad_statement}, mainpod::{self, pad_statement},
primitives::merkletree::{ primitives::merkletree::{
@ -39,10 +39,9 @@ use crate::{
}, },
measure_gates_begin, measure_gates_end, measure_gates_begin, measure_gates_end,
middleware::{ middleware::{
AnchoredKey, CustomPredicate, CustomPredicateBatch, CustomPredicateRef, Hash, AnchoredKey, CustomPredicate, CustomPredicateBatch, CustomPredicateRef, NativeOperation,
NativeOperation, NativePredicate, Params, PodType, PredicatePrefix, Statement, NativePredicate, Params, PodType, PredicatePrefix, Statement, StatementArg, ToFields,
StatementArg, ToFields, Value, WildcardValue, EMPTY_VALUE, F, HASH_SIZE, KEY_TYPE, SELF, Value, WildcardValue, EMPTY_VALUE, F, HASH_SIZE, KEY_TYPE, SELF, VALUE_SIZE,
VALUE_SIZE,
}, },
}; };
@ -1220,9 +1219,31 @@ impl MainPodVerifyGadget {
} }
let vds_root = builder.add_virtual_hash(); let vds_root = builder.add_virtual_hash();
// TODO: verify that all input pod proofs use verifier data from the public input VD array
// This requires merkle proofs // verify that all input pod proofs use verifier data from the public input VD array This
// https://github.com/0xPARC/pod2/issues/250 // requires merkle proofs
let mut vd_mt_proofs: Vec<MerkleClaimAndProofTarget> = vec![];
for verified_proof in verified_proofs {
// add target for the vd_mt_proof
let vd_mt_proof = MerkleProofGadget {
max_depth: params.max_depth_mt_vds,
}
.eval(builder);
// ensure that mt_proof is enabled
let true_targ = builder._true();
builder.connect(vd_mt_proof.enabled.target, true_targ.target);
// connect the vd_mt_proof's root to the actual vds_root, to ensure that the mt proof
// verifies against the vds_root
builder.connect_hashes(vds_root, vd_mt_proof.root);
// connect vd_mt_proof's value with the verified_proof.verifier_data_hash
builder.connect_hashes(
verified_proof.verifier_data_hash,
HashOutTarget::from_vec(vd_mt_proof.value.elements.to_vec()),
);
vd_mt_proofs.push(vd_mt_proof);
}
// Verify that VD array that input pod uses is the same we use now. // Verify that VD array that input pod uses is the same we use now.
for verified_proof in verified_proofs { for verified_proof in verified_proofs {
@ -1247,11 +1268,11 @@ impl MainPodVerifyGadget {
// Add Merkle claim/proof targets // Add Merkle claim/proof targets
let mp_gadget = MerkleProofGadget { let mp_gadget = MerkleProofGadget {
max_depth: params.max_depth_mt_gadget, max_depth: params.max_depth_mt_containers,
}; };
let merkle_proofs: Vec<_> = (0..params.max_merkle_proofs) let merkle_proofs: Vec<_> = (0..params.max_merkle_proofs_containers)
.map(|_| mp_gadget.eval(builder)) .map(|_| mp_gadget.eval(builder))
.collect::<Result<_>>()?; .collect();
let merkle_claims: Vec<_> = merkle_proofs let merkle_claims: Vec<_> = merkle_proofs
.clone() .clone()
.into_iter() .into_iter()
@ -1310,6 +1331,7 @@ impl MainPodVerifyGadget {
Ok(MainPodVerifyTarget { Ok(MainPodVerifyTarget {
params: params.clone(), params: params.clone(),
vds_root, vds_root,
vd_mt_proofs,
id, id,
signed_pods, signed_pods,
input_pods_self_statements, input_pods_self_statements,
@ -1325,6 +1347,7 @@ impl MainPodVerifyGadget {
pub struct MainPodVerifyTarget { pub struct MainPodVerifyTarget {
params: Params, params: Params,
vds_root: HashOutTarget, vds_root: HashOutTarget,
vd_mt_proofs: Vec<MerkleClaimAndProofTarget>,
id: HashOutTarget, id: HashOutTarget,
signed_pods: Vec<SignedPodVerifyTarget>, signed_pods: Vec<SignedPodVerifyTarget>,
input_pods_self_statements: Vec<Vec<StatementTarget>>, input_pods_self_statements: Vec<Vec<StatementTarget>>,
@ -1344,7 +1367,11 @@ pub struct CustomPredicateVerification {
} }
pub struct MainPodVerifyInput { pub struct MainPodVerifyInput {
pub vds_root: Hash, pub vds_set: VDSet,
// field containing the `vd_mt_proofs` aside from the `vds_set`, because
// inide the MainPodVerifyTarget circuit, since it is the InnerCircuit for
// the RecursiveCircuit, we don't have access to the used verifier_datas.
pub vd_mt_proofs: Vec<MerkleClaimAndProof>,
pub signed_pods: Vec<SignedPod>, pub signed_pods: Vec<SignedPod>,
pub recursive_pods_pub_self_statements: Vec<Vec<Statement>>, pub recursive_pods_pub_self_statements: Vec<Vec<Statement>>,
pub statements: Vec<mainpod::Statement>, pub statements: Vec<mainpod::Statement>,
@ -1378,13 +1405,58 @@ fn set_targets_input_pods_self_statements(
Ok(()) Ok(())
} }
impl MainPodVerifyTarget { pub struct MainPodVerifyCircuit {
pub fn set_targets( pub params: Params,
}
// TODO: Remove this type and implement it's logic directly in `impl InnerCircuit for MainPodVerifyTarget`
impl MainPodVerifyCircuit {
pub fn eval(
&self, &self,
pw: &mut PartialWitness<F>, builder: &mut CircuitBuilder,
input: &MainPodVerifyInput, verified_proofs: &[VerifiedProofTarget],
) -> Result<()> { ) -> Result<MainPodVerifyTarget> {
pw.set_target_arr(&self.vds_root.elements, &input.vds_root.0)?; let main_pod = MainPodVerifyGadget {
params: self.params.clone(),
}
.eval(builder, verified_proofs)?;
builder.register_public_inputs(&main_pod.id.elements);
builder.register_public_inputs(&main_pod.vds_root.elements);
Ok(main_pod)
}
}
impl InnerCircuit for MainPodVerifyTarget {
type Input = MainPodVerifyInput;
type Params = Params;
fn build(
builder: &mut CircuitBuilder,
params: &Self::Params,
verified_proofs: &[VerifiedProofTarget],
) -> Result<Self> {
MainPodVerifyCircuit {
params: params.clone(),
}
.eval(builder, verified_proofs)
}
/// assigns the values to the targets
fn set_targets(&self, pw: &mut PartialWitness<F>, input: &Self::Input) -> Result<()> {
let vds_root = input.vds_set.root();
pw.set_target_arr(&self.vds_root.elements, &vds_root.0)?;
for (i, vd_mt_proof) in input.vd_mt_proofs.iter().enumerate() {
self.vd_mt_proofs[i].set_targets(pw, true, vd_mt_proof)?;
}
// the rest of vd_mt_proofs set them to the empty_pod vd_mt_proof
let vd_emptypod_mt_proof = input
.vds_set
.get_vds_proofs(&[STANDARD_EMPTY_POD_DATA.1.verifier_only.clone()])?;
let vd_emptypod_mt_proof = vd_emptypod_mt_proof[0].clone();
for i in input.vd_mt_proofs.len()..self.vd_mt_proofs.len() {
self.vd_mt_proofs[i].set_targets(pw, true, &vd_emptypod_mt_proof)?;
}
assert!(input.signed_pods.len() <= self.params.max_input_signed_pods); assert!(input.signed_pods.len() <= self.params.max_input_signed_pods);
for (i, signed_pod) in input.signed_pods.iter().enumerate() { for (i, signed_pod) in input.signed_pods.iter().enumerate() {
@ -1414,7 +1486,7 @@ impl MainPodVerifyTarget {
} }
// Padding // Padding
if input.recursive_pods_pub_self_statements.len() != self.params.max_input_recursive_pods { if input.recursive_pods_pub_self_statements.len() != self.params.max_input_recursive_pods {
let empty_pod = EmptyPod::new_boxed(&self.params, input.vds_root); let empty_pod = EmptyPod::new_boxed(&self.params, input.vds_set.root());
let empty_pod_statements = empty_pod.pub_statements(); let empty_pod_statements = empty_pod.pub_statements();
for i in for i in
input.recursive_pods_pub_self_statements.len()..self.params.max_input_recursive_pods input.recursive_pods_pub_self_statements.len()..self.params.max_input_recursive_pods
@ -1434,13 +1506,13 @@ impl MainPodVerifyTarget {
self.operations[i].set_targets(pw, &self.params, op)?; self.operations[i].set_targets(pw, &self.params, op)?;
} }
assert!(input.merkle_proofs.len() <= self.params.max_merkle_proofs); assert!(input.merkle_proofs.len() <= self.params.max_merkle_proofs_containers);
for (i, mp) in input.merkle_proofs.iter().enumerate() { for (i, mp) in input.merkle_proofs.iter().enumerate() {
self.merkle_proofs[i].set_targets(pw, true, mp)?; self.merkle_proofs[i].set_targets(pw, true, mp)?;
} }
// Padding // Padding
let pad_mp = MerkleClaimAndProof::empty(); let pad_mp = MerkleClaimAndProof::empty();
for i in input.merkle_proofs.len()..self.params.max_merkle_proofs { for i in input.merkle_proofs.len()..self.params.max_merkle_proofs_containers {
self.merkle_proofs[i].set_targets(pw, false, &pad_mp)?; self.merkle_proofs[i].set_targets(pw, false, &pad_mp)?;
} }
@ -1487,48 +1559,6 @@ impl MainPodVerifyTarget {
} }
} }
pub struct MainPodVerifyCircuit {
pub params: Params,
}
// TODO: Remove this type and implement it's logic directly in `impl InnerCircuit for MainPodVerifyTarget`
impl MainPodVerifyCircuit {
pub fn eval(
&self,
builder: &mut CircuitBuilder,
verified_proofs: &[VerifiedProofTarget],
) -> Result<MainPodVerifyTarget> {
let main_pod = MainPodVerifyGadget {
params: self.params.clone(),
}
.eval(builder, verified_proofs)?;
builder.register_public_inputs(&main_pod.id.elements);
builder.register_public_inputs(&main_pod.vds_root.elements);
Ok(main_pod)
}
}
impl InnerCircuit for MainPodVerifyTarget {
type Input = MainPodVerifyInput;
type Params = Params;
fn build(
builder: &mut CircuitBuilder,
params: &Self::Params,
verified_proofs: &[VerifiedProofTarget],
) -> Result<Self> {
MainPodVerifyCircuit {
params: params.clone(),
}
.eval(builder, verified_proofs)
}
/// assigns the values to the targets
fn set_targets(&self, pw: &mut PartialWitness<F>, input: &Self::Input) -> Result<()> {
self.set_targets(pw, input)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{iter, ops::Not}; use std::{iter, ops::Not};
@ -1567,7 +1597,7 @@ mod tests {
..Default::default() ..Default::default()
}; };
let mp_gadget = MerkleProofGadget { let mp_gadget = MerkleProofGadget {
max_depth: params.max_depth_mt_gadget, max_depth: params.max_depth_mt_containers,
}; };
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
@ -1581,7 +1611,7 @@ mod tests {
let merkle_proofs_target: Vec<_> = merkle_proofs let merkle_proofs_target: Vec<_> = merkle_proofs
.iter() .iter()
.map(|_| mp_gadget.eval(&mut builder)) .map(|_| mp_gadget.eval(&mut builder))
.collect::<Result<_>>()?; .collect();
let merkle_claims_target: Vec<_> = merkle_proofs_target let merkle_claims_target: Vec<_> = merkle_proofs_target
.clone() .clone()
.into_iter() .into_iter()
@ -2360,7 +2390,7 @@ mod tests {
] ]
.into_iter() .into_iter()
.collect(); .collect();
let mt = MerkleTree::new(params.max_depth_mt_gadget, &kvs)?; let mt = MerkleTree::new(params.max_depth_mt_containers, &kvs)?;
let root = Value::from(mt.root()); let root = Value::from(mt.root());
let root_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "merkle root")); let root_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "merkle root"));
@ -2400,7 +2430,7 @@ mod tests {
] ]
.into_iter() .into_iter()
.collect(); .collect();
let mt = MerkleTree::new(params.max_depth_mt_gadget, &kvs)?; let mt = MerkleTree::new(params.max_depth_mt_containers, &kvs)?;
let root = Value::from(mt.root()); let root = Value::from(mt.root());
let root_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "merkle root")); let root_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "merkle root"));

View file

@ -41,7 +41,7 @@ impl SignedPodVerifyGadget {
let mut mt_proofs = Vec::new(); let mut mt_proofs = Vec::new();
for _ in 0..self.params.max_signed_pod_values { for _ in 0..self.params.max_signed_pod_values {
let mt_proof = MerkleProofExistenceGadget { let mt_proof = MerkleProofExistenceGadget {
max_depth: self.params.max_depth_mt_gadget, max_depth: self.params.max_depth_mt_containers,
} }
.eval(builder)?; .eval(builder)?;
builder.connect_hashes(id, mt_proof.root); builder.connect_hashes(id, mt_proof.root);

View file

@ -27,7 +27,7 @@ use crate::{
}, },
middleware::{ middleware::{
self, AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, self, AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement,
ToFields, Value, VerifierOnlyCircuitData, EMPTY_HASH, F, HASH_SIZE, KEY_TYPE, SELF, ToFields, Value, VerifierOnlyCircuitData, F, HASH_SIZE, KEY_TYPE, SELF,
}, },
timed, timed,
}; };
@ -80,7 +80,7 @@ pub struct EmptyPod {
type CircuitData = circuit_data::CircuitData<F, C, D>; type CircuitData = circuit_data::CircuitData<F, C, D>;
static STANDARD_EMPTY_POD_DATA: LazyLock<(EmptyPodVerifyTarget, CircuitData)> = pub static STANDARD_EMPTY_POD_DATA: LazyLock<(EmptyPodVerifyTarget, CircuitData)> =
LazyLock::new(|| build().expect("successful build")); LazyLock::new(|| build().expect("successful build"));
fn build() -> Result<(EmptyPodVerifyTarget, CircuitData)> { fn build() -> Result<(EmptyPodVerifyTarget, CircuitData)> {
@ -144,7 +144,7 @@ impl EmptyPod {
let public_inputs = id let public_inputs = id
.to_fields(&self.params) .to_fields(&self.params)
.iter() .iter()
.chain(EMPTY_HASH.0.iter()) // slot for the unused vds root .chain(self.vds_root.0.iter())
.cloned() .cloned()
.collect_vec(); .collect_vec();
@ -222,6 +222,7 @@ impl RecursivePod for EmptyPod {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::middleware::EMPTY_HASH;
#[test] #[test]
fn test_empty_pod() { fn test_empty_pod() {

View file

@ -28,7 +28,7 @@ use crate::{
middleware::{ middleware::{
self, resolve_wildcard_values, AnchoredKey, CustomPredicateBatch, DynError, Hash, self, resolve_wildcard_values, AnchoredKey, CustomPredicateBatch, DynError, Hash,
MainPodInputs, NativeOperation, NonePod, OperationType, Params, Pod, PodId, PodProver, MainPodInputs, NativeOperation, NonePod, OperationType, Params, Pod, PodId, PodProver,
PodType, RecursivePod, StatementArg, ToFields, F, KEY_TYPE, SELF, PodType, RecursivePod, StatementArg, ToFields, VDSet, F, KEY_TYPE, SELF,
}, },
}; };
@ -153,11 +153,11 @@ pub(crate) fn extract_merkle_proofs(
_ => None, _ => None,
}) })
.collect(); .collect();
if merkle_proofs.len() > params.max_merkle_proofs { if merkle_proofs.len() > params.max_merkle_proofs_containers {
return Err(Error::custom(format!( return Err(Error::custom(format!(
"The number of required Merkle proofs ({}) exceeds the maximum number ({}).", "The number of required Merkle proofs ({}) exceeds the maximum number ({}).",
merkle_proofs.len(), merkle_proofs.len(),
params.max_merkle_proofs params.max_merkle_proofs_containers
))); )));
} }
Ok(merkle_proofs) Ok(merkle_proofs)
@ -283,7 +283,7 @@ pub(crate) fn layout_statements(
// We mocking or we don't need padding so we skip creating an EmptyPod // We mocking or we don't need padding so we skip creating an EmptyPod
MockEmptyPod::new_boxed(params) MockEmptyPod::new_boxed(params)
} else { } else {
EmptyPod::new_boxed(params, inputs.vds_root) EmptyPod::new_boxed(params, inputs.vds_set.root())
}; };
let empty_pod = empty_pod_box.as_ref(); let empty_pod = empty_pod_box.as_ref();
assert!(inputs.recursive_pods.len() <= params.max_input_recursive_pods); assert!(inputs.recursive_pods.len() <= params.max_input_recursive_pods);
@ -410,7 +410,7 @@ pub(crate) fn process_public_statements_operations(
pub struct Prover {} pub struct Prover {}
impl Prover { impl Prover {
fn _prove(&self, params: &Params, inputs: MainPodInputs) -> Result<MainPod> { fn _prove(&self, params: &Params, vd_set: &VDSet, inputs: MainPodInputs) -> Result<MainPod> {
let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA; let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA;
let (main_pod_target, circuit_data) = let (main_pod_target, circuit_data) =
RecursiveCircuit::<MainPodVerifyTarget>::target_and_circuit_data_padded( RecursiveCircuit::<MainPodVerifyTarget>::target_and_circuit_data_padded(
@ -445,7 +445,7 @@ impl Prover {
// We don't need padding so we skip creating an EmptyPod // We don't need padding so we skip creating an EmptyPod
MockEmptyPod::new_boxed(params) MockEmptyPod::new_boxed(params)
} else { } else {
EmptyPod::new_boxed(params, inputs.vds_root) EmptyPod::new_boxed(params, inputs.vds_set.root())
}; };
let inputs = MainPodInputs { let inputs = MainPodInputs {
recursive_pods: &inputs recursive_pods: &inputs
@ -492,10 +492,10 @@ impl Prover {
.recursive_pods .recursive_pods
.iter() .iter()
.map(|pod| { .map(|pod| {
assert_eq!(inputs.vds_root, pod.vds_root()); assert_eq!(inputs.vds_set.root(), pod.vds_root());
ProofWithPublicInputs { ProofWithPublicInputs {
proof: pod.proof(), proof: pod.proof(),
public_inputs: [pod.id().0 .0, inputs.vds_root.0].concat(), public_inputs: [pod.id().0 .0, inputs.vds_set.root().0].concat(),
} }
}) })
.collect_vec(); .collect_vec();
@ -504,8 +504,12 @@ impl Prover {
.iter() .iter()
.map(|pod| pod.verifier_data()) .map(|pod| pod.verifier_data())
.collect_vec(); .collect_vec();
let vd_mt_proofs = vd_set.get_vds_proofs(&verifier_datas)?;
let input = MainPodVerifyInput { let input = MainPodVerifyInput {
vds_root: inputs.vds_root, vds_set: inputs.vds_set.clone(),
vd_mt_proofs,
signed_pods: signed_pods_input, signed_pods: signed_pods_input,
recursive_pods_pub_self_statements, recursive_pods_pub_self_statements,
statements: statements[statements.len() - params.max_statements..].to_vec(), statements: statements[statements.len() - params.max_statements..].to_vec(),
@ -519,7 +523,7 @@ impl Prover {
Ok(MainPod { Ok(MainPod {
params: params.clone(), params: params.clone(),
id, id,
vds_root: inputs.vds_root, vds_root: inputs.vds_set.root(),
public_statements, public_statements,
proof: proof_with_pis.proof, proof: proof_with_pis.proof,
}) })
@ -530,9 +534,10 @@ impl PodProver for Prover {
fn prove( fn prove(
&self, &self,
params: &Params, params: &Params,
vd_set: &VDSet,
inputs: MainPodInputs, inputs: MainPodInputs,
) -> Result<Box<dyn RecursivePod>, Box<DynError>> { ) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
Ok(self._prove(params, inputs).map(Box::new)?) Ok(self._prove(params, vd_set, inputs).map(Box::new)?)
} }
} }
@ -540,6 +545,11 @@ impl PodProver for Prover {
pub struct MainPod { pub struct MainPod {
params: Params, params: Params,
id: PodId, id: PodId,
/// vds_root is the merkle-root of the `VDSet`, which contains the
/// verifier_data hashes of the allowed set of VerifierOnlyCircuitData, for
/// 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, vds_root: Hash,
public_statements: Vec<Statement>, public_statements: Vec<Statement>,
proof: Proof, proof: Proof,
@ -696,7 +706,7 @@ pub mod tests {
{self}, {self},
}, },
middleware, middleware,
middleware::{CustomPredicateRef, NativePredicate as NP}, middleware::{CustomPredicateRef, NativePredicate as NP, DEFAULT_VD_SET},
op, op,
}; };
@ -711,6 +721,7 @@ pub mod tests {
..Default::default() ..Default::default()
}; };
println!("{:#?}", params); println!("{:#?}", params);
let vd_set = &*DEFAULT_VD_SET;
let (gov_id_builder, pay_stub_builder, sanction_list_builder) = let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
zu_kyc_sign_pod_builders(&params); zu_kyc_sign_pod_builders(&params);
@ -720,8 +731,13 @@ pub mod tests {
let pay_stub_pod = pay_stub_builder.sign(&mut signer)?; let pay_stub_pod = pay_stub_builder.sign(&mut signer)?;
let mut signer = Signer(SecretKey(3u64.into())); let mut signer = Signer(SecretKey(3u64.into()));
let sanction_list_pod = sanction_list_builder.sign(&mut signer)?; let sanction_list_pod = sanction_list_builder.sign(&mut signer)?;
let kyc_builder = let kyc_builder = zu_kyc_pod_builder(
zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod, &sanction_list_pod)?; &params,
&vd_set,
&gov_id_pod,
&pay_stub_pod,
&sanction_list_pod,
)?;
let mut prover = Prover {}; let mut prover = Prover {};
let kyc_pod = kyc_builder.prove(&mut prover, &params)?; let kyc_pod = kyc_builder.prove(&mut prover, &params)?;
@ -742,6 +758,7 @@ pub mod tests {
max_input_pods_public_statements: 10, max_input_pods_public_statements: 10,
..Default::default() ..Default::default()
}; };
let vd_set = &*DEFAULT_VD_SET;
let mut gov_id_builder = frontend::SignedPodBuilder::new(&params); let mut gov_id_builder = frontend::SignedPodBuilder::new(&params);
gov_id_builder.insert("idNumber", "4242424242"); gov_id_builder.insert("idNumber", "4242424242");
@ -750,7 +767,7 @@ pub mod tests {
let mut signer = Signer(SecretKey(42u64.into())); let mut signer = Signer(SecretKey(42u64.into()));
let gov_id = gov_id_builder.sign(&mut signer).unwrap(); let gov_id = gov_id_builder.sign(&mut signer).unwrap();
let now_minus_18y: i64 = 1169909388; let now_minus_18y: i64 = 1169909388;
let mut kyc_builder = frontend::MainPodBuilder::new(&params); let mut kyc_builder = frontend::MainPodBuilder::new(&params, &vd_set);
kyc_builder.add_signed_pod(&gov_id); kyc_builder.add_signed_pod(&gov_id);
kyc_builder kyc_builder
.pub_op(op!(lt, (&gov_id, "dateOfBirth"), now_minus_18y)) .pub_op(op!(lt, (&gov_id, "dateOfBirth"), now_minus_18y))
@ -792,11 +809,13 @@ pub mod tests {
max_custom_predicate_arity: 2, max_custom_predicate_arity: 2,
max_custom_predicate_wildcards: 2, max_custom_predicate_wildcards: 2,
max_custom_batch_size: 2, max_custom_batch_size: 2,
max_merkle_proofs: 2, max_merkle_proofs_containers: 2,
max_depth_mt_gadget: 4, max_depth_mt_containers: 4,
max_depth_mt_vds: 6,
}; };
let vd_set = &*DEFAULT_VD_SET;
let pod_builder = frontend::MainPodBuilder::new(&params); let pod_builder = frontend::MainPodBuilder::new(&params, &vd_set);
// Mock // Mock
let mut prover = MockProver {}; let mut prover = MockProver {};
@ -828,6 +847,7 @@ pub mod tests {
..Default::default() ..Default::default()
}; };
println!("{:#?}", params); println!("{:#?}", params);
let vd_set = &*DEFAULT_VD_SET;
let mut alice = Signer(SecretKey(1u32.into())); let mut alice = Signer(SecretKey(1u32.into()));
let bob = Signer(SecretKey(2u32.into())); let bob = Signer(SecretKey(2u32.into()));
@ -842,6 +862,7 @@ pub mod tests {
let alice_bob_ethdos_builder = eth_dos_pod_builder( let alice_bob_ethdos_builder = eth_dos_pod_builder(
&params, &params,
&vd_set,
false, false,
&alice_attestation, &alice_attestation,
&charlie_attestation, &charlie_attestation,
@ -878,6 +899,7 @@ pub mod tests {
..Default::default() ..Default::default()
}; };
println!("{:#?}", params); println!("{:#?}", params);
let vd_set = &*DEFAULT_VD_SET;
let mut cpb_builder = CustomPredicateBatchBuilder::new(params.clone(), "cpb".into()); let mut cpb_builder = CustomPredicateBatchBuilder::new(params.clone(), "cpb".into());
let stb0 = STB::new(NP::ValueOf) let stb0 = STB::new(NP::ValueOf)
@ -898,7 +920,7 @@ pub mod tests {
let cpb_and = CustomPredicateRef::new(cpb.clone(), 0); let cpb_and = CustomPredicateRef::new(cpb.clone(), 0);
let _cpb_or = CustomPredicateRef::new(cpb.clone(), 1); let _cpb_or = CustomPredicateRef::new(cpb.clone(), 1);
let mut pod_builder = MainPodBuilder::new(&params); let mut pod_builder = MainPodBuilder::new(&params, &vd_set);
let st0 = pod_builder.priv_op(op!(new_entry, ("score", 42)))?; let st0 = pod_builder.priv_op(op!(new_entry, ("score", 42)))?;
let st1 = pod_builder.priv_op(op!(new_entry, ("foo", 42)))?; let st1 = pod_builder.priv_op(op!(new_entry, ("foo", 42)))?;

View file

@ -19,7 +19,7 @@ use crate::{
}, },
middleware::{ middleware::{
self, hash_str, AnchoredKey, DynError, Hash, MainPodInputs, NativePredicate, Params, Pod, self, hash_str, AnchoredKey, DynError, Hash, MainPodInputs, NativePredicate, Params, Pod,
PodId, PodProver, PodType, Predicate, RecursivePod, StatementArg, KEY_TYPE, SELF, PodId, PodProver, PodType, Predicate, RecursivePod, StatementArg, VDSet, KEY_TYPE, SELF,
}, },
}; };
@ -29,6 +29,7 @@ impl PodProver for MockProver {
fn prove( fn prove(
&self, &self,
params: &Params, params: &Params,
_vd_set: &VDSet,
inputs: MainPodInputs, inputs: MainPodInputs,
) -> Result<Box<dyn RecursivePod>, Box<DynError>> { ) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
Ok(Box::new(MockMainPod::new(params, inputs)?)) Ok(Box::new(MockMainPod::new(params, inputs)?))
@ -176,7 +177,7 @@ impl MockMainPod {
Ok(Self { Ok(Self {
params: params.clone(), params: params.clone(),
id, id,
vds_root: inputs.vds_root, vds_root: inputs.vds_set.root(),
// input_signed_pods, // input_signed_pods,
// input_main_pods, // input_main_pods,
// input_statements, // input_statements,
@ -356,12 +357,13 @@ pub mod tests {
zu_kyc_sign_pod_builders, zu_kyc_sign_pod_builders,
}, },
frontend, frontend,
middleware::{self}, middleware::{self, DEFAULT_VD_SET},
}; };
#[test] #[test]
fn test_mock_main_zu_kyc() -> frontend::Result<()> { fn test_mock_main_zu_kyc() -> frontend::Result<()> {
let params = middleware::Params::default(); let params = middleware::Params::default();
let vd_set = &*DEFAULT_VD_SET;
let (gov_id_builder, pay_stub_builder, sanction_list_builder) = let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
zu_kyc_sign_pod_builders(&params); zu_kyc_sign_pod_builders(&params);
let mut signer = MockSigner { let mut signer = MockSigner {
@ -376,8 +378,13 @@ pub mod tests {
pk: "ZooOFAC".into(), pk: "ZooOFAC".into(),
}; };
let sanction_list_pod = sanction_list_builder.sign(&mut signer)?; let sanction_list_pod = sanction_list_builder.sign(&mut signer)?;
let kyc_builder = let kyc_builder = zu_kyc_pod_builder(
zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod, &sanction_list_pod)?; &params,
&vd_set,
&gov_id_pod,
&pay_stub_pod,
&sanction_list_pod,
)?;
let mut prover = MockProver {}; let mut prover = MockProver {};
let kyc_pod = kyc_builder.prove(&mut prover, &params)?; let kyc_pod = kyc_builder.prove(&mut prover, &params)?;

View file

@ -27,13 +27,13 @@ impl MockSigner {
} }
impl MockSigner { impl MockSigner {
fn _sign(&mut self, _params: &Params, kvs: &HashMap<Key, Value>) -> Result<MockSignedPod> { fn _sign(&mut self, params: &Params, kvs: &HashMap<Key, Value>) -> Result<MockSignedPod> {
let mut kvs = kvs.clone(); let mut kvs = kvs.clone();
let pubkey = self.public_key(); let pubkey = self.public_key();
kvs.insert(Key::from(KEY_SIGNER), Value::from(pubkey)); kvs.insert(Key::from(KEY_SIGNER), Value::from(pubkey));
kvs.insert(Key::from(KEY_TYPE), Value::from(PodType::MockSigned)); kvs.insert(Key::from(KEY_TYPE), Value::from(PodType::MockSigned));
let dict = Dictionary::new(kvs.clone())?; let dict = Dictionary::new(params.max_depth_mt_containers, kvs.clone())?;
let id = PodId(dict.commitment()); let id = PodId(dict.commitment());
let signature = format!("{}_signed_by_{}", id, pubkey); let signature = format!("{}_signed_by_{}", id, pubkey);
Ok(MockSignedPod { id, signature, kvs }) Ok(MockSignedPod { id, signature, kvs })

View file

@ -42,7 +42,7 @@ pub struct MerkleProofGadget {
pub max_depth: usize, pub max_depth: usize,
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct MerkleClaimAndProofTarget { pub struct MerkleClaimAndProofTarget {
pub(crate) max_depth: usize, pub(crate) max_depth: usize,
// `enabled` determines if the merkleproof verification is enabled // `enabled` determines if the merkleproof verification is enabled
@ -59,7 +59,7 @@ pub struct MerkleClaimAndProofTarget {
impl MerkleProofGadget { impl MerkleProofGadget {
/// creates the targets and defines the logic of the circuit /// creates the targets and defines the logic of the circuit
pub fn eval(&self, builder: &mut CircuitBuilder<F, D>) -> Result<MerkleClaimAndProofTarget> { pub fn eval(&self, builder: &mut CircuitBuilder<F, D>) -> MerkleClaimAndProofTarget {
let measure = measure_gates_begin!(builder, format!("MerkleProof_{}", self.max_depth)); let measure = measure_gates_begin!(builder, format!("MerkleProof_{}", self.max_depth));
let enabled = builder.add_virtual_bool_target_safe(); let enabled = builder.add_virtual_bool_target_safe();
let root = builder.add_virtual_hash(); let root = builder.add_virtual_hash();
@ -128,7 +128,7 @@ impl MerkleProofGadget {
// (this is for the three cases (existence, non-existence case i, and // (this is for the three cases (existence, non-existence case i, and
// non-existence case ii). // non-existence case ii).
let obtained_root = let obtained_root =
compute_root_from_leaf(self.max_depth, builder, &path, &leaf_hash, &siblings)?; compute_root_from_leaf(self.max_depth, builder, &path, &leaf_hash, &siblings);
// check that obtained_root==root (from inputs), when enabled==true // check that obtained_root==root (from inputs), when enabled==true
let zero = builder.zero(); let zero = builder.zero();
@ -143,7 +143,7 @@ impl MerkleProofGadget {
} }
measure_gates_end!(builder, measure); measure_gates_end!(builder, measure);
Ok(MerkleClaimAndProofTarget { MerkleClaimAndProofTarget {
max_depth: self.max_depth, max_depth: self.max_depth,
enabled, enabled,
existence, existence,
@ -154,7 +154,7 @@ impl MerkleProofGadget {
case_ii_selector, case_ii_selector,
other_key, other_key,
other_value, other_value,
}) }
} }
} }
@ -241,7 +241,7 @@ impl MerkleProofExistenceGadget {
// compute the root for the given siblings and the computed leaf_hash. // compute the root for the given siblings and the computed leaf_hash.
let obtained_root = let obtained_root =
compute_root_from_leaf(self.max_depth, builder, &path, &leaf_hash, &siblings)?; compute_root_from_leaf(self.max_depth, builder, &path, &leaf_hash, &siblings);
// check that obtained_root==root (from inputs), when enabled==true // check that obtained_root==root (from inputs), when enabled==true
let zero = builder.zero(); let zero = builder.zero();
@ -305,7 +305,7 @@ fn compute_root_from_leaf(
path: &[BoolTarget], path: &[BoolTarget],
leaf_hash: &HashOutTarget, leaf_hash: &HashOutTarget,
siblings: &[HashOutTarget], siblings: &[HashOutTarget],
) -> Result<HashOutTarget> { ) -> HashOutTarget {
assert_eq!(siblings.len(), max_depth); assert_eq!(siblings.len(), max_depth);
// Convenience constants // Convenience constants
let zero = builder.zero(); let zero = builder.zero();
@ -356,7 +356,7 @@ fn compute_root_from_leaf(
.collect(); .collect();
h = HashOutTarget::from_vec(h_targ); h = HashOutTarget::from_vec(h_targ);
} }
Ok(h) h
} }
// Note: this logic is in its own method for easy of reusability but // Note: this logic is in its own method for easy of reusability but
@ -546,7 +546,7 @@ pub mod tests {
let mut builder = CircuitBuilder::<F, D>::new(config); let mut builder = CircuitBuilder::<F, D>::new(config);
let mut pw = PartialWitness::<F>::new(); let mut pw = PartialWitness::<F>::new();
let targets = MerkleProofGadget { max_depth }.eval(&mut builder)?; let targets = MerkleProofGadget { max_depth }.eval(&mut builder);
targets.set_targets( targets.set_targets(
&mut pw, &mut pw,
true, true,
@ -667,7 +667,7 @@ pub mod tests {
let mut builder = CircuitBuilder::<F, D>::new(config); let mut builder = CircuitBuilder::<F, D>::new(config);
let mut pw = PartialWitness::<F>::new(); let mut pw = PartialWitness::<F>::new();
let targets = MerkleProofGadget { max_depth }.eval(&mut builder)?; let targets = MerkleProofGadget { max_depth }.eval(&mut builder);
targets.set_targets( targets.set_targets(
&mut pw, &mut pw,
true, true,
@ -714,7 +714,7 @@ pub mod tests {
let mut builder = CircuitBuilder::<F, D>::new(config); let mut builder = CircuitBuilder::<F, D>::new(config);
let mut pw = PartialWitness::<F>::new(); let mut pw = PartialWitness::<F>::new();
let targets = MerkleProofGadget { max_depth }.eval(&mut builder)?; let targets = MerkleProofGadget { max_depth }.eval(&mut builder);
// verification enabled & proof of existence // verification enabled & proof of existence
let mp = MerkleClaimAndProof::new(tree2.root(), key, Some(value), proof); let mp = MerkleClaimAndProof::new(tree2.root(), key, Some(value), proof);
targets.set_targets(&mut pw, true, &mp)?; targets.set_targets(&mut pw, true, &mp)?;
@ -730,7 +730,7 @@ pub mod tests {
let mut builder = CircuitBuilder::<F, D>::new(config); let mut builder = CircuitBuilder::<F, D>::new(config);
let mut pw = PartialWitness::<F>::new(); let mut pw = PartialWitness::<F>::new();
let targets = MerkleProofGadget { max_depth }.eval(&mut builder)?; let targets = MerkleProofGadget { max_depth }.eval(&mut builder);
// verification disabled & proof of existence // verification disabled & proof of existence
targets.set_targets(&mut pw, false, &mp)?; targets.set_targets(&mut pw, false, &mp)?;

View file

@ -28,13 +28,13 @@ use crate::{
pub struct Signer(pub SecretKey); pub struct Signer(pub SecretKey);
impl Signer { impl Signer {
fn _sign(&mut self, _params: &Params, kvs: &HashMap<Key, Value>) -> Result<SignedPod> { fn _sign(&mut self, params: &Params, kvs: &HashMap<Key, Value>) -> Result<SignedPod> {
let mut kvs = kvs.clone(); let mut kvs = kvs.clone();
let pubkey = self.0.public_key(); let pubkey = self.0.public_key();
kvs.insert(Key::from(KEY_SIGNER), Value::from(pubkey)); kvs.insert(Key::from(KEY_SIGNER), Value::from(pubkey));
kvs.insert(Key::from(KEY_TYPE), Value::from(PodType::Signed)); kvs.insert(Key::from(KEY_TYPE), Value::from(PodType::Signed));
let dict = Dictionary::new(kvs)?; let dict = Dictionary::new(params.max_depth_mt_containers, kvs)?;
let id = RawValue::from(dict.commitment()); // PodId as Value let id = RawValue::from(dict.commitment()); // PodId as Value
let nonce = OsRng.gen_biguint_below(&GROUP_ORDER); let nonce = OsRng.gen_biguint_below(&GROUP_ORDER);
@ -232,7 +232,7 @@ pub mod tests {
.into_iter() .into_iter()
.chain(iter::once(bad_kv)) .chain(iter::once(bad_kv))
.collect::<HashMap<Key, Value>>(); .collect::<HashMap<Key, Value>>();
bad_pod.dict = Dictionary::new(bad_kvs).unwrap(); bad_pod.dict = Dictionary::new(params.max_depth_mt_containers, bad_kvs).unwrap();
assert!(bad_pod.verify().is_err()); assert!(bad_pod.verify().is_err());
let mut bad_pod = pod.clone(); let mut bad_pod = pod.clone();
@ -244,7 +244,7 @@ pub mod tests {
.into_iter() .into_iter()
.chain(iter::once(bad_kv)) .chain(iter::once(bad_kv))
.collect::<HashMap<Key, Value>>(); .collect::<HashMap<Key, Value>>();
bad_pod.dict = Dictionary::new(bad_kvs).unwrap(); bad_pod.dict = Dictionary::new(params.max_depth_mt_containers, bad_kvs).unwrap();
assert!(bad_pod.verify().is_err()); assert!(bad_pod.verify().is_err());
Ok(()) Ok(())

View file

@ -8,8 +8,8 @@ use crate::{
backends::plonky2::mock::signedpod::MockSigner, backends::plonky2::mock::signedpod::MockSigner,
frontend::{MainPodBuilder, Result, SignedPod, SignedPodBuilder}, frontend::{MainPodBuilder, Result, SignedPod, SignedPodBuilder},
middleware::{ middleware::{
containers::Set, CustomPredicateRef, Params, PodType, Statement, TypedValue, Value, containers::Set, CustomPredicateRef, Params, PodType, Statement, TypedValue, VDSet, Value,
KEY_SIGNER, KEY_TYPE, DEFAULT_VD_SET, KEY_SIGNER, KEY_TYPE,
}, },
op, op,
}; };
@ -20,7 +20,8 @@ pub fn zu_kyc_sign_pod_builders(
params: &Params, params: &Params,
) -> (SignedPodBuilder, SignedPodBuilder, SignedPodBuilder) { ) -> (SignedPodBuilder, SignedPodBuilder, SignedPodBuilder) {
let sanctions_values: HashSet<Value> = ["A343434340"].iter().map(|s| Value::from(*s)).collect(); let sanctions_values: HashSet<Value> = ["A343434340"].iter().map(|s| Value::from(*s)).collect();
let sanction_set = Value::from(Set::new(sanctions_values).unwrap()); let sanction_set =
Value::from(Set::new(params.max_depth_mt_containers, sanctions_values).unwrap());
let mut gov_id = SignedPodBuilder::new(params); let mut gov_id = SignedPodBuilder::new(params);
gov_id.insert("idNumber", "4242424242"); gov_id.insert("idNumber", "4242424242");
@ -40,6 +41,7 @@ pub fn zu_kyc_sign_pod_builders(
pub fn zu_kyc_pod_builder( pub fn zu_kyc_pod_builder(
params: &Params, params: &Params,
vd_set: &VDSet,
gov_id: &SignedPod, gov_id: &SignedPod,
pay_stub: &SignedPod, pay_stub: &SignedPod,
sanction_list: &SignedPod, sanction_list: &SignedPod,
@ -47,7 +49,7 @@ pub fn zu_kyc_pod_builder(
let now_minus_18y: i64 = 1169909388; let now_minus_18y: i64 = 1169909388;
let now_minus_1y: i64 = 1706367566; let now_minus_1y: i64 = 1706367566;
let mut kyc = MainPodBuilder::new(params); let mut kyc = MainPodBuilder::new(params, vd_set);
kyc.add_signed_pod(gov_id); kyc.add_signed_pod(gov_id);
kyc.add_signed_pod(pay_stub); kyc.add_signed_pod(pay_stub);
kyc.add_signed_pod(sanction_list); kyc.add_signed_pod(sanction_list);
@ -78,6 +80,7 @@ pub fn eth_friend_signed_pod_builder(params: &Params, friend_pubkey: Value) -> S
pub fn eth_dos_pod_builder( pub fn eth_dos_pod_builder(
params: &Params, params: &Params,
vd_set: &VDSet,
mock: bool, mock: bool,
alice_attestation: &SignedPod, alice_attestation: &SignedPod,
charlie_attestation: &SignedPod, charlie_attestation: &SignedPod,
@ -91,7 +94,7 @@ pub fn eth_dos_pod_builder(
let eth_dos = CustomPredicateRef::new(eth_dos_batch.clone(), 2); let eth_dos = CustomPredicateRef::new(eth_dos_batch.clone(), 2);
// ETHDoS POD builder // ETHDoS POD builder
let mut alice_bob_ethdos = MainPodBuilder::new(params); let mut alice_bob_ethdos = MainPodBuilder::new(params, vd_set);
alice_bob_ethdos.add_signed_pod(alice_attestation); alice_bob_ethdos.add_signed_pod(alice_attestation);
alice_bob_ethdos.add_signed_pod(charlie_attestation); alice_bob_ethdos.add_signed_pod(charlie_attestation);
@ -229,6 +232,7 @@ pub fn friend_sign_pod_builder(params: &Params, friend: &str) -> SignedPodBuilde
pub fn great_boy_pod_builder( pub fn great_boy_pod_builder(
params: &Params, params: &Params,
vd_set: &VDSet,
good_boy_pods: [&SignedPod; 4], good_boy_pods: [&SignedPod; 4],
friend_pods: [&SignedPod; 2], friend_pods: [&SignedPod; 2],
good_boy_issuers: &Value, good_boy_issuers: &Value,
@ -242,7 +246,7 @@ pub fn great_boy_pod_builder(
// good boy 0 -> friend_pods[0] => receiver // good boy 0 -> friend_pods[0] => receiver
// good boy 1 -> friend_pods[1] => receiver // good boy 1 -> friend_pods[1] => receiver
let mut great_boy = MainPodBuilder::new(params); let mut great_boy = MainPodBuilder::new(params, vd_set);
for i in 0..4 { for i in 0..4 {
great_boy.add_signed_pod(good_boy_pods[i]); great_boy.add_signed_pod(good_boy_pods[i]);
} }
@ -305,6 +309,7 @@ pub fn great_boy_pod_full_flow() -> Result<(Params, MainPodBuilder)> {
num_public_statements_id: 50, num_public_statements_id: 50,
..Default::default() ..Default::default()
}; };
let vd_set = &*DEFAULT_VD_SET;
let good_boy_issuers = ["Giggles", "Macrosoft", "FaeBook"]; let good_boy_issuers = ["Giggles", "Macrosoft", "FaeBook"];
let mut giggles_signer = MockSigner { let mut giggles_signer = MockSigner {
@ -348,11 +353,13 @@ pub fn great_boy_pod_full_flow() -> Result<(Params, MainPodBuilder)> {
alice_friend_pods.push(friend.sign(&mut charlie_signer).unwrap()); alice_friend_pods.push(friend.sign(&mut charlie_signer).unwrap());
let good_boy_issuers = Value::from(Set::new( let good_boy_issuers = Value::from(Set::new(
params.max_depth_mt_containers,
good_boy_issuers.into_iter().map(Value::from).collect(), good_boy_issuers.into_iter().map(Value::from).collect(),
)?); )?);
let builder = great_boy_pod_builder( let builder = great_boy_pod_builder(
&params, &params,
&vd_set,
[ [
&bob_good_boys[0], &bob_good_boys[0],
&bob_good_boys[1], &bob_good_boys[1],
@ -383,6 +390,7 @@ pub fn tickets_sign_pod_builder(params: &Params) -> SignedPodBuilder {
pub fn tickets_pod_builder( pub fn tickets_pod_builder(
params: &Params, params: &Params,
vd_set: &VDSet,
signed_pod: &SignedPod, signed_pod: &SignedPod,
expected_event_id: i64, expected_event_id: i64,
expect_consumed: bool, expect_consumed: bool,
@ -390,7 +398,7 @@ pub fn tickets_pod_builder(
) -> Result<MainPodBuilder> { ) -> Result<MainPodBuilder> {
let blacklisted_email_set_value = Value::from(TypedValue::Set(blacklisted_emails.clone())); let blacklisted_email_set_value = Value::from(TypedValue::Set(blacklisted_emails.clone()));
// Create a main pod referencing this signed pod with some statements // Create a main pod referencing this signed pod with some statements
let mut builder = MainPodBuilder::new(params); let mut builder = MainPodBuilder::new(params, vd_set);
builder.add_signed_pod(signed_pod); builder.add_signed_pod(signed_pod);
builder.pub_op(op!(eq, (signed_pod, "eventId"), expected_event_id))?; builder.pub_op(op!(eq, (signed_pod, "eventId"), expected_event_id))?;
builder.pub_op(op!(eq, (signed_pod, "isConsumed"), expect_consumed))?; builder.pub_op(op!(eq, (signed_pod, "isConsumed"), expect_consumed))?;
@ -405,7 +413,15 @@ pub fn tickets_pod_builder(
pub fn tickets_pod_full_flow() -> Result<MainPodBuilder> { pub fn tickets_pod_full_flow() -> Result<MainPodBuilder> {
let params = Params::default(); let params = Params::default();
let vd_set = &*DEFAULT_VD_SET;
let builder = tickets_sign_pod_builder(&params); let builder = tickets_sign_pod_builder(&params);
let signed_pod = builder.sign(&mut MockSigner { pk: "test".into() }).unwrap(); let signed_pod = builder.sign(&mut MockSigner { pk: "test".into() }).unwrap();
tickets_pod_builder(&params, &signed_pod, 123, true, &Set::new(HashSet::new())?) tickets_pod_builder(
&params,
vd_set,
&signed_pod,
123,
true,
&Set::new(params.max_depth_mt_containers, HashSet::new())?,
)
} }

View file

@ -294,7 +294,7 @@ mod tests {
backends::plonky2::mock::mainpod::MockProver, backends::plonky2::mock::mainpod::MockProver,
examples::custom::{eth_dos_batch, eth_friend_batch}, examples::custom::{eth_dos_batch, eth_friend_batch},
frontend::MainPodBuilder, frontend::MainPodBuilder,
middleware::{self, containers::Set, CustomPredicateRef, Params, PodType}, middleware::{self, containers::Set, CustomPredicateRef, Params, PodType, DEFAULT_VD_SET},
op, op,
}; };
@ -328,6 +328,7 @@ mod tests {
#[test] #[test]
fn test_desugared_gt_custom_pred() -> Result<()> { fn test_desugared_gt_custom_pred() -> Result<()> {
let params = Params::default(); let params = Params::default();
let vd_set = &*DEFAULT_VD_SET;
let mut builder = CustomPredicateBatchBuilder::new(params.clone(), "gt_custom_pred".into()); let mut builder = CustomPredicateBatchBuilder::new(params.clone(), "gt_custom_pred".into());
let gt_stb = StatementTmplBuilder::new(NativePredicate::Gt) let gt_stb = StatementTmplBuilder::new(NativePredicate::Gt)
@ -344,7 +345,7 @@ mod tests {
let batch_clone = batch.clone(); let batch_clone = batch.clone();
let gt_custom_pred = CustomPredicateRef::new(batch, 0); let gt_custom_pred = CustomPredicateRef::new(batch, 0);
let mut mp_builder = MainPodBuilder::new(&params); let mut mp_builder = MainPodBuilder::new(&params, &vd_set);
// 2 > 1 // 2 > 1
let s1 = mp_builder.literal(true, Value::from(2))?; let s1 = mp_builder.literal(true, Value::from(2))?;
@ -376,6 +377,7 @@ mod tests {
#[test] #[test]
fn test_desugared_set_contains_custom_pred() -> Result<()> { fn test_desugared_set_contains_custom_pred() -> Result<()> {
let params = Params::default(); let params = Params::default();
let vd_set = &*DEFAULT_VD_SET;
let mut builder = let mut builder =
CustomPredicateBatchBuilder::new(params.clone(), "set_contains_custom_pred".into()); CustomPredicateBatchBuilder::new(params.clone(), "set_contains_custom_pred".into());
@ -392,10 +394,13 @@ mod tests {
let batch = builder.finish(); let batch = builder.finish();
let batch_clone = batch.clone(); let batch_clone = batch.clone();
let mut mp_builder = MainPodBuilder::new(&params); let mut mp_builder = MainPodBuilder::new(&params, &vd_set);
let set_values: HashSet<Value> = [1, 2, 3].iter().map(|i| Value::from(*i)).collect(); let set_values: HashSet<Value> = [1, 2, 3].iter().map(|i| Value::from(*i)).collect();
let s1 = mp_builder.literal(true, Value::from(Set::new(set_values)?))?; let s1 = mp_builder.literal(
true,
Value::from(Set::new(params.max_depth_mt_containers, set_values)?),
)?;
let s2 = mp_builder.literal(true, Value::from(1))?; let s2 = mp_builder.literal(true, Value::from(1))?;
let set_contains = mp_builder.pub_op(op!(set_contains, s1, s2))?; let set_contains = mp_builder.pub_op(op!(set_contains, s1, s2))?;

View file

@ -10,8 +10,7 @@ use serialization::{SerializedMainPod, SerializedSignedPod};
use crate::middleware::{ use crate::middleware::{
self, check_st_tmpl, hash_str, hash_values, AnchoredKey, Hash, Key, MainPodInputs, self, check_st_tmpl, hash_str, hash_values, AnchoredKey, Hash, Key, MainPodInputs,
NativeOperation, NativePredicate, OperationAux, OperationType, Params, PodId, PodProver, NativeOperation, NativePredicate, OperationAux, OperationType, Params, PodId, PodProver,
PodSigner, Predicate, Statement, StatementArg, Value, WildcardValue, EMPTY_HASH, KEY_TYPE, PodSigner, Predicate, Statement, StatementArg, VDSet, Value, WildcardValue, KEY_TYPE, SELF,
SELF,
}; };
mod custom; mod custom;
@ -117,6 +116,7 @@ impl SignedPod {
#[derive(Debug)] #[derive(Debug)]
pub struct MainPodBuilder { pub struct MainPodBuilder {
pub params: Params, pub params: Params,
pub vd_set: VDSet,
pub input_signed_pods: Vec<SignedPod>, pub input_signed_pods: Vec<SignedPod>,
pub input_main_pods: Vec<MainPod>, pub input_main_pods: Vec<MainPod>,
pub statements: Vec<Statement>, pub statements: Vec<Statement>,
@ -151,9 +151,10 @@ impl fmt::Display for MainPodBuilder {
} }
impl MainPodBuilder { impl MainPodBuilder {
pub fn new(params: &Params) -> Self { pub fn new(params: &Params, vd_set: &VDSet) -> Self {
Self { Self {
params: params.clone(), params: params.clone(),
vd_set: vd_set.clone(),
input_signed_pods: Vec::new(), input_signed_pods: Vec::new(),
input_main_pods: Vec::new(), input_main_pods: Vec::new(),
statements: Vec::new(), statements: Vec::new(),
@ -548,6 +549,7 @@ impl MainPodBuilder {
}; };
let (statements, operations, public_statements) = compiler.compile(inputs, params)?; let (statements, operations, public_statements) = compiler.compile(inputs, params)?;
let inputs = MainPodInputs { let inputs = MainPodInputs {
signed_pods: &self signed_pods: &self
.input_signed_pods .input_signed_pods
@ -562,9 +564,9 @@ impl MainPodBuilder {
statements: &statements, statements: &statements,
operations: &operations, operations: &operations,
public_statements: &public_statements, public_statements: &public_statements,
vds_root: EMPTY_HASH, // TODO https://github.com/0xPARC/pod2/issues/249 vds_set: self.vd_set.clone(),
}; };
let pod = prover.prove(&self.params, inputs)?; let pod = prover.prove(&self.params, &self.vd_set, inputs)?;
// Gather public statements, making sure to inject the type // Gather public statements, making sure to inject the type
// information specified by the backend. // information specified by the backend.
@ -838,7 +840,7 @@ pub mod tests {
eth_dos_pod_builder, eth_friend_signed_pod_builder, great_boy_pod_full_flow, eth_dos_pod_builder, eth_friend_signed_pod_builder, great_boy_pod_full_flow,
tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_sign_pod_builders, tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_sign_pod_builders,
}, },
middleware::{containers::Dictionary, Value}, middleware::{containers::Dictionary, Value, DEFAULT_VD_SET},
}; };
// Check that frontend public statements agree with those // Check that frontend public statements agree with those
@ -873,6 +875,7 @@ pub mod tests {
#[test] #[test]
fn test_front_zu_kyc() -> Result<()> { fn test_front_zu_kyc() -> Result<()> {
let params = Params::default(); let params = Params::default();
let vd_set = &*DEFAULT_VD_SET;
let (gov_id, pay_stub, sanction_list) = zu_kyc_sign_pod_builders(&params); let (gov_id, pay_stub, sanction_list) = zu_kyc_sign_pod_builders(&params);
println!("{}", gov_id); println!("{}", gov_id);
@ -899,7 +902,7 @@ pub mod tests {
check_kvs(&sanction_list)?; check_kvs(&sanction_list)?;
println!("{}", sanction_list); println!("{}", sanction_list);
let kyc_builder = zu_kyc_pod_builder(&params, &gov_id, &pay_stub, &sanction_list)?; let kyc_builder = zu_kyc_pod_builder(&params, &vd_set, &gov_id, &pay_stub, &sanction_list)?;
println!("{}", kyc_builder); println!("{}", kyc_builder);
// prove kyc with MockProver and print it // prove kyc with MockProver and print it
@ -926,6 +929,7 @@ pub mod tests {
max_custom_predicate_wildcards: 12, max_custom_predicate_wildcards: 12,
..Default::default() ..Default::default()
}; };
let vd_set = &*DEFAULT_VD_SET;
let mut alice = MockSigner { pk: "Alice".into() }; let mut alice = MockSigner { pk: "Alice".into() };
let bob = MockSigner { pk: "Bob".into() }; let bob = MockSigner { pk: "Bob".into() };
@ -945,6 +949,7 @@ pub mod tests {
let mut prover = MockProver {}; let mut prover = MockProver {};
let alice_bob_ethdos = eth_dos_pod_builder( let alice_bob_ethdos = eth_dos_pod_builder(
&params, &params,
&vd_set,
true, true,
&alice_attestation, &alice_attestation,
&charlie_attestation, &charlie_attestation,
@ -978,13 +983,15 @@ pub mod tests {
#[should_panic] #[should_panic]
fn test_equal() { fn test_equal() {
let params = Params::default(); let params = Params::default();
let vd_set = &*DEFAULT_VD_SET;
let mut signed_builder = SignedPodBuilder::new(&params); let mut signed_builder = SignedPodBuilder::new(&params);
signed_builder.insert("a", 1); signed_builder.insert("a", 1);
signed_builder.insert("b", 1); signed_builder.insert("b", 1);
let mut signer = MockSigner { pk: "key".into() }; let mut signer = MockSigner { pk: "key".into() };
let signed_pod = signed_builder.sign(&mut signer).unwrap(); let signed_pod = signed_builder.sign(&mut signer).unwrap();
let mut builder = MainPodBuilder::new(&params); let mut builder = MainPodBuilder::new(&params, &vd_set);
builder.add_signed_pod(&signed_pod); builder.add_signed_pod(&signed_pod);
//let op_val1 = Operation{ //let op_val1 = Operation{
@ -1028,6 +1035,7 @@ pub mod tests {
#[should_panic] #[should_panic]
fn test_false_st() { fn test_false_st() {
let params = Params::default(); let params = Params::default();
let vd_set = &*DEFAULT_VD_SET;
let mut builder = SignedPodBuilder::new(&params); let mut builder = SignedPodBuilder::new(&params);
builder.insert("num", 2); builder.insert("num", 2);
@ -1039,7 +1047,7 @@ pub mod tests {
println!("{}", pod); println!("{}", pod);
let mut builder = MainPodBuilder::new(&params); let mut builder = MainPodBuilder::new(&params, &vd_set);
builder.add_signed_pod(&pod); builder.add_signed_pod(&pod);
builder.pub_op(op!(gt, (&pod, "num"), 5)).unwrap(); builder.pub_op(op!(gt, (&pod, "num"), 5)).unwrap();
@ -1053,6 +1061,7 @@ pub mod tests {
#[test] #[test]
fn test_dictionaries() -> Result<()> { fn test_dictionaries() -> Result<()> {
let params = Params::default(); let params = Params::default();
let vd_set = &*DEFAULT_VD_SET;
let mut builder = SignedPodBuilder::new(&params); let mut builder = SignedPodBuilder::new(&params);
let mut my_dict_kvs: HashMap<Key, Value> = HashMap::new(); let mut my_dict_kvs: HashMap<Key, Value> = HashMap::new();
@ -1061,7 +1070,7 @@ pub mod tests {
my_dict_kvs.insert(Key::from("c"), Value::from(3)); my_dict_kvs.insert(Key::from("c"), Value::from(3));
// let my_dict_as_mt = MerkleTree::new(5, &my_dict_kvs).unwrap(); // let my_dict_as_mt = MerkleTree::new(5, &my_dict_kvs).unwrap();
// let dict = Dictionary { mt: my_dict_as_mt }; // let dict = Dictionary { mt: my_dict_as_mt };
let dict = Dictionary::new(my_dict_kvs)?; let dict = Dictionary::new(params.max_depth_mt_containers, my_dict_kvs)?;
let dict_root = Value::from(dict.clone()); let dict_root = Value::from(dict.clone());
builder.insert("dict", dict_root); builder.insert("dict", dict_root);
@ -1070,7 +1079,7 @@ pub mod tests {
}; };
let pod = builder.sign(&mut signer).unwrap(); let pod = builder.sign(&mut signer).unwrap();
let mut builder = MainPodBuilder::new(&params); let mut builder = MainPodBuilder::new(&params, &vd_set);
builder.add_signed_pod(&pod); builder.add_signed_pod(&pod);
let st0 = pod.get_statement("dict").unwrap(); let st0 = pod.get_statement("dict").unwrap();
let st1 = builder.op(true, op!(new_entry, ("key", "a"))).unwrap(); let st1 = builder.op(true, op!(new_entry, ("key", "a"))).unwrap();
@ -1106,7 +1115,8 @@ pub mod tests {
env_logger::init(); env_logger::init();
let params = Params::default(); let params = Params::default();
let mut builder = MainPodBuilder::new(&params); let vd_set = &*DEFAULT_VD_SET;
let mut builder = MainPodBuilder::new(&params, &vd_set);
let st = Statement::ValueOf(AnchoredKey::from((SELF, "a")), Value::from(3)); let st = Statement::ValueOf(AnchoredKey::from((SELF, "a")), Value::from(3));
let op_new_entry = Operation( let op_new_entry = Operation(
OperationType::Native(NativeOperation::NewEntry), OperationType::Native(NativeOperation::NewEntry),
@ -1124,8 +1134,7 @@ pub mod tests {
// try to insert a statement that doesn't follow from the operation // try to insert a statement that doesn't follow from the operation
// right now the mock prover catches this when it calls compile() // right now the mock prover catches this when it calls compile()
let params = Params::default(); let mut builder = MainPodBuilder::new(&params, &vd_set);
let mut builder = MainPodBuilder::new(&params);
let self_a = AnchoredKey::from((SELF, "a")); let self_a = AnchoredKey::from((SELF, "a"));
let self_b = AnchoredKey::from((SELF, "b")); let self_b = AnchoredKey::from((SELF, "b"));
let value_of_a = Statement::ValueOf(self_a.clone(), Value::from(3)); let value_of_a = Statement::ValueOf(self_a.clone(), Value::from(3));

View file

@ -112,24 +112,25 @@ mod tests {
middleware::{ middleware::{
self, self,
containers::{Array, Dictionary, Set}, containers::{Array, Dictionary, Set},
Params, TypedValue, Params, TypedValue, DEFAULT_VD_SET,
}, },
}; };
#[test] #[test]
fn test_value_serialization() { fn test_value_serialization() {
let params = &Params::default();
// Pairs of values and their expected serialized representations // Pairs of values and their expected serialized representations
let values = vec![ let values = vec![
(TypedValue::String("hello".to_string()), "\"hello\""), (TypedValue::String("hello".to_string()), "\"hello\""),
(TypedValue::Int(42), "{\"Int\":\"42\"}"), (TypedValue::Int(42), "{\"Int\":\"42\"}"),
(TypedValue::Bool(true), "true"), (TypedValue::Bool(true), "true"),
( (
TypedValue::Array(Array::new(vec!["foo".into(), false.into()]).unwrap()), TypedValue::Array(Array::new(params.max_depth_mt_containers, vec!["foo".into(), false.into()]).unwrap()),
"[\"foo\",false]", "{\"max_depth\":32,\"array\":[\"foo\",false]}",
), ),
( (
TypedValue::Dictionary( TypedValue::Dictionary(
Dictionary::new(HashMap::from([ Dictionary::new(params.max_depth_mt_containers, HashMap::from([
// The set of valid keys is equal to the set of valid JSON keys // The set of valid keys is equal to the set of valid JSON keys
("foo".into(), 123.into()), ("foo".into(), 123.into()),
// Empty strings are valid JSON keys // Empty strings are valid JSON keys
@ -145,11 +146,11 @@ mod tests {
])) ]))
.unwrap(), .unwrap(),
), ),
"{\"Dictionary\":{\"\":\"baz\",\"\\u0000\":\"\",\" hi\":false,\"!@£$%^&&*()\":\"\",\"foo\":{\"Int\":\"123\"},\"🥳\":\"party time!\"}}", "{\"Dictionary\":{\"max_depth\":32,\"kvs\":{\"\":\"baz\",\"\\u0000\":\"\",\" hi\":false,\"!@£$%^&&*()\":\"\",\"foo\":{\"Int\":\"123\"},\"🥳\":\"party time!\"}}}",
), ),
( (
TypedValue::Set(Set::new(HashSet::from(["foo".into(), "bar".into()])).unwrap()), TypedValue::Set(Set::new(params.max_depth_mt_containers, HashSet::from(["foo".into(), "bar".into()])).unwrap()),
"{\"Set\":[\"bar\",\"foo\"]}", "{\"Set\":{\"max_depth\":32,\"set\":[\"bar\",\"foo\"]}}",
), ),
]; ];
@ -168,30 +169,45 @@ mod tests {
} }
fn signed_pod_builder() -> SignedPodBuilder { fn signed_pod_builder() -> SignedPodBuilder {
let mut builder = SignedPodBuilder::new(&Params::default()); let params = &Params::default();
let mut builder = SignedPodBuilder::new(params);
builder.insert("name", "test"); builder.insert("name", "test");
builder.insert("age", 30); builder.insert("age", 30);
builder.insert("very_large_int", 1152921504606846976); builder.insert("very_large_int", 1152921504606846976);
builder.insert( builder.insert(
"a_dict_containing_one_key", "a_dict_containing_one_key",
Dictionary::new(HashMap::from([ Dictionary::new(
params.max_depth_mt_containers,
HashMap::from([
("foo".into(), 123.into()), ("foo".into(), 123.into()),
( (
"an_array_containing_three_ints".into(), "an_array_containing_three_ints".into(),
Array::new(vec![1.into(), 2.into(), 3.into()]) Array::new(
params.max_depth_mt_containers,
vec![1.into(), 2.into(), 3.into()],
)
.unwrap() .unwrap()
.into(), .into(),
), ),
( (
"a_set_containing_two_strings".into(), "a_set_containing_two_strings".into(),
Set::new(HashSet::from([ Set::new(
Array::new(vec!["foo".into(), "bar".into()]).unwrap().into(), params.max_depth_mt_containers,
HashSet::from([
Array::new(
params.max_depth_mt_containers,
vec!["foo".into(), "bar".into()],
)
.unwrap()
.into(),
"baz".into(), "baz".into(),
])) ]),
)
.unwrap() .unwrap()
.into(), .into(),
), ),
])) ]),
)
.unwrap(), .unwrap(),
); );
builder builder
@ -235,6 +251,7 @@ mod tests {
fn build_mock_zukyc_pod() -> Result<MainPod> { fn build_mock_zukyc_pod() -> Result<MainPod> {
let params = middleware::Params::default(); let params = middleware::Params::default();
let vd_set = &*DEFAULT_VD_SET;
let (gov_id_builder, pay_stub_builder, sanction_list_builder) = let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
zu_kyc_sign_pod_builders(&params); zu_kyc_sign_pod_builders(&params);
@ -250,8 +267,14 @@ mod tests {
pk: "ZooOFAC".into(), pk: "ZooOFAC".into(),
}; };
let sanction_list_pod = sanction_list_builder.sign(&mut signer).unwrap(); let sanction_list_pod = sanction_list_builder.sign(&mut signer).unwrap();
let kyc_builder = let kyc_builder = zu_kyc_pod_builder(
zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod, &sanction_list_pod).unwrap(); &params,
&vd_set,
&gov_id_pod,
&pay_stub_pod,
&sanction_list_pod,
)
.unwrap();
let mut prover = MockProver {}; let mut prover = MockProver {};
let kyc_pod = kyc_builder.prove(&mut prover, &params).unwrap(); let kyc_pod = kyc_builder.prove(&mut prover, &params).unwrap();
@ -265,6 +288,7 @@ mod tests {
max_input_recursive_pods: 1, max_input_recursive_pods: 1,
..Default::default() ..Default::default()
}; };
let vd_set = &*DEFAULT_VD_SET;
let (gov_id_builder, pay_stub_builder, sanction_list_builder) = let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
zu_kyc_sign_pod_builders(&params); zu_kyc_sign_pod_builders(&params);
@ -274,8 +298,13 @@ mod tests {
let pay_stub_pod = pay_stub_builder.sign(&mut signer)?; let pay_stub_pod = pay_stub_builder.sign(&mut signer)?;
let mut signer = Signer(SecretKey(3u32.into())); let mut signer = Signer(SecretKey(3u32.into()));
let sanction_list_pod = sanction_list_builder.sign(&mut signer)?; let sanction_list_pod = sanction_list_builder.sign(&mut signer)?;
let kyc_builder = let kyc_builder = zu_kyc_pod_builder(
zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod, &sanction_list_pod)?; &params,
&vd_set,
&gov_id_pod,
&pay_stub_pod,
&sanction_list_pod,
)?;
let mut prover = Prover {}; let mut prover = Prover {};
let kyc_pod = kyc_builder.prove(&mut prover, &params)?; let kyc_pod = kyc_builder.prove(&mut prover, &params)?;
@ -324,6 +353,7 @@ mod tests {
max_custom_predicate_wildcards: 12, max_custom_predicate_wildcards: 12,
..Default::default() ..Default::default()
}; };
let vd_set = &*DEFAULT_VD_SET;
let mut alice = MockSigner { pk: "Alice".into() }; let mut alice = MockSigner { pk: "Alice".into() };
let bob = MockSigner { pk: "Bob".into() }; let bob = MockSigner { pk: "Bob".into() };
@ -341,6 +371,7 @@ mod tests {
let mut prover = MockProver {}; let mut prover = MockProver {};
let alice_bob_ethdos = eth_dos_pod_builder( let alice_bob_ethdos = eth_dos_pod_builder(
&params, &params,
&vd_set,
true, true,
&alice_attestation, &alice_attestation,
&charlie_attestation, &charlie_attestation,

View file

@ -659,8 +659,11 @@ fn process_literal_value(lit_val_pair: &Pair<Rule>) -> Result<Value, ProcessorEr
.into_inner() .into_inner()
.map(|elem_pair| process_literal_value(&elem_pair)) .map(|elem_pair| process_literal_value(&elem_pair))
.collect(); .collect();
let middleware_array = middleware::containers::Array::new(elements?) let middleware_array =
.map_err(|e| ProcessorError::Internal(format!("Failed to create Array: {}", e)))?; middleware::containers::Array::new(crate::constants::MAX_DEPTH, elements?)
.map_err(|e| {
ProcessorError::Internal(format!("Failed to create Array: {}", e))
})?;
Ok(Value::from(middleware_array)) Ok(Value::from(middleware_array))
} }
Rule::literal_set => { Rule::literal_set => {
@ -668,8 +671,10 @@ fn process_literal_value(lit_val_pair: &Pair<Rule>) -> Result<Value, ProcessorEr
.into_inner() .into_inner()
.map(|elem_pair| process_literal_value(&elem_pair)) .map(|elem_pair| process_literal_value(&elem_pair))
.collect(); .collect();
let middleware_set = middleware::containers::Set::new(elements?) let middleware_set =
.map_err(|e| ProcessorError::Internal(format!("Failed to create Set: {}", e)))?; middleware::containers::Set::new(crate::constants::MAX_DEPTH, elements?).map_err(
|e| ProcessorError::Internal(format!("Failed to create Set: {}", e)),
)?;
Ok(Value::from(middleware_set)) Ok(Value::from(middleware_set))
} }
Rule::literal_dict => { Rule::literal_dict => {
@ -684,7 +689,9 @@ fn process_literal_value(lit_val_pair: &Pair<Rule>) -> Result<Value, ProcessorEr
Ok((Key::new(key_str), val)) Ok((Key::new(key_str), val))
}) })
.collect(); .collect();
let middleware_dict = middleware::containers::Dictionary::new(pairs?).map_err(|e| { let middleware_dict =
middleware::containers::Dictionary::new(crate::constants::MAX_DEPTH, pairs?)
.map_err(|e| {
ProcessorError::Internal(format!("Failed to create Dictionary: {}", e)) ProcessorError::Internal(format!("Failed to create Dictionary: {}", e))
})?; })?;
Ok(Value::from(middleware_dict)) Ok(Value::from(middleware_dict))

View file

@ -9,31 +9,32 @@ use serde::{Deserialize, Deserializer, Serialize};
use super::serialization::{ordered_map, ordered_set}; use super::serialization::{ordered_map, ordered_set};
#[cfg(feature = "backend_plonky2")] #[cfg(feature = "backend_plonky2")]
use crate::backends::plonky2::primitives::merkletree::{MerkleProof, MerkleTree}; use crate::backends::plonky2::primitives::merkletree::{MerkleProof, MerkleTree};
use crate::{ use crate::middleware::{hash_value, Error, Hash, Key, RawValue, Result, Value};
constants::MAX_DEPTH,
middleware::{hash_value, Error, Hash, Key, RawValue, Result, Value},
};
/// Dictionary: the user original keys and values are hashed to be used in the leaf. /// Dictionary: the user original keys and values are hashed to be used in the leaf.
/// leaf.key=hash(original_key) /// leaf.key=hash(original_key)
/// leaf.value=hash(original_value) /// leaf.value=hash(original_value)
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize, JsonSchema)]
#[serde(transparent)]
pub struct Dictionary { pub struct Dictionary {
#[serde(skip)] #[serde(skip)]
#[schemars(skip)]
mt: MerkleTree, mt: MerkleTree,
max_depth: usize,
#[serde(serialize_with = "ordered_map")] #[serde(serialize_with = "ordered_map")]
kvs: HashMap<Key, Value>, kvs: HashMap<Key, Value>,
} }
impl Dictionary { impl Dictionary {
pub fn new(kvs: HashMap<Key, Value>) -> Result<Self> { /// max_depth determines the depth of the underlying MerkleTree, allowing to
/// store 2^max_depth elements in the Dictionary
pub fn new(max_depth: usize, kvs: HashMap<Key, Value>) -> Result<Self> {
let kvs_raw: HashMap<RawValue, RawValue> = kvs let kvs_raw: HashMap<RawValue, RawValue> = kvs
.iter() .iter()
.map(|(k, v)| (RawValue(k.hash().0), v.raw())) .map(|(k, v)| (RawValue(k.hash().0), v.raw()))
.collect(); .collect();
Ok(Self { Ok(Self {
mt: MerkleTree::new(MAX_DEPTH, &kvs_raw)?, mt: MerkleTree::new(max_depth, &kvs_raw)?,
max_depth,
kvs, kvs,
}) })
} }
@ -53,20 +54,31 @@ impl Dictionary {
pub fn prove_nonexistence(&self, key: &Key) -> Result<MerkleProof> { pub fn prove_nonexistence(&self, key: &Key) -> Result<MerkleProof> {
Ok(self.mt.prove_nonexistence(&RawValue(key.hash().0))?) Ok(self.mt.prove_nonexistence(&RawValue(key.hash().0))?)
} }
pub fn verify(root: Hash, proof: &MerkleProof, key: &Key, value: &Value) -> Result<()> { pub fn verify(
max_depth: usize,
root: Hash,
proof: &MerkleProof,
key: &Key,
value: &Value,
) -> Result<()> {
let key = RawValue(key.hash().0); let key = RawValue(key.hash().0);
Ok(MerkleTree::verify( Ok(MerkleTree::verify(
MAX_DEPTH, max_depth,
root, root,
proof, proof,
&key, &key,
&value.raw(), &value.raw(),
)?) )?)
} }
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, key: &Key) -> Result<()> { pub fn verify_nonexistence(
max_depth: usize,
root: Hash,
proof: &MerkleProof,
key: &Key,
) -> Result<()> {
let key = RawValue(key.hash().0); let key = RawValue(key.hash().0);
Ok(MerkleTree::verify_nonexistence( Ok(MerkleTree::verify_nonexistence(
MAX_DEPTH, root, proof, &key, max_depth, root, proof, &key,
)?) )?)
} }
// TODO: Rename to dict to be consistent maybe? // TODO: Rename to dict to be consistent maybe?
@ -74,14 +86,6 @@ impl Dictionary {
&self.kvs &self.kvs
} }
} }
// impl<'a> IntoIterator for &'a Dictionary {
// type Item = (&'a RawValue, &'a RawValue);
// type IntoIter = TreeIter<'a>;
//
// fn into_iter(self) -> Self::IntoIter {
// self.mt.iter()
// }
// }
impl PartialEq for Dictionary { impl PartialEq for Dictionary {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
@ -95,36 +99,34 @@ impl<'de> Deserialize<'de> for Dictionary {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let kvs: HashMap<Key, Value> = HashMap::deserialize(deserializer)?; #[derive(Deserialize)]
Dictionary::new(kvs).map_err(serde::de::Error::custom) struct Aux {
#[serde(serialize_with = "ordered_map")]
kvs: HashMap<Key, Value>,
max_depth: usize,
} }
} let aux = Aux::deserialize(deserializer)?;
Dictionary::new(aux.max_depth, aux.kvs).map_err(serde::de::Error::custom)
impl JsonSchema for Dictionary {
fn schema_name() -> String {
"Dictionary".to_string()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
// Just use the schema of HashMap<Key, Value> since that's what we're actually serializing
<HashMap<Key, Value>>::json_schema(gen)
} }
} }
/// Set: the value field of the leaf is unused, and the key contains the hash of the element. /// Set: the value field of the leaf is unused, and the key contains the hash of the element.
/// leaf.key=hash(original_value) /// leaf.key=hash(original_value)
/// leaf.value=0 /// leaf.value=0
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize, JsonSchema)]
#[serde(transparent)]
pub struct Set { pub struct Set {
#[serde(skip)] #[serde(skip)]
#[schemars(skip)]
mt: MerkleTree, mt: MerkleTree,
max_depth: usize,
#[serde(serialize_with = "ordered_set")] #[serde(serialize_with = "ordered_set")]
set: HashSet<Value>, set: HashSet<Value>,
} }
impl Set { impl Set {
pub fn new(set: HashSet<Value>) -> Result<Self> { /// max_depth determines the depth of the underlying MerkleTree, allowing to
/// store 2^max_depth elements in the Array
pub fn new(max_depth: usize, set: HashSet<Value>) -> Result<Self> {
let kvs_raw: HashMap<RawValue, RawValue> = set let kvs_raw: HashMap<RawValue, RawValue> = set
.iter() .iter()
.map(|e| { .map(|e| {
@ -133,7 +135,8 @@ impl Set {
}) })
.collect(); .collect();
Ok(Self { Ok(Self {
mt: MerkleTree::new(MAX_DEPTH, &kvs_raw)?, mt: MerkleTree::new(max_depth, &kvs_raw)?,
max_depth,
set, set,
}) })
} }
@ -152,20 +155,25 @@ impl Set {
let h = hash_value(&value.raw()); let h = hash_value(&value.raw());
Ok(self.mt.prove_nonexistence(&RawValue::from(h))?) Ok(self.mt.prove_nonexistence(&RawValue::from(h))?)
} }
pub fn verify(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> { pub fn verify(max_depth: usize, root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
let h = hash_value(&value.raw()); let h = hash_value(&value.raw());
Ok(MerkleTree::verify( Ok(MerkleTree::verify(
MAX_DEPTH, max_depth,
root, root,
proof, proof,
&RawValue::from(h), &RawValue::from(h),
&RawValue::from(h), &RawValue::from(h),
)?) )?)
} }
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> { pub fn verify_nonexistence(
max_depth: usize,
root: Hash,
proof: &MerkleProof,
value: &Value,
) -> Result<()> {
let h = hash_value(&value.raw()); let h = hash_value(&value.raw());
Ok(MerkleTree::verify_nonexistence( Ok(MerkleTree::verify_nonexistence(
MAX_DEPTH, max_depth,
root, root,
proof, proof,
&RawValue::from(h), &RawValue::from(h),
@ -188,22 +196,14 @@ impl<'de> Deserialize<'de> for Set {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
// Deserialize the set directly #[derive(Deserialize, JsonSchema)]
let set: HashSet<Value> = HashSet::deserialize(deserializer)?; struct Aux {
#[serde(serialize_with = "ordered_set")]
// Create a new Set using the set field set: HashSet<Value>,
Set::new(set).map_err(serde::de::Error::custom) max_depth: usize,
} }
} let aux = Aux::deserialize(deserializer)?;
Set::new(aux.max_depth, aux.set).map_err(serde::de::Error::custom)
impl JsonSchema for Set {
fn schema_name() -> String {
"Set".to_string()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
// Just use the schema of HashSet<Value> since that's what we're actually serializing
<HashSet<Value>>::json_schema(gen)
} }
} }
@ -211,16 +211,19 @@ impl JsonSchema for Set {
/// array index (integer). /// array index (integer).
/// leaf.key=i /// leaf.key=i
/// leaf.value=original_value /// leaf.value=original_value
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize, JsonSchema)]
#[serde(transparent)]
pub struct Array { pub struct Array {
#[serde(skip)] #[serde(skip)]
#[schemars(skip)]
mt: MerkleTree, mt: MerkleTree,
max_depth: usize,
array: Vec<Value>, array: Vec<Value>,
} }
impl Array { impl Array {
pub fn new(array: Vec<Value>) -> Result<Self> { /// max_depth determines the depth of the underlying MerkleTree, allowing to
/// store 2^max_depth elements in the Array
pub fn new(max_depth: usize, array: Vec<Value>) -> Result<Self> {
let kvs_raw: HashMap<RawValue, RawValue> = array let kvs_raw: HashMap<RawValue, RawValue> = array
.iter() .iter()
.enumerate() .enumerate()
@ -228,7 +231,8 @@ impl Array {
.collect(); .collect();
Ok(Self { Ok(Self {
mt: MerkleTree::new(MAX_DEPTH, &kvs_raw)?, mt: MerkleTree::new(max_depth, &kvs_raw)?,
max_depth,
array, array,
}) })
} }
@ -245,9 +249,15 @@ impl Array {
let value = self.array.get(i).expect("valid index"); let value = self.array.get(i).expect("valid index");
Ok((value, mtp)) Ok((value, mtp))
} }
pub fn verify(root: Hash, proof: &MerkleProof, i: usize, value: &Value) -> Result<()> { pub fn verify(
max_depth: usize,
root: Hash,
proof: &MerkleProof,
i: usize,
value: &Value,
) -> Result<()> {
Ok(MerkleTree::verify( Ok(MerkleTree::verify(
MAX_DEPTH, max_depth,
root, root,
proof, proof,
&RawValue::from(i as i64), &RawValue::from(i as i64),
@ -271,18 +281,12 @@ impl<'de> Deserialize<'de> for Array {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let array: Vec<Value> = Vec::deserialize(deserializer)?; #[derive(Deserialize, JsonSchema)]
Array::new(array).map_err(serde::de::Error::custom) struct Aux {
} array: Vec<Value>,
} max_depth: usize,
}
impl JsonSchema for Array { let aux = Aux::deserialize(deserializer)?;
fn schema_name() -> String { Array::new(aux.max_depth, aux.array).map_err(serde::de::Error::custom)
"Array".to_string()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
// Just use the schema of Vec<Value> since that's what we're actually serializing
<Vec<Value>>::json_schema(gen)
} }
} }

View file

@ -597,6 +597,7 @@ impl fmt::Display for PodType {
} }
} }
/// Params: non dynamic parameters that define the circuit.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Hash)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Params { pub struct Params {
@ -612,10 +613,14 @@ pub struct Params {
// max number of operations using custom predicates that can be verified in the MainPod // max number of operations using custom predicates that can be verified in the MainPod
pub max_custom_predicate_verifications: usize, pub max_custom_predicate_verifications: usize,
pub max_custom_predicate_wildcards: usize, pub max_custom_predicate_wildcards: usize,
// maximum number of merkle proofs // maximum number of merkle proofs used for container operations
pub max_merkle_proofs: usize, pub max_merkle_proofs_containers: usize,
// maximum depth for merkle tree gadget // maximum depth for merkle tree gadget used for container operations
pub max_depth_mt_gadget: usize, pub max_depth_mt_containers: usize,
// maximum depth of the merkle tree gadget used for verifier_data membership
// check. This allows creating verifying sets of pod circuits of size
// 2^max_depth_mt_vds.
pub max_depth_mt_vds: usize,
// //
// The following parameters define how a pod id is calculated. They need to be the same among // The following parameters define how a pod id is calculated. They need to be the same among
// different circuits to be compatible in their verification. // different circuits to be compatible in their verification.
@ -651,8 +656,9 @@ impl Default for Params {
max_custom_predicate_arity: 5, max_custom_predicate_arity: 5,
max_custom_predicate_wildcards: 10, max_custom_predicate_wildcards: 10,
max_custom_batch_size: 5, max_custom_batch_size: 5,
max_merkle_proofs: 5, max_merkle_proofs_containers: 5,
max_depth_mt_gadget: 32, max_depth_mt_containers: 32,
max_depth_mt_vds: 6, // up to 64 (2^6) different pod circuits
} }
} }
} }
@ -843,13 +849,14 @@ pub struct MainPodInputs<'a> {
/// Statements that need to be made public (they can come from input pods or input /// Statements that need to be made public (they can come from input pods or input
/// statements) /// statements)
pub public_statements: &'a [Statement], pub public_statements: &'a [Statement],
pub vds_root: Hash, // TODO: Figure out if we use Hash or a Map here https://github.com/0xPARC/pod2/issues/249 pub vds_set: VDSet,
} }
pub trait PodProver { pub trait PodProver {
fn prove( fn prove(
&self, &self,
params: &Params, params: &Params,
vd_set: &VDSet,
inputs: MainPodInputs, inputs: MainPodInputs,
) -> Result<Box<dyn RecursivePod>, Box<DynError>>; ) -> Result<Box<dyn RecursivePod>, Box<DynError>>;
} }