Complete the verification in MainMockPod (#302)
- Update the `RecursivePod` trait to return `vd_set` instead of `vds_root` - A native verifier requires the entire set to reason about the circuits that have been used in the recursive tree - Implement serialization/deserialization for `VDSet` - Remove `DynError` and use `BackendError` instead for middleware functions that wrap or define trait functions implemented in the backend. This is based on the fact that we will only have a single backend enabled at a time, so there's no need for a `dyn Error` - Move the implementations of `_verify` functions to `verify` and similarly for `_prove` - Complete the verification of a MockMainPod: the verification of input pods was missing. The inclusion of these input pods in the serialization was also missing. With this change a `MockMainPod` will grow after each recursion. This was expected from the design but was not the case because of the missing recursive native verification implementation. * apply feedback from @arnaucube
This commit is contained in:
parent
df8fce76d6
commit
6249406cb2
16 changed files with 427 additions and 350 deletions
|
|
@ -4,10 +4,11 @@
|
||||||
|
|
||||||
use plonky2::{
|
use plonky2::{
|
||||||
field::{extension::quadratic::QuadraticExtension, goldilocks_field::GoldilocksField},
|
field::{extension::quadratic::QuadraticExtension, goldilocks_field::GoldilocksField},
|
||||||
hash::poseidon::PoseidonHash,
|
hash::{hash_types, poseidon::PoseidonHash},
|
||||||
plonk::{circuit_builder, circuit_data, config::GenericConfig, proof},
|
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
|
/// F is the native field we use everywhere. Currently it's Goldilocks from plonky2
|
||||||
pub type F = GoldilocksField;
|
pub type F = GoldilocksField;
|
||||||
|
|
@ -36,12 +37,10 @@ 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>;
|
||||||
|
pub type HashOut = hash_types::HashOut<F>;
|
||||||
|
|
||||||
use std::{collections::HashMap, sync::LazyLock};
|
use std::{collections::HashMap, sync::LazyLock};
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
use plonky2::hash::hash_types::HashOut;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backends::plonky2::{
|
backends::plonky2::{
|
||||||
emptypod::STANDARD_EMPTY_POD_DATA, primitives::merkletree::MerkleClaimAndProof,
|
emptypod::STANDARD_EMPTY_POD_DATA, primitives::merkletree::MerkleClaimAndProof,
|
||||||
|
|
@ -65,38 +64,32 @@ pub static DEFAULT_VD_SET: LazyLock<VDSet> = LazyLock::new(|| {
|
||||||
/// verifying the recursive proofs of previous PODs appears in the VDSet.
|
/// 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
|
/// The VDSet struct that allows to get the specific merkle proofs for the given
|
||||||
/// verifier_data.
|
/// verifier_data.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Serialize, JsonSchema)]
|
||||||
pub struct VDSet {
|
pub struct VDSet {
|
||||||
|
#[serde(skip)]
|
||||||
|
#[schemars(skip)]
|
||||||
root: Hash,
|
root: Hash,
|
||||||
// (verifier_data's hash, merkleproof)
|
// (verifier_data's hash, merkleproof)
|
||||||
proofs_map: HashMap<HashOut<F>, MerkleClaimAndProof>,
|
#[serde(skip)]
|
||||||
|
#[schemars(skip)]
|
||||||
|
proofs_map: HashMap<Hash, MerkleClaimAndProof>,
|
||||||
|
tree_depth: usize,
|
||||||
|
vds_hashes: Vec<Hash>,
|
||||||
}
|
}
|
||||||
impl VDSet {
|
|
||||||
/// builds the verifier_datas tree, and returns the root and the proofs
|
|
||||||
pub fn new(tree_depth: usize, vds: &[VerifierOnlyCircuitData]) -> Result<Self> {
|
|
||||||
// compute the verifier_data's hashes
|
|
||||||
let vds_hashes: Vec<HashOut<F>> = vds
|
|
||||||
.iter()
|
|
||||||
.map(crate::backends::plonky2::recursion::circuit::hash_verifier_data)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
|
impl VDSet {
|
||||||
|
fn new_from_vds_hashes(tree_depth: usize, mut vds_hashes: Vec<Hash>) -> Result<Self> {
|
||||||
// before using the hash values, sort them, so that each set of
|
// before using the hash values, sort them, so that each set of
|
||||||
// verifier_datas gets the same VDSet root
|
// verifier_datas gets the same VDSet root
|
||||||
let vds_hashes: Vec<&HashOut<F>> = vds_hashes
|
vds_hashes.sort();
|
||||||
.iter()
|
|
||||||
.sorted_by_key(|vd| RawValue(vd.elements))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let array = Array::new(
|
let array = Array::new(
|
||||||
tree_depth,
|
tree_depth,
|
||||||
vds_hashes
|
vds_hashes.iter().map(|vd| Value::from(*vd)).collect(),
|
||||||
.iter()
|
|
||||||
.map(|vd| Value::from(RawValue(vd.elements)))
|
|
||||||
.collect(),
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let root = array.commitment();
|
let root = array.commitment();
|
||||||
let mut proofs_map = HashMap::<HashOut<F>, MerkleClaimAndProof>::new();
|
let mut proofs_map = HashMap::<Hash, MerkleClaimAndProof>::new();
|
||||||
|
|
||||||
for (i, vd) in vds_hashes.iter().enumerate() {
|
for (i, vd) in vds_hashes.iter().enumerate() {
|
||||||
let (value, proof) = array.prove(i)?;
|
let (value, proof) = array.prove(i)?;
|
||||||
|
|
@ -106,9 +99,29 @@ impl VDSet {
|
||||||
value: value.raw(),
|
value: value.raw(),
|
||||||
proof,
|
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<Self> {
|
||||||
|
// compute the verifier_data's hashes
|
||||||
|
let vds_hashes: Vec<HashOut> = vds
|
||||||
|
.iter()
|
||||||
|
.map(crate::backends::plonky2::recursion::circuit::hash_verifier_data)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let vds_hashes: Vec<Hash> = vds_hashes
|
||||||
|
.into_iter()
|
||||||
|
.map(|h| Hash(h.elements))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
Self::new_from_vds_hashes(tree_depth, vds_hashes)
|
||||||
}
|
}
|
||||||
pub fn root(&self) -> Hash {
|
pub fn root(&self) -> Hash {
|
||||||
self.root
|
self.root
|
||||||
|
|
@ -120,9 +133,11 @@ impl VDSet {
|
||||||
) -> Result<Vec<MerkleClaimAndProof>> {
|
) -> Result<Vec<MerkleClaimAndProof>> {
|
||||||
let mut proofs: Vec<MerkleClaimAndProof> = vec![];
|
let mut proofs: Vec<MerkleClaimAndProof> = vec![];
|
||||||
for vd in vds {
|
for vd in vds {
|
||||||
|
let verifier_data_hash =
|
||||||
|
crate::backends::plonky2::recursion::circuit::hash_verifier_data(vd);
|
||||||
let p = self
|
let p = self
|
||||||
.proofs_map
|
.proofs_map
|
||||||
.get(&crate::backends::plonky2::recursion::circuit::hash_verifier_data(vd))
|
.get(&Hash(verifier_data_hash.elements))
|
||||||
.ok_or(crate::middleware::Error::custom(
|
.ok_or(crate::middleware::Error::custom(
|
||||||
"verifier_data not found in VDSet".to_string(),
|
"verifier_data not found in VDSet".to_string(),
|
||||||
))?;
|
))?;
|
||||||
|
|
@ -130,4 +145,24 @@ impl VDSet {
|
||||||
}
|
}
|
||||||
Ok(proofs)
|
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<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Aux {
|
||||||
|
tree_depth: usize,
|
||||||
|
vds_hashes: Vec<Hash>,
|
||||||
|
}
|
||||||
|
let aux = Aux::deserialize(deserializer)?;
|
||||||
|
VDSet::new_from_vds_hashes(aux.tree_depth, aux.vds_hashes).map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1528,7 +1528,7 @@ impl InnerCircuit for 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_set.root());
|
let empty_pod = EmptyPod::new_boxed(&self.params, input.vds_set.clone());
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ use crate::{
|
||||||
serialize_proof, DEFAULT_PARAMS, STANDARD_REC_MAIN_POD_CIRCUIT_DATA,
|
serialize_proof, DEFAULT_PARAMS, STANDARD_REC_MAIN_POD_CIRCUIT_DATA,
|
||||||
},
|
},
|
||||||
middleware::{
|
middleware::{
|
||||||
self, AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement,
|
self, AnchoredKey, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, ToFields,
|
||||||
ToFields, Value, VerifierOnlyCircuitData, F, HASH_SIZE, KEY_TYPE, SELF,
|
VDSet, Value, VerifierOnlyCircuitData, F, HASH_SIZE, KEY_TYPE, SELF,
|
||||||
},
|
},
|
||||||
timed,
|
timed,
|
||||||
};
|
};
|
||||||
|
|
@ -77,7 +77,7 @@ impl EmptyPodVerifyTarget {
|
||||||
pub struct EmptyPod {
|
pub struct EmptyPod {
|
||||||
params: Params,
|
params: Params,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
proof: Proof,
|
proof: Proof,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,34 +106,45 @@ static EMPTY_POD_CACHE: LazyLock<Mutex<HashMap<Hash, EmptyPod>>> =
|
||||||
LazyLock::new(|| Mutex::new(HashMap::new()));
|
LazyLock::new(|| Mutex::new(HashMap::new()));
|
||||||
|
|
||||||
impl EmptyPod {
|
impl EmptyPod {
|
||||||
pub fn _prove(params: &Params, vds_root: Hash) -> Result<EmptyPod> {
|
pub fn new(params: &Params, vd_set: VDSet) -> Result<EmptyPod> {
|
||||||
let (empty_pod_verify_target, data) = &*STANDARD_EMPTY_POD_DATA;
|
let (empty_pod_verify_target, data) = &*STANDARD_EMPTY_POD_DATA;
|
||||||
|
|
||||||
let mut pw = PartialWitness::<F>::new();
|
let mut pw = PartialWitness::<F>::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 proof = timed!("EmptyPod prove", data.prove(pw)?);
|
||||||
let id = &proof.public_inputs[PI_OFFSET_ID..PI_OFFSET_ID + HASH_SIZE];
|
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]]));
|
let id = PodId(Hash([id[0], id[1], id[2], id[3]]));
|
||||||
Ok(EmptyPod {
|
Ok(EmptyPod {
|
||||||
params: params.clone(),
|
params: params.clone(),
|
||||||
id,
|
id,
|
||||||
vds_root,
|
vd_set,
|
||||||
proof: proof.proof,
|
proof: proof.proof,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn new_boxed(params: &Params, vds_root: Hash) -> Box<dyn RecursivePod> {
|
pub fn new_boxed(params: &Params, vd_set: VDSet) -> Box<dyn RecursivePod> {
|
||||||
let default_params = &*DEFAULT_PARAMS;
|
let default_params = &*DEFAULT_PARAMS;
|
||||||
assert_eq!(default_params.id_params(), params.id_params());
|
assert_eq!(default_params.id_params(), params.id_params());
|
||||||
|
|
||||||
let empty_pod = EMPTY_POD_CACHE
|
let empty_pod = EMPTY_POD_CACHE
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(vds_root)
|
.entry(vd_set.root())
|
||||||
.or_insert_with(|| Self::_prove(params, vds_root).expect("prove EmptyPod"))
|
.or_insert_with(|| Self::new(params, vd_set).expect("prove EmptyPod"))
|
||||||
.clone();
|
.clone();
|
||||||
Box::new(empty_pod)
|
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
|
let statements = self
|
||||||
.pub_self_statements()
|
.pub_self_statements()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -147,7 +158,7 @@ impl EmptyPod {
|
||||||
let public_inputs = id
|
let public_inputs = id
|
||||||
.to_fields(&self.params)
|
.to_fields(&self.params)
|
||||||
.iter()
|
.iter()
|
||||||
.chain(self.vds_root.0.iter())
|
.chain(self.vd_set.root().0.iter())
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
||||||
|
|
@ -156,21 +167,7 @@ impl EmptyPod {
|
||||||
proof: self.proof.clone(),
|
proof: self.proof.clone(),
|
||||||
public_inputs,
|
public_inputs,
|
||||||
})
|
})
|
||||||
.map_err(|e| Error::custom(format!("EmptyPod proof verification failure: {:?}", e)))
|
.map_err(|e| Error::plonky2_proof_fail("EmptyPod", e))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct Data {
|
|
||||||
proof: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pod for EmptyPod {
|
|
||||||
fn params(&self) -> &Params {
|
|
||||||
&self.params
|
|
||||||
}
|
|
||||||
fn verify(&self) -> Result<(), Box<DynError>> {
|
|
||||||
Ok(self._verify()?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self) -> PodId {
|
fn id(&self) -> PodId {
|
||||||
|
|
@ -200,22 +197,22 @@ impl RecursivePod for EmptyPod {
|
||||||
fn proof(&self) -> Proof {
|
fn proof(&self) -> Proof {
|
||||||
self.proof.clone()
|
self.proof.clone()
|
||||||
}
|
}
|
||||||
fn vds_root(&self) -> Hash {
|
fn vd_set(&self) -> &VDSet {
|
||||||
self.vds_root
|
&self.vd_set
|
||||||
}
|
}
|
||||||
fn deserialize_data(
|
fn deserialize_data(
|
||||||
params: Params,
|
params: Params,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
|
) -> Result<Box<dyn RecursivePod>> {
|
||||||
let data: Data = serde_json::from_value(data)?;
|
let data: Data = serde_json::from_value(data)?;
|
||||||
let circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA;
|
let circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA;
|
||||||
let proof = deserialize_proof(&circuit_data.common, &data.proof)?;
|
let proof = deserialize_proof(&circuit_data.common, &data.proof)?;
|
||||||
Ok(Box::new(Self {
|
Ok(Box::new(Self {
|
||||||
params,
|
params,
|
||||||
id,
|
id,
|
||||||
vds_root,
|
vd_set,
|
||||||
proof,
|
proof,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
@ -224,13 +221,12 @@ 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() {
|
||||||
let params = Params::default();
|
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();
|
empty_pod.verify().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ pub enum Error {
|
||||||
},
|
},
|
||||||
#[error("anyhow::Error: {0}")]
|
#[error("anyhow::Error: {0}")]
|
||||||
Anyhow(#[from] anyhow::Error),
|
Anyhow(#[from] anyhow::Error),
|
||||||
#[error("Plonky2 proof failed to verify: {0}")]
|
#[error("Plonky2 proof failed to verify {0}: {1}")]
|
||||||
Plonky2ProofFail(anyhow::Error),
|
Plonky2ProofFail(String, anyhow::Error),
|
||||||
#[error("base64::DecodeError: {0}")]
|
#[error("base64::DecodeError: {0}")]
|
||||||
Base64Decode(#[from] base64::DecodeError),
|
Base64Decode(#[from] base64::DecodeError),
|
||||||
#[error("serde_json::Error: {0}")]
|
#[error("serde_json::Error: {0}")]
|
||||||
|
|
@ -70,8 +70,8 @@ impl Error {
|
||||||
pub fn custom(s: String) -> Self {
|
pub fn custom(s: String) -> Self {
|
||||||
new!(Custom(s))
|
new!(Custom(s))
|
||||||
}
|
}
|
||||||
pub fn plonky2_proof_fail(e: anyhow::Error) -> Self {
|
pub fn plonky2_proof_fail(context: impl Into<String>, e: anyhow::Error) -> Self {
|
||||||
Self::Plonky2ProofFail(e)
|
Self::Plonky2ProofFail(context.into(), e)
|
||||||
}
|
}
|
||||||
pub fn key_not_found() -> Self {
|
pub fn key_not_found() -> Self {
|
||||||
new!(KeyNotFound)
|
new!(KeyNotFound)
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,15 @@ use crate::{
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
mock::{emptypod::MockEmptyPod, signedpod::MockSignedPod},
|
mock::{emptypod::MockEmptyPod, signedpod::MockSignedPod},
|
||||||
primitives::merkletree::MerkleClaimAndProof,
|
primitives::merkletree::MerkleClaimAndProof,
|
||||||
recursion::{RecursiveCircuit, RecursiveParams},
|
recursion::{hash_verifier_data, RecursiveCircuit, RecursiveParams},
|
||||||
serialize_proof,
|
serialize_proof,
|
||||||
signedpod::SignedPod,
|
signedpod::SignedPod,
|
||||||
STANDARD_REC_MAIN_POD_CIRCUIT_DATA,
|
STANDARD_REC_MAIN_POD_CIRCUIT_DATA,
|
||||||
},
|
},
|
||||||
middleware::{
|
middleware::{
|
||||||
self, resolve_wildcard_values, value_from_op, AnchoredKey, CustomPredicateBatch, DynError,
|
self, resolve_wildcard_values, value_from_op, AnchoredKey, CustomPredicateBatch, Hash,
|
||||||
Hash, MainPodInputs, NativeOperation, OperationType, Params, Pod, PodId, PodProver,
|
MainPodInputs, NativeOperation, OperationType, Params, Pod, PodId, PodProver, PodType,
|
||||||
PodType, RecursivePod, StatementArg, ToFields, VDSet, F, KEY_TYPE, SELF,
|
RecursivePod, StatementArg, ToFields, VDSet, F, KEY_TYPE, SELF,
|
||||||
},
|
},
|
||||||
timed,
|
timed,
|
||||||
};
|
};
|
||||||
|
|
@ -294,9 +294,9 @@ pub(crate) fn layout_statements(
|
||||||
let empty_pod_box: Box<dyn RecursivePod> =
|
let empty_pod_box: Box<dyn RecursivePod> =
|
||||||
if mock || inputs.recursive_pods.len() == params.max_input_recursive_pods {
|
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
|
// 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 {
|
} 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();
|
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);
|
||||||
|
|
@ -432,8 +432,13 @@ pub(crate) fn process_public_statements_operations(
|
||||||
|
|
||||||
pub struct Prover {}
|
pub struct Prover {}
|
||||||
|
|
||||||
impl Prover {
|
impl PodProver for Prover {
|
||||||
fn _prove(&self, params: &Params, vd_set: &VDSet, inputs: MainPodInputs) -> Result<MainPod> {
|
fn prove(
|
||||||
|
&self,
|
||||||
|
params: &Params,
|
||||||
|
vd_set: &VDSet,
|
||||||
|
inputs: MainPodInputs,
|
||||||
|
) -> Result<Box<dyn RecursivePod>> {
|
||||||
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(
|
||||||
|
|
@ -466,9 +471,9 @@ impl Prover {
|
||||||
// Pad input recursive pods with empty pods if necessary
|
// Pad input recursive pods with empty pods if necessary
|
||||||
let empty_pod = if inputs.recursive_pods.len() == params.max_input_recursive_pods {
|
let empty_pod = if inputs.recursive_pods.len() == params.max_input_recursive_pods {
|
||||||
// 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, inputs.vd_set.clone())
|
||||||
} else {
|
} else {
|
||||||
EmptyPod::new_boxed(params, inputs.vds_set.root())
|
EmptyPod::new_boxed(params, inputs.vd_set.clone())
|
||||||
};
|
};
|
||||||
let inputs = MainPodInputs {
|
let inputs = MainPodInputs {
|
||||||
recursive_pods: &inputs
|
recursive_pods: &inputs
|
||||||
|
|
@ -515,10 +520,10 @@ impl Prover {
|
||||||
.recursive_pods
|
.recursive_pods
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pod| {
|
.map(|pod| {
|
||||||
assert_eq!(inputs.vds_set.root(), pod.vds_root());
|
assert_eq!(inputs.vd_set.root(), pod.vd_set().root());
|
||||||
ProofWithPublicInputs {
|
ProofWithPublicInputs {
|
||||||
proof: pod.proof(),
|
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();
|
.collect_vec();
|
||||||
|
|
@ -531,7 +536,7 @@ impl Prover {
|
||||||
let vd_mt_proofs = vd_set.get_vds_proofs(&verifier_datas)?;
|
let vd_mt_proofs = vd_set.get_vds_proofs(&verifier_datas)?;
|
||||||
|
|
||||||
let input = MainPodVerifyInput {
|
let input = MainPodVerifyInput {
|
||||||
vds_set: inputs.vds_set.clone(),
|
vds_set: inputs.vd_set.clone(),
|
||||||
vd_mt_proofs,
|
vd_mt_proofs,
|
||||||
signed_pods: signed_pods_input,
|
signed_pods: signed_pods_input,
|
||||||
recursive_pods_pub_self_statements,
|
recursive_pods_pub_self_statements,
|
||||||
|
|
@ -546,24 +551,13 @@ impl Prover {
|
||||||
main_pod.prove(&input, proofs, verifier_datas)?
|
main_pod.prove(&input, proofs, verifier_datas)?
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(MainPod {
|
Ok(Box::new(MainPod {
|
||||||
params: params.clone(),
|
params: params.clone(),
|
||||||
id,
|
id,
|
||||||
vds_root: inputs.vds_set.root(),
|
vd_set: inputs.vd_set,
|
||||||
public_statements,
|
public_statements,
|
||||||
proof: proof_with_pis.proof,
|
proof: proof_with_pis.proof,
|
||||||
})
|
}))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PodProver for Prover {
|
|
||||||
fn prove(
|
|
||||||
&self,
|
|
||||||
params: &Params,
|
|
||||||
vd_set: &VDSet,
|
|
||||||
inputs: MainPodInputs,
|
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
|
|
||||||
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
|
/// the succession of recursive MainPods, which when proving the POD, it is
|
||||||
/// proven that all the recursive proofs that are being verified in-circuit
|
/// proven that all the recursive proofs that are being verified in-circuit
|
||||||
/// use one of the verifier_data's contained in the VDSet.
|
/// use one of the verifier_data's contained in the VDSet.
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
public_statements: Vec<Statement>,
|
public_statements: Vec<Statement>,
|
||||||
proof: Proof,
|
proof: Proof,
|
||||||
}
|
}
|
||||||
|
|
@ -605,13 +599,37 @@ struct Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MainPod {
|
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
|
// 2. get the id out of the public statements
|
||||||
let id = PodId(calculate_id(&self.public_statements, &self.params));
|
let id = PodId(calculate_id(&self.public_statements, &self.params));
|
||||||
if id != self.id {
|
if id != self.id {
|
||||||
return Err(Error::id_not_equal(self.id, 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
|
// 1, 3, 4, 5 verification via the zkSNARK proof
|
||||||
let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA;
|
let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA;
|
||||||
// TODO: cache these artefacts
|
// TODO: cache these artefacts
|
||||||
|
|
@ -625,7 +643,7 @@ impl MainPod {
|
||||||
let public_inputs = id
|
let public_inputs = id
|
||||||
.to_fields(&self.params)
|
.to_fields(&self.params)
|
||||||
.iter()
|
.iter()
|
||||||
.chain(self.vds_root.0.iter())
|
.chain(self.vd_set.root().0.iter())
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
circuit_data
|
circuit_data
|
||||||
|
|
@ -633,28 +651,7 @@ impl MainPod {
|
||||||
proof: self.proof.clone(),
|
proof: self.proof.clone(),
|
||||||
public_inputs,
|
public_inputs,
|
||||||
})
|
})
|
||||||
.map_err(|e| Error::custom(format!("MainPod proof verification failure: {:?}", e)))
|
.map_err(|e| Error::plonky2_proof_fail("MainPod", 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<DynError>> {
|
|
||||||
Ok(self._verify()?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self) -> PodId {
|
fn id(&self) -> PodId {
|
||||||
|
|
@ -689,22 +686,22 @@ impl RecursivePod for MainPod {
|
||||||
fn proof(&self) -> Proof {
|
fn proof(&self) -> Proof {
|
||||||
self.proof.clone()
|
self.proof.clone()
|
||||||
}
|
}
|
||||||
fn vds_root(&self) -> Hash {
|
fn vd_set(&self) -> &VDSet {
|
||||||
self.vds_root
|
&self.vd_set
|
||||||
}
|
}
|
||||||
fn deserialize_data(
|
fn deserialize_data(
|
||||||
params: Params,
|
params: Params,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
|
) -> Result<Box<dyn RecursivePod>> {
|
||||||
let data: Data = serde_json::from_value(data)?;
|
let data: Data = serde_json::from_value(data)?;
|
||||||
let common = get_common_data(¶ms)?;
|
let common = get_common_data(¶ms)?;
|
||||||
let proof = deserialize_proof(&common, &data.proof)?;
|
let proof = deserialize_proof(&common, &data.proof)?;
|
||||||
Ok(Box::new(Self {
|
Ok(Box::new(Self {
|
||||||
params,
|
params,
|
||||||
id,
|
id,
|
||||||
vds_root,
|
vd_set,
|
||||||
proof,
|
proof,
|
||||||
public_statements: data.public_statements,
|
public_statements: data.public_statements,
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ use crate::{
|
||||||
mainpod::{self, calculate_id},
|
mainpod::{self, calculate_id},
|
||||||
},
|
},
|
||||||
middleware::{
|
middleware::{
|
||||||
AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, Value,
|
AnchoredKey, Params, Pod, PodId, PodType, RecursivePod, Statement, VDSet, Value, KEY_TYPE,
|
||||||
KEY_TYPE, SELF,
|
SELF,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -16,6 +16,7 @@ use crate::{
|
||||||
pub struct MockEmptyPod {
|
pub struct MockEmptyPod {
|
||||||
params: Params,
|
params: Params,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
|
vd_set: VDSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_statement() -> Statement {
|
fn type_statement() -> Statement {
|
||||||
|
|
@ -26,15 +27,22 @@ fn type_statement() -> Statement {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockEmptyPod {
|
impl MockEmptyPod {
|
||||||
pub fn new_boxed(params: &Params) -> Box<dyn RecursivePod> {
|
pub fn new_boxed(params: &Params, vd_set: VDSet) -> Box<dyn RecursivePod> {
|
||||||
let statements = [mainpod::Statement::from(type_statement())];
|
let statements = [mainpod::Statement::from(type_statement())];
|
||||||
let id = PodId(calculate_id(&statements, params));
|
let id = PodId(calculate_id(&statements, params));
|
||||||
Box::new(Self {
|
Box::new(Self {
|
||||||
params: params.clone(),
|
params: params.clone(),
|
||||||
id,
|
id,
|
||||||
|
vd_set,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn _verify(&self) -> Result<()> {
|
}
|
||||||
|
|
||||||
|
impl Pod for MockEmptyPod {
|
||||||
|
fn params(&self) -> &Params {
|
||||||
|
&self.params
|
||||||
|
}
|
||||||
|
fn verify(&self) -> Result<()> {
|
||||||
let statements = self
|
let statements = self
|
||||||
.pub_self_statements()
|
.pub_self_statements()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -46,15 +54,6 @@ impl MockEmptyPod {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Pod for MockEmptyPod {
|
|
||||||
fn params(&self) -> &Params {
|
|
||||||
&self.params
|
|
||||||
}
|
|
||||||
fn verify(&self) -> Result<(), Box<DynError>> {
|
|
||||||
Ok(self._verify()?)
|
|
||||||
}
|
|
||||||
fn id(&self) -> PodId {
|
fn id(&self) -> PodId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
@ -77,16 +76,16 @@ impl RecursivePod for MockEmptyPod {
|
||||||
fn proof(&self) -> Proof {
|
fn proof(&self) -> Proof {
|
||||||
panic!("MockEmptyPod can't be verified in a recursive MainPod circuit");
|
panic!("MockEmptyPod can't be verified in a recursive MainPod circuit");
|
||||||
}
|
}
|
||||||
fn vds_root(&self) -> Hash {
|
fn vd_set(&self) -> &VDSet {
|
||||||
panic!("MockEmptyPod can't be verified in a recursive MainPod circuit");
|
&self.vd_set
|
||||||
}
|
}
|
||||||
fn deserialize_data(
|
fn deserialize_data(
|
||||||
params: Params,
|
params: Params,
|
||||||
_data: serde_json::Value,
|
_data: serde_json::Value,
|
||||||
_vds_root: Hash,
|
vd_set: VDSet,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
|
) -> Result<Box<dyn RecursivePod>> {
|
||||||
Ok(Box::new(Self { params, id }))
|
Ok(Box::new(Self { params, id, vd_set }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,7 +97,7 @@ pub mod tests {
|
||||||
fn test_mock_empty_pod() {
|
fn test_mock_empty_pod() {
|
||||||
let params = Params::default();
|
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();
|
empty_pod.verify().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// MainPod
|
// MainPod
|
||||||
//
|
//
|
||||||
|
|
||||||
use std::fmt;
|
use std::{fmt, iter};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -16,12 +16,14 @@ use crate::{
|
||||||
process_private_statements_operations, process_public_statements_operations, Operation,
|
process_private_statements_operations, process_public_statements_operations, Operation,
|
||||||
Statement,
|
Statement,
|
||||||
},
|
},
|
||||||
|
mock::{emptypod::MockEmptyPod, signedpod::MockSignedPod},
|
||||||
primitives::merkletree::MerkleClaimAndProof,
|
primitives::merkletree::MerkleClaimAndProof,
|
||||||
|
recursion::hash_verifier_data,
|
||||||
},
|
},
|
||||||
middleware::{
|
middleware::{
|
||||||
self, hash_str, AnchoredKey, DynError, Hash, MainPodInputs, NativeOperation,
|
self, deserialize_pod, deserialize_signed_pod, hash_str, AnchoredKey, Hash, MainPodInputs,
|
||||||
NativePredicate, OperationType, Params, Pod, PodId, PodProver, PodType, Predicate,
|
NativeOperation, NativePredicate, OperationType, Params, Pod, PodId, PodProver, PodType,
|
||||||
RecursivePod, StatementArg, VDSet, KEY_TYPE, SELF,
|
Predicate, RecursivePod, StatementArg, VDSet, Value, KEY_TYPE, SELF,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -33,58 +35,65 @@ impl PodProver for MockProver {
|
||||||
params: &Params,
|
params: &Params,
|
||||||
_vd_set: &VDSet,
|
_vd_set: &VDSet,
|
||||||
inputs: MainPodInputs,
|
inputs: MainPodInputs,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
|
) -> Result<Box<dyn RecursivePod>> {
|
||||||
Ok(Box::new(MockMainPod::new(params, inputs)?))
|
Ok(Box::new(MockMainPod::new(params, inputs)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MockMainPod {
|
pub struct MockMainPod {
|
||||||
params: Params,
|
params: Params,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
// input_signed_pods: Vec<Box<dyn Pod>>,
|
input_signed_pods: Vec<Box<dyn Pod>>,
|
||||||
// input_main_pods: Vec<Box<dyn Pod>>,
|
input_recursive_pods: Vec<Box<dyn RecursivePod>>,
|
||||||
// New statements introduced by this pod
|
// All statements (inherited + newly introduced by this pod)
|
||||||
// input_statements: Vec<Statement>,
|
|
||||||
public_statements: Vec<Statement>,
|
|
||||||
operations: Vec<Operation>,
|
|
||||||
// All statements (inherited + new)
|
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
|
operations: Vec<Operation>,
|
||||||
|
// public subset of the `statements` vector
|
||||||
|
public_statements: Vec<Statement>,
|
||||||
// All Merkle proofs
|
// All Merkle proofs
|
||||||
// TODO: Use a backend-specific representation
|
merkle_proofs_containers: Vec<MerkleClaimAndProof>,
|
||||||
merkle_proofs: Vec<MerkleClaimAndProof>,
|
|
||||||
// TODO: Add input pods
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for MockMainPod {
|
impl fmt::Display for MockMainPod {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
writeln!(f, "MockMainPod ({}):", self.id)?;
|
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_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_input_statements = self.offset_input_statements();
|
||||||
let offset_public_statements = self.offset_public_statements();
|
let offset_public_statements = self.offset_public_statements();
|
||||||
for (i, st) in self.statements.iter().enumerate() {
|
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)
|
&& ((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!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
" from input SignedPod {}:",
|
" from input SignedPod {} (id={}, type={:?}):",
|
||||||
i / self.params.max_signed_pod_values
|
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_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)
|
== 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!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
" from input MainPod {}:",
|
" from input recursive Pod {} (id={}, type={:?}):",
|
||||||
(i - offset_input_main_pods) / self.params.max_signed_pod_values
|
index, id, pod_type
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if i == offset_input_statements {
|
if i == offset_input_statements {
|
||||||
|
|
@ -134,6 +143,8 @@ struct Data {
|
||||||
operations: Vec<Operation>,
|
operations: Vec<Operation>,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
merkle_proofs: Vec<MerkleClaimAndProof>,
|
merkle_proofs: Vec<MerkleClaimAndProof>,
|
||||||
|
input_signed_pods: Vec<(usize, PodId, serde_json::Value)>,
|
||||||
|
input_recursive_pods: Vec<(usize, Params, PodId, VDSet, serde_json::Value)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inputs are sorted as:
|
/// Inputs are sorted as:
|
||||||
|
|
@ -145,12 +156,12 @@ impl MockMainPod {
|
||||||
fn offset_input_signed_pods() -> usize {
|
fn offset_input_signed_pods() -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
fn offset_input_main_pods(&self) -> usize {
|
fn offset_input_recursive_pods(&self) -> usize {
|
||||||
Self::offset_input_signed_pods()
|
Self::offset_input_signed_pods()
|
||||||
+ self.params.max_input_signed_pods * self.params.max_signed_pod_values
|
+ self.params.max_input_signed_pods * self.params.max_signed_pod_values
|
||||||
}
|
}
|
||||||
fn offset_input_statements(&self) -> usize {
|
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
|
+ self.params.max_input_recursive_pods * self.params.max_input_pods_public_statements
|
||||||
}
|
}
|
||||||
fn offset_public_statements(&self) -> usize {
|
fn offset_public_statements(&self) -> usize {
|
||||||
|
|
@ -158,8 +169,6 @@ impl MockMainPod {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(params: &Params, inputs: MainPodInputs) -> Result<Self> {
|
pub fn new(params: &Params, inputs: MainPodInputs) -> Result<Self> {
|
||||||
// TODO: Insert a new public statement of ValueOf with `key=KEY_TYPE,
|
|
||||||
// value=PodType::MockMainPod`
|
|
||||||
let (statements, public_statements) = layout_statements(params, true, &inputs)?;
|
let (statements, public_statements) = layout_statements(params, true, &inputs)?;
|
||||||
// Extract Merkle proofs and pad.
|
// Extract Merkle proofs and pad.
|
||||||
let merkle_proofs = extract_merkle_proofs(params, inputs.operations, inputs.statements)?;
|
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
|
// get the id out of the public statements
|
||||||
let id: PodId = PodId(calculate_id(&public_statements, params));
|
let id: PodId = PodId(calculate_id(&public_statements, params));
|
||||||
|
|
||||||
|
let pad_signed_pod: Box<dyn Pod> = Box::new(MockSignedPod::dummy());
|
||||||
|
let input_signed_pods: Vec<Box<dyn Pod>> = 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<Box<dyn RecursivePod>> = 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 {
|
Ok(Self {
|
||||||
params: params.clone(),
|
params: params.clone(),
|
||||||
id,
|
id,
|
||||||
vds_root: inputs.vds_set.root(),
|
vd_set: inputs.vd_set,
|
||||||
// input_signed_pods,
|
input_signed_pods,
|
||||||
// input_main_pods,
|
input_recursive_pods,
|
||||||
// input_statements,
|
|
||||||
public_statements,
|
public_statements,
|
||||||
statements,
|
statements,
|
||||||
operations,
|
operations,
|
||||||
merkle_proofs,
|
merkle_proofs_containers: merkle_proofs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _verify(&self) -> Result<()> {
|
pub fn params(&self) -> &Params {
|
||||||
// 1. TODO: Verify input pods
|
&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();
|
let input_statement_offset = self.offset_input_statements();
|
||||||
// get the input_statements from the self.statements
|
// get the input_statements from the self.statements
|
||||||
let input_statements = &self.statements[input_statement_offset..];
|
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
|
// 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
|
// find a ValueOf statement from the public statements with key=KEY_TYPE and check that the
|
||||||
// value is PodType::MockMainPod
|
// value is PodType::MockMainPod
|
||||||
let has_type_statement = self.public_statements.iter().any(|s| {
|
let type_statement = &self.public_statements[0];
|
||||||
s.0 == Predicate::Native(NativePredicate::Equal) && {
|
let type_statement_ok = type_statement.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)
|
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 {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}});
|
};
|
||||||
|
if !type_statement_ok {
|
||||||
|
return Err(Error::not_type_statement());
|
||||||
|
}
|
||||||
// 3. check that all `NewEntry` operations have unique keys
|
// 3. check that all `NewEntry` operations have unique keys
|
||||||
// (no duplicates)
|
// (no duplicates)
|
||||||
let value_ofs_unique = input_statements
|
let value_ofs_unique = input_statements
|
||||||
|
|
@ -225,7 +296,9 @@ impl MockMainPod {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.all_unique();
|
.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
|
// 5. verify that all `input_statements` are correctly generated
|
||||||
// by `self.operations` (where each operation can only access previous statements)
|
// by `self.operations` (where each operation can only access previous statements)
|
||||||
|
|
@ -236,40 +309,19 @@ impl MockMainPod {
|
||||||
self.operations[i]
|
self.operations[i]
|
||||||
.deref(
|
.deref(
|
||||||
&self.statements[..input_statement_offset + i],
|
&self.statements[..input_statement_offset + i],
|
||||||
&self.merkle_proofs,
|
&self.merkle_proofs_containers,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.check_and_log(&self.params, &s.clone().try_into().unwrap())
|
.check_and_log(&self.params, &s.clone().try_into().unwrap())
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, middleware::Error>>()
|
.collect::<Result<Vec<_>, middleware::Error>>()
|
||||||
.unwrap();
|
.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) {
|
if !statement_check.iter().all(|b| *b) {
|
||||||
return Err(Error::statement_not_check());
|
return Err(Error::statement_not_check());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn params(&self) -> &Params {
|
|
||||||
&self.params
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pod for MockMainPod {
|
|
||||||
fn params(&self) -> &Params {
|
|
||||||
&self.params
|
|
||||||
}
|
|
||||||
fn verify(&self) -> Result<(), Box<DynError>> {
|
|
||||||
Ok(self._verify()?)
|
|
||||||
}
|
|
||||||
fn id(&self) -> PodId {
|
fn id(&self) -> PodId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
@ -285,11 +337,31 @@ impl Pod for MockMainPod {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_data(&self) -> serde_json::Value {
|
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 {
|
serde_json::to_value(Data {
|
||||||
public_statements: self.public_statements.clone(),
|
public_statements: self.public_statements.clone(),
|
||||||
operations: self.operations.clone(),
|
operations: self.operations.clone(),
|
||||||
statements: self.statements.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")
|
.expect("serialization to json")
|
||||||
}
|
}
|
||||||
|
|
@ -302,8 +374,8 @@ impl RecursivePod for MockMainPod {
|
||||||
fn proof(&self) -> Proof {
|
fn proof(&self) -> Proof {
|
||||||
panic!("MockMainPod can't be verified in a recursive MainPod circuit");
|
panic!("MockMainPod can't be verified in a recursive MainPod circuit");
|
||||||
}
|
}
|
||||||
fn vds_root(&self) -> Hash {
|
fn vd_set(&self) -> &VDSet {
|
||||||
self.vds_root
|
&self.vd_set
|
||||||
}
|
}
|
||||||
// MockMainPods include some internal private state which is necessary
|
// MockMainPods include some internal private state which is necessary
|
||||||
// for verification. In non-mock Pods, this state will not be necessary,
|
// for verification. In non-mock Pods, this state will not be necessary,
|
||||||
|
|
@ -311,23 +383,37 @@ impl RecursivePod for MockMainPod {
|
||||||
fn deserialize_data(
|
fn deserialize_data(
|
||||||
params: Params,
|
params: Params,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>> {
|
) -> Result<Box<dyn RecursivePod>> {
|
||||||
let Data {
|
let Data {
|
||||||
public_statements,
|
public_statements,
|
||||||
operations,
|
operations,
|
||||||
statements,
|
statements,
|
||||||
merkle_proofs,
|
merkle_proofs,
|
||||||
|
input_signed_pods,
|
||||||
|
input_recursive_pods,
|
||||||
} = serde_json::from_value(data)?;
|
} = 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::<Result<Vec<_>>>()?;
|
||||||
|
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::<Result<Vec<_>>>()?;
|
||||||
Ok(Box::new(Self {
|
Ok(Box::new(Self {
|
||||||
params,
|
params,
|
||||||
id,
|
id,
|
||||||
vds_root,
|
vd_set,
|
||||||
|
input_signed_pods,
|
||||||
|
input_recursive_pods,
|
||||||
public_statements,
|
public_statements,
|
||||||
operations,
|
operations,
|
||||||
statements,
|
statements,
|
||||||
merkle_proofs,
|
merkle_proofs_containers: merkle_proofs,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -341,16 +427,16 @@ pub mod tests {
|
||||||
backends::plonky2::mock::signedpod::MockSigner,
|
backends::plonky2::mock::signedpod::MockSigner,
|
||||||
examples::{
|
examples::{
|
||||||
great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder,
|
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,
|
frontend,
|
||||||
middleware::{self, DEFAULT_VD_SET},
|
middleware::{self},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[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 vd_set = &*MOCK_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(¶ms);
|
zu_kyc_sign_pod_builders(¶ms);
|
||||||
let mut signer = MockSigner {
|
let mut signer = MockSigner {
|
||||||
|
|
@ -381,9 +467,7 @@ pub mod tests {
|
||||||
|
|
||||||
println!("{:#}", pod);
|
println!("{:#}", pod);
|
||||||
|
|
||||||
pod.verify()?; // TODO
|
pod.verify()?;
|
||||||
// println!("id: {}", pod.id());
|
|
||||||
// println!("pub_statements: {:?}", pod.pub_statements());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
constants::MAX_DEPTH,
|
constants::MAX_DEPTH,
|
||||||
middleware::{
|
middleware::{
|
||||||
containers::Dictionary, hash_str, serialization::ordered_map, AnchoredKey, DynError, Key,
|
containers::Dictionary, hash_str, serialization::ordered_map, AnchoredKey, Key, Params,
|
||||||
Params, Pod, PodId, PodSigner, PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE,
|
Pod, PodId, PodSigner, PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE, SELF,
|
||||||
SELF,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,11 +40,7 @@ impl MockSigner {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PodSigner for MockSigner {
|
impl PodSigner for MockSigner {
|
||||||
fn sign(
|
fn sign(&mut self, params: &Params, kvs: &HashMap<Key, Value>) -> Result<Box<dyn Pod>> {
|
||||||
&mut self,
|
|
||||||
params: &Params,
|
|
||||||
kvs: &HashMap<Key, Value>,
|
|
||||||
) -> Result<Box<dyn Pod>, Box<DynError>> {
|
|
||||||
Ok(self._sign(params, kvs).map(Box::new)?)
|
Ok(self._sign(params, kvs).map(Box::new)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +64,30 @@ impl MockSignedPod {
|
||||||
self.signature.clone()
|
self.signature.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _verify(&self) -> Result<()> {
|
pub(crate) fn deserialize(id: PodId, data: serde_json::Value) -> Result<Box<dyn Pod>> {
|
||||||
|
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
|
// 1. Verify id
|
||||||
let mt = MerkleTree::new(
|
let mt = MerkleTree::new(
|
||||||
MAX_DEPTH,
|
MAX_DEPTH,
|
||||||
|
|
@ -112,33 +130,6 @@ impl MockSignedPod {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn deserialize(id: PodId, data: serde_json::Value) -> Result<Box<dyn Pod>> {
|
|
||||||
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<DynError>> {
|
|
||||||
Ok(self._verify()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> PodId {
|
fn id(&self) -> PodId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +186,7 @@ pub mod tests {
|
||||||
.downcast::<MockSignedPod>()
|
.downcast::<MockSignedPod>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
pod._verify()?;
|
pod.verify()?;
|
||||||
println!("id: {}", pod.id());
|
println!("id: {}", pod.id());
|
||||||
println!("kvs: {:?}", pod.kvs());
|
println!("kvs: {:?}", pod.kvs());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -517,7 +517,7 @@ fn hash_verifier_data_gadget(
|
||||||
}
|
}
|
||||||
|
|
||||||
// compatible with hash_verifier_data_gadget.
|
// compatible with hash_verifier_data_gadget.
|
||||||
pub(crate) fn hash_verifier_data(verifier_only_data: &VerifierOnlyCircuitData<C, D>) -> HashOut<F> {
|
pub fn hash_verifier_data(verifier_only_data: &VerifierOnlyCircuitData<C, D>) -> HashOut<F> {
|
||||||
let f: Vec<F> = [
|
let f: Vec<F> = [
|
||||||
verifier_only_data.circuit_digest.elements.to_vec(),
|
verifier_only_data.circuit_digest.elements.to_vec(),
|
||||||
verifier_only_data
|
verifier_only_data
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod circuit;
|
pub mod circuit;
|
||||||
pub use circuit::{
|
pub use circuit::{
|
||||||
common_data_for_recursion, new_params, new_params_padded, pad_circuit, InnerCircuit,
|
common_data_for_recursion, hash_verifier_data, new_params, new_params_padded, pad_circuit,
|
||||||
RecursiveCircuit, RecursiveParams, VerifiedProofTarget,
|
InnerCircuit, RecursiveCircuit, RecursiveParams, VerifiedProofTarget,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
constants::MAX_DEPTH,
|
constants::MAX_DEPTH,
|
||||||
middleware::{
|
middleware::{
|
||||||
containers::Dictionary, AnchoredKey, DynError, Hash, Key, Params, Pod, PodId, PodSigner,
|
containers::Dictionary, AnchoredKey, Hash, Key, Params, Pod, PodId, PodSigner, PodType,
|
||||||
PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE, SELF,
|
RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE, SELF,
|
||||||
},
|
},
|
||||||
timed,
|
timed,
|
||||||
};
|
};
|
||||||
|
|
@ -62,11 +62,7 @@ impl Signer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PodSigner for Signer {
|
impl PodSigner for Signer {
|
||||||
fn sign(
|
fn sign(&mut self, params: &Params, kvs: &HashMap<Key, Value>) -> Result<Box<dyn Pod>> {
|
||||||
&mut self,
|
|
||||||
params: &Params,
|
|
||||||
kvs: &HashMap<Key, Value>,
|
|
||||||
) -> Result<Box<dyn Pod>, Box<DynError>> {
|
|
||||||
Ok(self._sign(params, kvs).map(Box::new)?)
|
Ok(self._sign(params, kvs).map(Box::new)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,44 +92,6 @@ fn dummy() -> SignedPod {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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::<HashMap<RawValue, RawValue>>(),
|
|
||||||
)?;
|
|
||||||
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<Box<dyn Pod>> {
|
pub(crate) fn deserialize(id: PodId, data: serde_json::Value) -> Result<Box<dyn Pod>> {
|
||||||
let data: Data = serde_json::from_value(data)?;
|
let data: Data = serde_json::from_value(data)?;
|
||||||
let signer_bytes = deserialize_bytes(&data.signer)?;
|
let signer_bytes = deserialize_bytes(&data.signer)?;
|
||||||
|
|
@ -172,8 +130,42 @@ impl Pod for SignedPod {
|
||||||
fn params(&self) -> &Params {
|
fn params(&self) -> &Params {
|
||||||
panic!("SignedPod doesn't have params");
|
panic!("SignedPod doesn't have params");
|
||||||
}
|
}
|
||||||
fn verify(&self) -> Result<(), Box<DynError>> {
|
fn verify(&self) -> Result<()> {
|
||||||
Ok(self._verify().map_err(Box::new)?)
|
// 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::<HashMap<RawValue, RawValue>>(),
|
||||||
|
)?;
|
||||||
|
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 {
|
fn id(&self) -> PodId {
|
||||||
|
|
@ -234,7 +226,7 @@ pub mod tests {
|
||||||
let pod = pod.sign(&mut signer).unwrap();
|
let pod = pod.sign(&mut signer).unwrap();
|
||||||
let pod = (pod.pod as Box<dyn Any>).downcast::<SignedPod>().unwrap();
|
let pod = (pod.pod as Box<dyn Any>).downcast::<SignedPod>().unwrap();
|
||||||
|
|
||||||
pod._verify()?;
|
pod.verify()?;
|
||||||
println!("id: {}", pod.id());
|
println!("id: {}", pod.id());
|
||||||
println!("kvs: {:?}", pod.kvs());
|
println!("kvs: {:?}", pod.kvs());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{backtrace::Backtrace, fmt::Debug};
|
use std::{backtrace::Backtrace, fmt::Debug};
|
||||||
|
|
||||||
use crate::middleware::{DynError, Statement, StatementTmpl, Value};
|
use crate::middleware::{BackendError, Statement, StatementTmpl, Value};
|
||||||
|
|
||||||
pub type Result<T, E = Error> = core::result::Result<T, E>;
|
pub type Result<T, E = Error> = core::result::Result<T, E>;
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Infallible(#[from] std::convert::Infallible),
|
Infallible(#[from] std::convert::Infallible),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Backend(#[from] Box<DynError>),
|
Backend(#[from] BackendError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Middleware(#[from] crate::middleware::Error),
|
Middleware(#[from] crate::middleware::Error),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -564,7 +564,7 @@ impl MainPodBuilder {
|
||||||
statements: &statements,
|
statements: &statements,
|
||||||
operations: &operations,
|
operations: &operations,
|
||||||
public_statements: &public_statements,
|
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)?;
|
let pod = prover.prove(&self.params, &self.vd_set, inputs)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use super::Error;
|
use super::Error;
|
||||||
use crate::{
|
use crate::{
|
||||||
frontend::{MainPod, SignedPod},
|
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)]
|
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||||
|
|
@ -29,7 +29,7 @@ pub struct SerializedMainPod {
|
||||||
params: Params,
|
params: Params,
|
||||||
pod_type: (usize, String),
|
pod_type: (usize, String),
|
||||||
id: PodId,
|
id: PodId,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ impl From<MainPod> for SerializedMainPod {
|
||||||
SerializedMainPod {
|
SerializedMainPod {
|
||||||
pod_type: (pod_type, pod_type_name_str.to_string()),
|
pod_type: (pod_type, pod_type_name_str.to_string()),
|
||||||
id: pod.id(),
|
id: pod.id(),
|
||||||
vds_root: pod.pod.vds_root(),
|
vd_set: pod.pod.vd_set().clone(),
|
||||||
params: pod.params.clone(),
|
params: pod.params.clone(),
|
||||||
data,
|
data,
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,7 @@ impl TryFrom<SerializedMainPod> for MainPod {
|
||||||
serialized.pod_type.0,
|
serialized.pod_type.0,
|
||||||
serialized.params.clone(),
|
serialized.params.clone(),
|
||||||
serialized.id,
|
serialized.id,
|
||||||
serialized.vds_root,
|
serialized.vd_set,
|
||||||
serialized.data,
|
serialized.data,
|
||||||
)?;
|
)?;
|
||||||
let public_statements = pod.pub_statements();
|
let public_statements = pod.pub_statements();
|
||||||
|
|
|
||||||
|
|
@ -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")
|
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 {
|
pub trait Pod: fmt::Debug + DynClone + Any {
|
||||||
fn params(&self) -> &Params;
|
fn params(&self) -> &Params;
|
||||||
fn verify(&self) -> Result<(), Box<DynError>>;
|
fn verify(&self) -> Result<(), BackendError>;
|
||||||
fn id(&self) -> PodId;
|
fn id(&self) -> PodId;
|
||||||
/// Return a uuid of the pod type and its name. The name is only used as metadata.
|
/// Return a uuid of the pod type and its name. The name is only used as metadata.
|
||||||
fn pod_type(&self) -> (usize, &'static str);
|
fn pod_type(&self) -> (usize, &'static str);
|
||||||
|
|
@ -807,18 +805,6 @@ pub trait Pod: fmt::Debug + DynClone + Any {
|
||||||
})
|
})
|
||||||
.collect()
|
.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<dyn Pod>
|
// impl Clone for Box<dyn Pod>
|
||||||
|
|
@ -830,15 +816,15 @@ dyn_clone::clone_trait_object!(Pod);
|
||||||
pub trait RecursivePod: Pod {
|
pub trait RecursivePod: Pod {
|
||||||
fn verifier_data(&self) -> VerifierOnlyCircuitData;
|
fn verifier_data(&self) -> VerifierOnlyCircuitData;
|
||||||
fn proof(&self) -> Proof;
|
fn proof(&self) -> Proof;
|
||||||
fn vds_root(&self) -> Hash;
|
fn vd_set(&self) -> &VDSet;
|
||||||
|
|
||||||
/// Returns the deserialized RecursivePod.
|
/// Returns the deserialized RecursivePod.
|
||||||
fn deserialize_data(
|
fn deserialize_data(
|
||||||
params: Params,
|
params: Params,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>>
|
) -> Result<Box<dyn RecursivePod>, BackendError>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
@ -851,7 +837,7 @@ pub trait PodSigner {
|
||||||
&mut self,
|
&mut self,
|
||||||
params: &Params,
|
params: &Params,
|
||||||
kvs: &HashMap<Key, Value>,
|
kvs: &HashMap<Key, Value>,
|
||||||
) -> Result<Box<dyn Pod>, Box<DynError>>;
|
) -> Result<Box<dyn Pod>, BackendError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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 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_set: VDSet,
|
pub vd_set: VDSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PodProver {
|
pub trait PodProver {
|
||||||
|
|
@ -872,7 +858,7 @@ pub trait PodProver {
|
||||||
params: &Params,
|
params: &Params,
|
||||||
vd_set: &VDSet,
|
vd_set: &VDSet,
|
||||||
inputs: MainPodInputs,
|
inputs: MainPodInputs,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>>;
|
) -> Result<Box<dyn RecursivePod>, BackendError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToFields {
|
pub trait ToFields {
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ use std::{
|
||||||
sync::{LazyLock, Mutex},
|
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(
|
type DeserializeFn = fn(
|
||||||
params: Params,
|
params: Params,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
) -> Result<Box<dyn RecursivePod>, Box<DynError>>;
|
) -> Result<Box<dyn RecursivePod>, BackendError>;
|
||||||
|
|
||||||
static DESERIALIZERS: LazyLock<Mutex<HashMap<usize, DeserializeFn>>> =
|
static DESERIALIZERS: LazyLock<Mutex<HashMap<usize, DeserializeFn>>> =
|
||||||
LazyLock::new(backend::deserializers_default);
|
LazyLock::new(backend::deserializers_default);
|
||||||
|
|
@ -26,28 +26,27 @@ pub fn deserialize_pod(
|
||||||
pod_type: usize,
|
pod_type: usize,
|
||||||
params: Params,
|
params: Params,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
vds_root: Hash,
|
vd_set: VDSet,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
) -> Result<Box<dyn RecursivePod>> {
|
) -> Result<Box<dyn RecursivePod>, BackendError> {
|
||||||
let deserialize_fn: DeserializeFn =
|
let deserialize_fn: DeserializeFn =
|
||||||
*DESERIALIZERS
|
*DESERIALIZERS
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&pod_type)
|
.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 deserializer for pod_type={} not registered. See https://github.com/0xPARC/pod2/wiki/PodType for pod type assignments.",
|
||||||
pod_type
|
pod_type
|
||||||
)))?;
|
)))?;
|
||||||
|
|
||||||
deserialize_fn(params, data, vds_root, id)
|
deserialize_fn(params, data, vd_set, id)
|
||||||
.map_err(|e| Error::custom(format!("deserialize error: {:?}", e)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize_signed_pod(
|
pub fn deserialize_signed_pod(
|
||||||
pod_type: usize,
|
pod_type: usize,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
) -> Result<Box<dyn Pod>> {
|
) -> Result<Box<dyn Pod>, BackendError> {
|
||||||
backend::deserialize_signed_pod(pod_type, id, data)
|
backend::deserialize_signed_pod(pod_type, id, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,15 +73,13 @@ mod backend {
|
||||||
pod_type: usize,
|
pod_type: usize,
|
||||||
id: PodId,
|
id: PodId,
|
||||||
data: serde_json::Value,
|
data: serde_json::Value,
|
||||||
) -> Result<Box<dyn Pod>> {
|
) -> Result<Box<dyn Pod>, BackendError> {
|
||||||
if pod_type == PodType::MockSigned as usize {
|
if pod_type == PodType::MockSigned as usize {
|
||||||
MockSignedPod::deserialize(id, data)
|
MockSignedPod::deserialize(id, data)
|
||||||
.map_err(|e| Error::custom(format!("deserialize error: {:?}", e)))
|
|
||||||
} else if pod_type == PodType::Signed as usize {
|
} else if pod_type == PodType::Signed as usize {
|
||||||
SignedPod::deserialize(id, data)
|
SignedPod::deserialize(id, data)
|
||||||
.map_err(|e| Error::custom(format!("deserialize error: {:?}", e)))
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::custom(format!(
|
Err(BackendError::custom(format!(
|
||||||
"unexpected pod_type={} for deserialize_signed_pod",
|
"unexpected pod_type={} for deserialize_signed_pod",
|
||||||
pod_type
|
pod_type
|
||||||
)))
|
)))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue