No Pod IDs (#394)
- middleware:
- Add `Statement::Intro`
- Add `SignedBy` native predicate and operation. The signature is auxiliary data to the operation
- Rename `PodSigner` to `Signer` with a new API (just for signing `RawValue`)
- Removed `NewEntry` operation. Use `ContainsFromEntries` instead
- Remove `KEY_SIGNER` and `KEY_TYPE` which are no longer used
- Merge `RecursivePod` and `Pod` traits
- Change the `Pod::deserialize_data` method to use `Self` instead of `Box<dyn Pod>`
- Extend `Pod` trait with these methods:
- `is_main`: when the pod is Main, in a (recursive) verification its vk will be checked to exist in the vd_set but not if it's intro pod
- `is_mock`: skip some verifications in the recursive mock MainPod verification
- `verifier_data_hash`
- `pod_id` renamed to `statements_hash`
- AnchoredKeys are now a pair of dictionary root and key
- Entry statements are now defined as Contains with literal arguments
- Operations that take Entries now use Contains statements with literal arguments
- frontend:
- Rename `SignedPod` to `SignedDict` (which now contains the dict, public key and signature, and can still `verify(self)`ed)
- The `SignedDict` keeps the method `get_statement` for convenience but now it returns a `Contains` statement that proves the existence of the key in the dict
- The `MainPodBuilder` automatically inserts a `Contains` statement when an operation is added that uses an entry as argument that was not yet "opened".
- Removed the `literal` methods from the `MainPodBuilder` that were loading literals to anchored keys: that was no longer needed after we introduced literal arguments
- backend
- Only verify inclusion of the verifying key into the vd_set if the pod is MainPod. A pod is not MainPod if the first statement is Intro.
- Reject intro pods that have non-intro statements
- Empty pod now returns an intro statement
- Don't insert a type statement automatically in MainPod and MockMainPod. We get rid of the type entry.
- Implement `SignedBy` operation, which uses the muxed table to store signature verifications
- Rename `PodId` to `statements_hash` or `sts_hash` for short. Now this is only used as a hash of the statements for the circuits public inputs.
- Refactor normalization of `self` statements:
- Before: replace values that contain `SELF` by the given pod_id
- After: place the verifying key hash into the Intro predicates
This commit is contained in:
parent
122f9c3cac
commit
0e2f7b756e
39 changed files with 2127 additions and 3064 deletions
|
|
@ -1,8 +1,10 @@
|
|||
pub mod operation;
|
||||
use crate::middleware::PodType;
|
||||
pub mod statement;
|
||||
use std::{any::Any, iter, sync::Arc};
|
||||
use std::{iter, sync::Arc};
|
||||
|
||||
use itertools::Itertools;
|
||||
use num_bigint::BigUint;
|
||||
pub use operation::*;
|
||||
use plonky2::{hash::poseidon::PoseidonHash, plonk::config::Hasher};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -10,7 +12,7 @@ pub use statement::*;
|
|||
|
||||
use crate::{
|
||||
backends::plonky2::{
|
||||
basetypes::{CircuitData, Proof, ProofWithPublicInputs, VerifierOnlyCircuitData},
|
||||
basetypes::{CircuitData, Proof, ProofWithPublicInputs, VerifierOnlyCircuitData, F},
|
||||
cache::{self, CacheEntry},
|
||||
cache_get_standard_rec_main_pod_common_circuit_data,
|
||||
circuits::mainpod::{CustomPredicateVerification, MainPodVerifyInput, MainPodVerifyTarget},
|
||||
|
|
@ -20,7 +22,10 @@ use crate::{
|
|||
hash_common_data,
|
||||
mock::emptypod::MockEmptyPod,
|
||||
primitives::{
|
||||
ec::schnorr::SecretKey,
|
||||
ec::{
|
||||
curve::Point as PublicKey,
|
||||
schnorr::{SecretKey, Signature},
|
||||
},
|
||||
merkletree::{MerkleClaimAndProof, MerkleTreeStateTransitionProof},
|
||||
},
|
||||
recursion::{
|
||||
|
|
@ -30,32 +35,31 @@ use crate::{
|
|||
CircuitDataSerializer, CommonCircuitDataSerializer, VerifierCircuitDataSerializer,
|
||||
},
|
||||
serialize_proof, serialize_verifier_only,
|
||||
signedpod::SignedPod,
|
||||
},
|
||||
middleware::{
|
||||
self, resolve_wildcard_values, value_from_op, AnchoredKey, CustomPredicateBatch,
|
||||
Error as MiddlewareError, Hash, MainPodInputs, NativeOperation, OperationType, Params, Pod,
|
||||
PodId, PodProver, PodType, RecursivePod, StatementArg, ToFields, VDSet, KEY_TYPE, SELF,
|
||||
self, resolve_wildcard_values, value_from_op, CustomPredicateBatch,
|
||||
Error as MiddlewareError, Hash, MainPodInputs, MainPodProver, NativeOperation,
|
||||
OperationType, Params, Pod, RawValue, StatementArg, ToFields, VDSet,
|
||||
},
|
||||
timed,
|
||||
};
|
||||
|
||||
/// Hash a list of public statements to derive the PodId. To make circuits with different number
|
||||
/// of `max_public_statements compatible we pad the statements up to `num_public_statements_id`.
|
||||
/// As an optimization we front pad with none-statements so that circuits with a small
|
||||
/// `max_public_statements` only pay for `max_public_statements` by starting the poseidon state
|
||||
/// with a precomputed constant corresponding to the front-padding part:
|
||||
/// `id = hash(serialize(reverse(statements || none-statements)))`
|
||||
pub fn calculate_id(statements: &[Statement], params: &Params) -> middleware::Hash {
|
||||
assert!(statements.len() <= params.num_public_statements_id);
|
||||
assert!(params.max_public_statements <= params.num_public_statements_id);
|
||||
/// Hash a list of public statements to derive the Statements hash. To make circuits with
|
||||
/// different number of `max_public_statements compatible we pad the statements up to
|
||||
/// `num_public_statements_id`. As an optimization we front pad with none-statements so that
|
||||
/// circuits with a small `max_public_statements` only pay for `max_public_statements` by starting
|
||||
/// the poseidon state with a precomputed constant corresponding to the front-padding part: `id =
|
||||
/// hash(serialize(reverse(statements || none-statements)))`
|
||||
pub fn calculate_statements_hash(statements: &[Statement], params: &Params) -> middleware::Hash {
|
||||
assert!(statements.len() <= params.num_public_statements_hash);
|
||||
assert!(params.max_public_statements <= params.num_public_statements_hash);
|
||||
|
||||
let mut none_st: Statement = middleware::Statement::None.into();
|
||||
pad_statement(params, &mut none_st);
|
||||
let statements_back_padded = statements
|
||||
.iter()
|
||||
.chain(iter::repeat(&none_st))
|
||||
.take(params.num_public_statements_id)
|
||||
.take(params.num_public_statements_hash)
|
||||
.collect_vec();
|
||||
let field_elems = statements_back_padded
|
||||
.iter()
|
||||
|
|
@ -236,6 +240,60 @@ pub(crate) fn extract_public_key_of(
|
|||
Ok(table)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SignedBy {
|
||||
pub msg: RawValue,
|
||||
pub pk: PublicKey,
|
||||
pub sig: Signature,
|
||||
}
|
||||
|
||||
impl SignedBy {
|
||||
/// A valid deterministic signature from a known private key and nonce, used for padding
|
||||
pub fn dummy() -> Self {
|
||||
let sk = SecretKey(BigUint::from(1u32));
|
||||
let pk = sk.public_key();
|
||||
let msg = RawValue([F(0), F(0), F(0), F(0)]);
|
||||
let nonce = BigUint::from(2u32);
|
||||
let sig = sk.sign(msg, &nonce);
|
||||
Self { msg, pk, sig }
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts Signatures verification data from SignedBy ops.
|
||||
pub(crate) fn extract_signatures(
|
||||
params: &Params,
|
||||
aux_list: &mut [OperationAux],
|
||||
operations: &[middleware::Operation],
|
||||
statements: &[middleware::Statement],
|
||||
) -> Result<Vec<SignedBy>> {
|
||||
let mut table = Vec::new();
|
||||
for (i, (op, st)) in operations.iter().zip(statements.iter()).enumerate() {
|
||||
let deduction_err = || MiddlewareError::invalid_deduction(op.clone(), st.clone());
|
||||
if let (
|
||||
middleware::Operation::SignedBy(msg_s, pk_s, sig),
|
||||
middleware::Statement::SignedBy(msg_ref, pk_ref),
|
||||
) = (op, st)
|
||||
{
|
||||
let msg = value_from_op(msg_s, msg_ref).ok_or_else(deduction_err)?;
|
||||
let pk = value_from_op(pk_s, pk_ref).ok_or_else(deduction_err)?;
|
||||
aux_list[i] = OperationAux::SignedByIndex(table.len());
|
||||
table.push(SignedBy {
|
||||
msg: msg.raw(),
|
||||
pk: PublicKey::try_from(pk.typed())?,
|
||||
sig: sig.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
if table.len() > params.max_signed_by {
|
||||
return Err(Error::custom(format!(
|
||||
"The number of required signatures ({}) exceeds the maximum number ({}).",
|
||||
table.len(),
|
||||
params.max_signed_by
|
||||
)));
|
||||
}
|
||||
Ok(table)
|
||||
}
|
||||
|
||||
/// Find the operation argument statement in the list of previous statements and return the index.
|
||||
fn find_op_arg(statements: &[Statement], op_arg: &middleware::Statement) -> Result<OperationArg> {
|
||||
// NOTE: The `None` `Statement` always exists as a constant at index 0
|
||||
|
|
@ -283,37 +341,17 @@ pub(crate) fn layout_statements(
|
|||
// predicate statements
|
||||
statements.push(middleware::Statement::None.into());
|
||||
|
||||
// Input signed pods region
|
||||
let dummy_signed_pod_box: Box<dyn Pod> = Box::new(SignedPod::dummy());
|
||||
let dummy_signed_pod = dummy_signed_pod_box.as_ref();
|
||||
assert!(inputs.signed_pods.len() <= params.max_input_signed_pods);
|
||||
for i in 0..params.max_input_signed_pods {
|
||||
let pod = inputs.signed_pods.get(i).unwrap_or(&dummy_signed_pod);
|
||||
let sts = pod.pub_statements();
|
||||
assert!(sts.len() <= params.max_signed_pod_values);
|
||||
for j in 0..params.max_signed_pod_values {
|
||||
let mut st = sts
|
||||
.get(j)
|
||||
.unwrap_or(&middleware::Statement::None)
|
||||
.clone()
|
||||
.into();
|
||||
pad_statement(params, &mut st);
|
||||
statements.push(st);
|
||||
}
|
||||
}
|
||||
|
||||
// Input main pods region
|
||||
let empty_pod_box: Box<dyn RecursivePod> =
|
||||
if mock || inputs.recursive_pods.len() == params.max_input_recursive_pods {
|
||||
// We mocking or we don't need padding so we skip creating an EmptyPod
|
||||
MockEmptyPod::new_boxed(params, inputs.vd_set.clone())
|
||||
} else {
|
||||
EmptyPod::new_boxed(params, inputs.vd_set.clone())
|
||||
};
|
||||
// Input pods region
|
||||
let empty_pod_box: Box<dyn Pod> = if mock || inputs.pods.len() == params.max_input_pods {
|
||||
// We mocking or we don't need padding so we skip creating an EmptyPod
|
||||
MockEmptyPod::new_boxed(params, inputs.vd_set.clone())
|
||||
} else {
|
||||
EmptyPod::new_boxed(params, inputs.vd_set.clone())
|
||||
};
|
||||
let empty_pod = empty_pod_box.as_ref();
|
||||
assert!(inputs.recursive_pods.len() <= params.max_input_recursive_pods);
|
||||
for i in 0..params.max_input_recursive_pods {
|
||||
let pod = inputs.recursive_pods.get(i).copied().unwrap_or(empty_pod);
|
||||
assert!(inputs.pods.len() <= params.max_input_pods);
|
||||
for i in 0..params.max_input_pods {
|
||||
let pod = inputs.pods.get(i).copied().unwrap_or(empty_pod);
|
||||
let sts = pod.pub_statements();
|
||||
assert!(sts.len() <= params.max_public_statements);
|
||||
for j in 0..params.max_input_pods_public_statements {
|
||||
|
|
@ -347,20 +385,7 @@ pub(crate) fn layout_statements(
|
|||
|
||||
// Public statements
|
||||
assert!(inputs.public_statements.len() < params.max_public_statements);
|
||||
let pod_type = if mock {
|
||||
PodType::MockMain
|
||||
} else {
|
||||
PodType::Main
|
||||
};
|
||||
let mut type_st = middleware::Statement::Equal(
|
||||
AnchoredKey::from((SELF, KEY_TYPE)).into(),
|
||||
middleware::Value::from(pod_type).into(),
|
||||
)
|
||||
.into();
|
||||
pad_statement(params, &mut type_st);
|
||||
statements.push(type_st);
|
||||
|
||||
for i in 0..(params.max_public_statements - 1) {
|
||||
for i in 0..params.max_public_statements {
|
||||
let mut st = inputs
|
||||
.public_statements
|
||||
.get(i)
|
||||
|
|
@ -373,7 +398,7 @@ pub(crate) fn layout_statements(
|
|||
|
||||
let offset_public_statements = statements.len() - params.max_public_statements;
|
||||
let public_statements = statements
|
||||
[offset_public_statements..offset_public_statements + 1 + inputs.public_statements.len()]
|
||||
[offset_public_statements..offset_public_statements + inputs.public_statements.len()]
|
||||
.to_vec();
|
||||
Ok((statements, public_statements))
|
||||
}
|
||||
|
|
@ -413,13 +438,7 @@ pub(crate) fn process_public_statements_operations(
|
|||
mut operations: Vec<Operation>,
|
||||
) -> Result<Vec<Operation>> {
|
||||
let offset_public_statements = statements.len() - params.max_public_statements;
|
||||
operations.push(Operation(
|
||||
OperationType::Native(NativeOperation::NewEntry),
|
||||
vec![],
|
||||
OperationAux::None,
|
||||
));
|
||||
for i in 0..(params.max_public_statements - 1) {
|
||||
let st = &statements[offset_public_statements + i + 1];
|
||||
for st in statements.iter().skip(offset_public_statements) {
|
||||
let mut op = if st.is_none() {
|
||||
Operation(
|
||||
OperationType::Native(NativeOperation::None),
|
||||
|
|
@ -442,44 +461,28 @@ pub(crate) fn process_public_statements_operations(
|
|||
|
||||
pub struct Prover {}
|
||||
|
||||
impl PodProver for Prover {
|
||||
fn prove(
|
||||
&self,
|
||||
params: &Params,
|
||||
vd_set: &VDSet,
|
||||
inputs: MainPodInputs,
|
||||
) -> Result<Box<dyn RecursivePod>> {
|
||||
let signed_pods_input: Vec<SignedPod> = inputs
|
||||
.signed_pods
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let p = (*p as &dyn Any)
|
||||
.downcast_ref::<SignedPod>()
|
||||
.expect("type SignedPod");
|
||||
p.clone()
|
||||
})
|
||||
.collect_vec();
|
||||
|
||||
impl MainPodProver for Prover {
|
||||
fn prove(&self, params: &Params, inputs: MainPodInputs) -> Result<Box<dyn Pod>> {
|
||||
// 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.pods.len() == params.max_input_pods {
|
||||
// We don't need padding so we skip creating an EmptyPod
|
||||
MockEmptyPod::new_boxed(params, inputs.vd_set.clone())
|
||||
} else {
|
||||
EmptyPod::new_boxed(params, inputs.vd_set.clone())
|
||||
};
|
||||
let inputs = MainPodInputs {
|
||||
recursive_pods: &inputs
|
||||
.recursive_pods
|
||||
pods: &inputs
|
||||
.pods
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(iter::repeat(&*empty_pod))
|
||||
.take(params.max_input_recursive_pods)
|
||||
.take(params.max_input_pods)
|
||||
.collect_vec(),
|
||||
..inputs
|
||||
};
|
||||
|
||||
let recursive_pods_pub_self_statements = inputs
|
||||
.recursive_pods
|
||||
let input_pods_pub_self_statements = inputs
|
||||
.pods
|
||||
.iter()
|
||||
.map(|pod| {
|
||||
assert_eq!(params.id_params(), pod.params().id_params());
|
||||
|
|
@ -500,6 +503,8 @@ impl PodProver for Prover {
|
|||
)?;
|
||||
let public_key_of_sks =
|
||||
extract_public_key_of(params, &mut aux_list, inputs.operations, inputs.statements)?;
|
||||
let signed_bys =
|
||||
extract_signatures(params, &mut aux_list, inputs.operations, inputs.statements)?;
|
||||
|
||||
let merkle_tree_state_transition_proofs =
|
||||
extract_merkle_tree_state_transition_proofs(params, &mut aux_list, inputs.operations)?;
|
||||
|
|
@ -514,38 +519,54 @@ impl PodProver for Prover {
|
|||
let operations = process_public_statements_operations(params, &statements, operations)?;
|
||||
|
||||
// get the id out of the public statements
|
||||
let id: PodId = PodId(calculate_id(&public_statements, params));
|
||||
let sts_hash = calculate_statements_hash(&public_statements, params);
|
||||
|
||||
let common_hash: String = cache_get_rec_main_pod_common_hash(params).clone();
|
||||
let proofs = inputs
|
||||
.recursive_pods
|
||||
.pods
|
||||
.iter()
|
||||
.map(|pod| {
|
||||
assert_eq!(pod.common_hash(), common_hash);
|
||||
assert_eq!(inputs.vd_set.root(), pod.vd_set().root());
|
||||
ProofWithPublicInputs {
|
||||
proof: pod.proof(),
|
||||
public_inputs: [pod.id().0 .0, inputs.vd_set.root().0].concat(),
|
||||
public_inputs: [pod.statements_hash().0, inputs.vd_set.root().0].concat(),
|
||||
}
|
||||
})
|
||||
.collect_vec();
|
||||
let verifier_datas = inputs
|
||||
.recursive_pods
|
||||
.pods
|
||||
.iter()
|
||||
.map(|pod| pod.verifier_data())
|
||||
.collect_vec();
|
||||
|
||||
let vd_mt_proofs = vd_set.get_vds_proofs(&verifier_datas)?;
|
||||
let mut vd_mt_proofs = Vec::with_capacity(inputs.pods.len());
|
||||
for (pod, vd) in inputs.pods.iter().zip(&verifier_datas) {
|
||||
vd_mt_proofs.push(if pod.is_main() {
|
||||
(true, inputs.vd_set.get_vds_proof(vd)?)
|
||||
} else {
|
||||
// For intro pods we don't verify inclusion of their vk into the vd set, so we
|
||||
// generate a dummy mt proof with expected root and value to pass some constraints
|
||||
(
|
||||
false,
|
||||
MerkleClaimAndProof {
|
||||
root: inputs.vd_set.root(),
|
||||
value: RawValue::from(pod.verifier_data_hash()),
|
||||
..MerkleClaimAndProof::empty()
|
||||
},
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
let input = MainPodVerifyInput {
|
||||
vds_set: inputs.vd_set.clone(),
|
||||
vd_mt_proofs,
|
||||
signed_pods: signed_pods_input,
|
||||
recursive_pods_pub_self_statements,
|
||||
input_pods_pub_self_statements,
|
||||
statements: statements[statements.len() - params.max_statements..].to_vec(),
|
||||
operations,
|
||||
merkle_proofs,
|
||||
public_key_of_sks,
|
||||
signed_bys,
|
||||
merkle_tree_state_transition_proofs,
|
||||
custom_predicate_batches,
|
||||
custom_predicate_verifications,
|
||||
|
|
@ -567,7 +588,7 @@ impl PodProver for Prover {
|
|||
params: params.clone(),
|
||||
verifier_only: circuit_data.verifier_only.clone(),
|
||||
common_hash,
|
||||
id,
|
||||
sts_hash,
|
||||
vd_set: inputs.vd_set,
|
||||
public_statements,
|
||||
proof: proof_with_pis.proof,
|
||||
|
|
@ -578,7 +599,7 @@ impl PodProver for Prover {
|
|||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct MainPod {
|
||||
params: Params,
|
||||
id: PodId,
|
||||
sts_hash: Hash,
|
||||
verifier_only: VerifierOnlyCircuitData,
|
||||
common_hash: String,
|
||||
/// vds_root is the merkle-root of the `VDSet`, which contains the
|
||||
|
|
@ -598,7 +619,7 @@ pub(crate) fn rec_main_pod_circuit_data(
|
|||
timed!(
|
||||
"recursive MainPod circuit_data padded",
|
||||
RecursiveCircuit::<MainPodVerifyTarget>::target_and_circuit_data_padded(
|
||||
params.max_input_recursive_pods,
|
||||
params.max_input_pods,
|
||||
&rec_common_circuit_data,
|
||||
params,
|
||||
)
|
||||
|
|
@ -676,6 +697,9 @@ impl Pod for MainPod {
|
|||
fn params(&self) -> &Params {
|
||||
&self.params
|
||||
}
|
||||
fn is_main(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn verify(&self) -> Result<()> {
|
||||
// 0. Assert that the CommonCircuitData of the pod is the current one
|
||||
let expect_common_hash = &*cache_get_rec_main_pod_common_hash(&self.params);
|
||||
|
|
@ -686,9 +710,9 @@ impl Pod for MainPod {
|
|||
)));
|
||||
}
|
||||
// 2. get the id out of the public statements
|
||||
let id = PodId(calculate_id(&self.public_statements, &self.params));
|
||||
if id != self.id {
|
||||
return Err(Error::id_not_equal(self.id, id));
|
||||
let sts_hash = calculate_statements_hash(&self.public_statements, &self.params);
|
||||
if sts_hash != self.sts_hash {
|
||||
return Err(Error::statements_hash_not_equal(self.sts_hash, sts_hash));
|
||||
}
|
||||
|
||||
// 7. verifier_data_hash is in the VDSet
|
||||
|
|
@ -705,7 +729,7 @@ impl Pod for MainPod {
|
|||
// 1, 3, 4, 5 verification via the zkSNARK proof
|
||||
let rec_main_pod_verifier_circuit_data =
|
||||
&*cache_get_rec_main_pod_verifier_circuit_data(&self.params);
|
||||
let public_inputs = id
|
||||
let public_inputs = sts_hash
|
||||
.to_fields(&self.params)
|
||||
.iter()
|
||||
.chain(self.vd_set.root().0.iter())
|
||||
|
|
@ -719,8 +743,8 @@ impl Pod for MainPod {
|
|||
.map_err(|e| Error::plonky2_proof_fail("MainPod", e))
|
||||
}
|
||||
|
||||
fn id(&self) -> PodId {
|
||||
self.id
|
||||
fn statements_hash(&self) -> Hash {
|
||||
self.sts_hash
|
||||
}
|
||||
fn pod_type(&self) -> (usize, &'static str) {
|
||||
(PodType::Main as usize, "Main")
|
||||
|
|
@ -734,18 +758,6 @@ impl Pod for MainPod {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn serialize_data(&self) -> serde_json::Value {
|
||||
serde_json::to_value(Data {
|
||||
proof: serialize_proof(&self.proof),
|
||||
public_statements: self.public_statements.clone(),
|
||||
verifier_only: serialize_verifier_only(&self.verifier_only),
|
||||
common_hash: self.common_hash.clone(),
|
||||
})
|
||||
.expect("serialization to json")
|
||||
}
|
||||
}
|
||||
|
||||
impl RecursivePod for MainPod {
|
||||
fn verifier_data(&self) -> VerifierOnlyCircuitData {
|
||||
self.verifier_only.clone()
|
||||
}
|
||||
|
|
@ -758,30 +770,42 @@ impl RecursivePod for MainPod {
|
|||
fn vd_set(&self) -> &VDSet {
|
||||
&self.vd_set
|
||||
}
|
||||
|
||||
fn serialize_data(&self) -> serde_json::Value {
|
||||
serde_json::to_value(Data {
|
||||
proof: serialize_proof(&self.proof),
|
||||
public_statements: self.public_statements.clone(),
|
||||
verifier_only: serialize_verifier_only(&self.verifier_only),
|
||||
common_hash: self.common_hash.clone(),
|
||||
})
|
||||
.expect("serialization to json")
|
||||
}
|
||||
fn deserialize_data(
|
||||
params: Params,
|
||||
data: serde_json::Value,
|
||||
vd_set: VDSet,
|
||||
id: PodId,
|
||||
) -> Result<Box<dyn RecursivePod>> {
|
||||
id: Hash,
|
||||
) -> Result<Self> {
|
||||
let data: Data = serde_json::from_value(data)?;
|
||||
let common = cache_get_rec_main_pod_common_circuit_data(¶ms);
|
||||
let proof = deserialize_proof(&common, &data.proof)?;
|
||||
let verifier_only = deserialize_verifier_only(&data.verifier_only)?;
|
||||
Ok(Box::new(Self {
|
||||
Ok(Self {
|
||||
params,
|
||||
id,
|
||||
sts_hash: id,
|
||||
verifier_only,
|
||||
common_hash: data.common_hash,
|
||||
vd_set,
|
||||
proof,
|
||||
public_statements: data.public_statements,
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use std::{any::Any, collections::HashSet};
|
||||
|
||||
use num::{BigUint, One};
|
||||
|
||||
use super::*;
|
||||
|
|
@ -789,18 +813,19 @@ pub mod tests {
|
|||
backends::plonky2::{
|
||||
mock::mainpod::{MockMainPod, MockProver},
|
||||
primitives::ec::schnorr::SecretKey,
|
||||
signedpod::Signer,
|
||||
signer::Signer,
|
||||
},
|
||||
dict,
|
||||
examples::{
|
||||
attest_eth_friend, tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_sign_pod_builders,
|
||||
EthDosHelper,
|
||||
attest_eth_friend, tickets_pod_full_flow, zu_kyc_pod_builder,
|
||||
zu_kyc_sign_dict_builders, EthDosHelper,
|
||||
},
|
||||
frontend::{
|
||||
self, literal, CustomPredicateBatchBuilder, MainPodBuilder, StatementTmplBuilder as STB,
|
||||
},
|
||||
middleware::{
|
||||
self, containers::Set, CustomPredicateRef, NativePredicate as NP, DEFAULT_VD_LIST,
|
||||
DEFAULT_VD_SET,
|
||||
self, containers::Set, CustomPredicateRef, NativePredicate as NP, Signer as _,
|
||||
DEFAULT_VD_LIST, DEFAULT_VD_SET,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -809,7 +834,7 @@ pub mod tests {
|
|||
let params = middleware::Params {
|
||||
// Currently the circuit uses random access that only supports vectors of length 64.
|
||||
// With max_input_main_pods=3 we need random access to a vector of length 73.
|
||||
max_input_recursive_pods: 0,
|
||||
max_input_pods: 0,
|
||||
max_custom_predicate_batches: 0,
|
||||
max_custom_predicate_verifications: 0,
|
||||
..Default::default()
|
||||
|
|
@ -819,7 +844,7 @@ pub mod tests {
|
|||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
||||
|
||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(¶ms);
|
||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_dict_builders(¶ms);
|
||||
let signer = Signer(SecretKey(BigUint::one()));
|
||||
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
||||
let signer = Signer(SecretKey(2u64.into()));
|
||||
|
|
@ -850,9 +875,8 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_mini_0() {
|
||||
let params = middleware::Params {
|
||||
max_input_signed_pods: 1,
|
||||
max_input_recursive_pods: 1,
|
||||
max_signed_pod_values: 6,
|
||||
max_signed_by: 1,
|
||||
max_input_pods: 1,
|
||||
max_statements: 8,
|
||||
max_public_statements: 4,
|
||||
max_input_pods_public_statements: 10,
|
||||
|
|
@ -862,7 +886,7 @@ pub mod tests {
|
|||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
||||
|
||||
let mut gov_id_builder = frontend::SignedPodBuilder::new(¶ms);
|
||||
let mut gov_id_builder = frontend::SignedDictBuilder::new(¶ms);
|
||||
gov_id_builder.insert("idNumber", "4242424242");
|
||||
gov_id_builder.insert("dateOfBirth", 1169909384);
|
||||
gov_id_builder.insert("socialSecurityNumber", "G2121210");
|
||||
|
|
@ -870,7 +894,10 @@ pub mod tests {
|
|||
let gov_id = gov_id_builder.sign(&signer).unwrap();
|
||||
let now_minus_18y: i64 = 1169909388;
|
||||
let mut kyc_builder = frontend::MainPodBuilder::new(¶ms, &vd_set);
|
||||
kyc_builder.add_signed_pod(&gov_id);
|
||||
|
||||
kyc_builder
|
||||
.priv_op(frontend::Operation::dict_signed_by(&gov_id))
|
||||
.unwrap();
|
||||
kyc_builder
|
||||
.pub_op(frontend::Operation::lt(
|
||||
(&gov_id, "dateOfBirth"),
|
||||
|
|
@ -902,9 +929,8 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_mini_1() {
|
||||
let params = middleware::Params {
|
||||
max_input_signed_pods: 0,
|
||||
max_input_recursive_pods: 0,
|
||||
max_signed_pod_values: 0,
|
||||
max_signed_by: 0,
|
||||
max_input_pods: 0,
|
||||
max_statements: 2,
|
||||
max_public_statements: 1,
|
||||
max_input_pods_public_statements: 0,
|
||||
|
|
@ -939,13 +965,12 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_mainpod_small_empty() {
|
||||
let params = middleware::Params {
|
||||
max_input_signed_pods: 0,
|
||||
max_input_recursive_pods: 0,
|
||||
max_signed_by: 0,
|
||||
max_input_pods: 0,
|
||||
max_input_pods_public_statements: 2,
|
||||
max_statements: 5,
|
||||
max_signed_pod_values: 2,
|
||||
max_public_statements: 2,
|
||||
num_public_statements_id: 4,
|
||||
num_public_statements_hash: 4,
|
||||
max_statement_args: 4,
|
||||
max_operation_args: 4,
|
||||
max_custom_predicate_batches: 2,
|
||||
|
|
@ -996,7 +1021,7 @@ pub mod tests {
|
|||
let alice_attestation = attest_eth_friend(¶ms, &alice, bob.public_key());
|
||||
let bob_attestation = attest_eth_friend(¶ms, &bob, charlie.public_key());
|
||||
|
||||
let helper = EthDosHelper::new(¶ms, vd_set, false, alice.public_key())?;
|
||||
let helper = EthDosHelper::new(¶ms, vd_set, alice.public_key())?;
|
||||
let prover = Prover {};
|
||||
let dist_1 = helper.dist_1(&alice_attestation)?.prove(&prover)?;
|
||||
crate::measure_gates_print!();
|
||||
|
|
@ -1010,8 +1035,8 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_main_mini_custom_1() -> frontend::Result<()> {
|
||||
let params = Params {
|
||||
max_input_signed_pods: 0,
|
||||
max_input_recursive_pods: 0,
|
||||
max_signed_by: 0,
|
||||
max_input_pods: 0,
|
||||
max_statements: 9,
|
||||
max_public_statements: 4,
|
||||
max_statement_args: 4,
|
||||
|
|
@ -1020,7 +1045,7 @@ pub mod tests {
|
|||
max_custom_batch_size: 3,
|
||||
max_custom_predicate_wildcards: 4,
|
||||
max_custom_predicate_verifications: 2,
|
||||
max_merkle_proofs_containers: 0,
|
||||
max_merkle_proofs_containers: 3,
|
||||
max_merkle_tree_state_transition_proofs_containers: 0,
|
||||
..Default::default()
|
||||
};
|
||||
|
|
@ -1030,17 +1055,20 @@ pub mod tests {
|
|||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
||||
|
||||
let mut cpb_builder = CustomPredicateBatchBuilder::new(params.clone(), "cpb".into());
|
||||
let stb0 = STB::new(NP::Equal).arg(("id", "score")).arg(literal(42));
|
||||
let stb0 = STB::new(NP::Contains)
|
||||
.arg("dict")
|
||||
.arg(literal("score"))
|
||||
.arg(literal(42));
|
||||
let stb1 = STB::new(NP::Equal)
|
||||
.arg(("secret_id", "key"))
|
||||
.arg(("id", "score"));
|
||||
.arg(("secret_dict", "key"))
|
||||
.arg(("dict", "score"));
|
||||
let _ = cpb_builder.predicate_and(
|
||||
"pred_and",
|
||||
&["id"],
|
||||
&["secret_id"],
|
||||
&["dict"],
|
||||
&["secret_dict"],
|
||||
&[stb0.clone(), stb1.clone()],
|
||||
)?;
|
||||
let _ = cpb_builder.predicate_or("pred_or", &["id"], &["secret_id"], &[stb0, stb1])?;
|
||||
let _ = cpb_builder.predicate_or("pred_or", &["dict"], &["secret_dict"], &[stb0, stb1])?;
|
||||
let cpb = cpb_builder.finish();
|
||||
|
||||
let cpb_and = CustomPredicateRef::new(cpb.clone(), 0);
|
||||
|
|
@ -1048,9 +1076,17 @@ pub mod tests {
|
|||
|
||||
let mut pod_builder = MainPodBuilder::new(¶ms, &vd_set);
|
||||
|
||||
let st0 = pod_builder.priv_op(frontend::Operation::new_entry("score", 42))?;
|
||||
let st1 = pod_builder.priv_op(frontend::Operation::new_entry("key", 42))?;
|
||||
let st2 = pod_builder.priv_op(frontend::Operation::eq(st1.clone(), st0.clone()))?;
|
||||
let dict = dict!(32, {"score" => 42})?;
|
||||
let secret_dict = dict!(32, {"key" => 42})?;
|
||||
let st0 = pod_builder.priv_op(frontend::Operation::dict_contains(
|
||||
dict.clone(),
|
||||
"score",
|
||||
42,
|
||||
))?;
|
||||
let st2 = pod_builder.priv_op(frontend::Operation::eq(
|
||||
(&secret_dict.clone(), "key"),
|
||||
(&dict, "score"),
|
||||
))?;
|
||||
|
||||
let _st3 = pod_builder.priv_op(frontend::Operation::custom(cpb_and.clone(), [st0, st2]))?;
|
||||
|
||||
|
|
@ -1071,15 +1107,9 @@ pub mod tests {
|
|||
fn test_set_contains() -> frontend::Result<()> {
|
||||
let params = Params::default();
|
||||
let mut builder = MainPodBuilder::new(¶ms, &DEFAULT_VD_SET);
|
||||
let set = [1, 2, 3].into_iter().map(|n| n.into()).collect();
|
||||
let st = builder
|
||||
.pub_op(frontend::Operation::new_entry(
|
||||
"entry",
|
||||
Set::new(params.max_depth_mt_containers, set).unwrap(),
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
builder.pub_op(frontend::Operation::set_contains(st, 1))?;
|
||||
let set: HashSet<_> = [1, 2, 3].into_iter().map(|n| n.into()).collect();
|
||||
let set = Set::new(params.max_depth_mt_containers, set).unwrap();
|
||||
builder.pub_op(frontend::Operation::set_contains(set, 1))?;
|
||||
|
||||
let prover = Prover {};
|
||||
let proof = builder.prove(&prover).unwrap();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue