diff --git a/book/src/merklestatements.md b/book/src/merklestatements.md index 53297027..918be3fa 100644 --- a/book/src/merklestatements.md +++ b/book/src/merklestatements.md @@ -39,7 +39,7 @@ all of which are represented as `MerkleTree` on the back end. The frontend compound types and their implementation as Merkle trees is explained under [POD value types](./values.md#dictionary-array-set). The backend structure of a MerkleTree is explained on [the Merkle tree page](./merkletree.md). -The POD2 interface provides statements for working with Merkle trees and compond types at all layers of the stack: +The POD2 interface provides statements for working with Merkle trees and compound types at all layers of the stack: - Primitive statements for Merkle trees - General derived statements for Merkle trees - Specialized `ContainsKey`, `NotContainsKey`, and `ContainsValue` statements for the three front-end types. diff --git a/src/backends/plonky2/error.rs b/src/backends/plonky2/error.rs index 088591d5..a0ca4e18 100644 --- a/src/backends/plonky2/error.rs +++ b/src/backends/plonky2/error.rs @@ -63,31 +63,31 @@ macro_rules! new { } use InnerError::*; impl Error { - pub(crate) fn custom(s: String) -> Self { + pub fn custom(s: String) -> Self { new!(Custom(s)) } - pub(crate) fn plonky2_proof_fail(e: anyhow::Error) -> Self { + pub fn plonky2_proof_fail(e: anyhow::Error) -> Self { Self::Plonky2ProofFail(e) } - pub(crate) fn key_not_found() -> Self { + pub fn key_not_found() -> Self { new!(KeyNotFound) } - pub(crate) fn statement_not_check() -> Self { + pub fn statement_not_check() -> Self { new!(StatementNotCheck) } - pub(crate) fn repeated_value_of() -> Self { + pub fn repeated_value_of() -> Self { new!(RepeatedValueOf) } - pub(crate) fn not_type_statement() -> Self { + pub fn not_type_statement() -> Self { new!(NotTypeStatement) } - pub(crate) fn pod_id_invalid() -> Self { + pub fn pod_id_invalid() -> Self { new!(PodIdInvalid) } - pub(crate) fn id_not_equal(expected: PodId, found: PodId) -> Self { + pub fn id_not_equal(expected: PodId, found: PodId) -> Self { new!(IdNotEqual(expected, found)) } - pub(crate) fn type_not_equal(expected: PodType, found: Value) -> Self { + pub fn type_not_equal(expected: PodType, found: Value) -> Self { new!(TypeNotEqual(expected, found)) } } diff --git a/src/backends/plonky2/mainpod/mod.rs b/src/backends/plonky2/mainpod/mod.rs index deaab645..0746ac9d 100644 --- a/src/backends/plonky2/mainpod/mod.rs +++ b/src/backends/plonky2/mainpod/mod.rs @@ -39,7 +39,7 @@ use crate::{ /// `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(crate) fn calculate_id(statements: &[Statement], params: &Params) -> middleware::Hash { +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); @@ -409,7 +409,7 @@ impl Prover { fn _prove(&self, params: &Params, inputs: MainPodInputs) -> Result { let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA; let (main_pod_target, circuit_data) = - RecursiveCircuit::::circuit_data_padded( + RecursiveCircuit::::target_and_circuit_data_padded( params.max_input_recursive_pods, &rec_circuit_data.common, params, @@ -570,11 +570,12 @@ impl MainPod { let rec_circuit_data = &*STANDARD_REC_MAIN_POD_CIRCUIT_DATA; // TODO: cache these artefacts // https://github.com/0xPARC/pod2/issues/247 - let (_, circuit_data) = RecursiveCircuit::::circuit_data_padded( - self.params.max_input_recursive_pods, - &rec_circuit_data.common, - &self.params, - )?; + let (_, circuit_data) = + RecursiveCircuit::::target_and_circuit_data_padded( + self.params.max_input_recursive_pods, + &rec_circuit_data.common, + &self.params, + )?; let public_inputs = id .to_fields(&self.params) .iter() diff --git a/src/backends/plonky2/recursion/circuit.rs b/src/backends/plonky2/recursion/circuit.rs index 0c728fb6..6e95aa6c 100644 --- a/src/backends/plonky2/recursion/circuit.rs +++ b/src/backends/plonky2/recursion/circuit.rs @@ -113,7 +113,7 @@ pub fn new_params_padded( inner_params: &I::Params, ) -> Result { let (_, circuit_data) = - RecursiveCircuit::::circuit_data_padded(arity, common_data, inner_params)?; + RecursiveCircuit::::target_and_circuit_data_padded(arity, common_data, inner_params)?; let common_data = circuit_data.common.clone(); let verifier_data = circuit_data.verifier_data(); Ok(RecursiveParams { @@ -265,7 +265,7 @@ impl RecursiveCircuit { } /// returns the full-recursive CircuitData padded to share the input `common_data` - pub fn circuit_data_padded( + pub fn target_and_circuit_data_padded( arity: usize, common_data: &CommonCircuitData, inner_params: &I::Params, @@ -688,7 +688,7 @@ mod tests { let common_data = &circuit_data_3.common; let (_, circuit_data_1) = - RC::::circuit_data_padded(arity, &common_data, &inner_params)?; + RC::::target_and_circuit_data_padded(arity, &common_data, &inner_params)?; let params_1 = RecursiveParams { arity, common_data: circuit_data_1.common.clone(), @@ -696,7 +696,7 @@ mod tests { }; let (_, circuit_data_2) = - RC::::circuit_data_padded(arity, &common_data, &inner_params)?; + RC::::target_and_circuit_data_padded(arity, &common_data, &inner_params)?; let params_2 = RecursiveParams { arity, common_data: circuit_data_2.common.clone(), diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index c39ddccc..62ad475a 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -645,6 +645,22 @@ impl MainPod { pub fn id(&self) -> PodId { self.pod.id() } + + /// Returns the value of a ValueOf statement with self id that defines key if it exists. + pub fn get(&self, key: impl Into) -> Option { + let key: Key = key.into(); + self.public_statements + .iter() + .find_map(|st| match st { + Statement::ValueOf(ak, value) + if ak.pod_id == self.id() && ak.key.hash() == key.hash() => + { + Some(value) + } + _ => None, + }) + .cloned() + } } struct MainPodCompilerInputs<'a> { @@ -759,6 +775,9 @@ pub mod build_utils { (new_entry, ($key:expr, $value:expr)) => { $crate::frontend::Operation( $crate::middleware::OperationType::Native($crate::middleware::NativeOperation::NewEntry), $crate::op_args!(($key, $value)), $crate::middleware::OperationAux::None) }; + (copy, $($arg:expr),+) => { $crate::frontend::Operation( + $crate::middleware::OperationType::Native($crate::middleware::NativeOperation::CopyStatement), + $crate::op_args!($($arg),*), $crate::middleware::OperationAux::None) }; (eq, $($arg:expr),+) => { $crate::frontend::Operation( $crate::middleware::OperationType::Native($crate::middleware::NativeOperation::EqualFromEntries), $crate::op_args!($($arg),*), $crate::middleware::OperationAux::None) }; diff --git a/src/frontend/operation.rs b/src/frontend/operation.rs index 8e8bb99e..e558ca43 100644 --- a/src/frontend/operation.rs +++ b/src/frontend/operation.rs @@ -1,7 +1,7 @@ use std::fmt; use crate::{ - frontend::SignedPod, + frontend::{MainPod, SignedPod}, middleware::{AnchoredKey, OperationAux, OperationType, Statement, Value}, }; @@ -78,6 +78,18 @@ impl From<(&SignedPod, &str)> for OperationArg { )) } } +impl From<(&MainPod, &str)> for OperationArg { + fn from((pod, key): (&MainPod, &str)) -> Self { + // TODO: TryFrom. + let value = pod + .get(key) + .unwrap_or_else(|| panic!("Key {} is not present in POD: {}", key, pod)); + Self::Statement(Statement::ValueOf( + AnchoredKey::from((pod.id(), key)), + value, + )) + } +} impl From for OperationArg { fn from(s: Statement) -> Self {