chore(backend): implement more circuit op logic (#173)

* Add backend MerkleProof type

* Add eval_not_contains

* Remove print statement

* Handle some edge cases

* Add test

* Add missing ?

* Optimisation and stylistic changes

* Code review
This commit is contained in:
Ahmad Afuni 2025-04-08 02:15:46 +10:00 committed by GitHub
parent adad695ba5
commit 6528914366
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 502 additions and 48 deletions

View file

@ -9,7 +9,7 @@ use std::any::Any;
use std::fmt;
use crate::{
backends::plonky2::primitives::merkletree::MerkleProof,
backends::plonky2::primitives::merkletree,
middleware::{
self, hash_str, AnchoredKey, Hash, MainPodInputs, NativeOperation, NativePredicate,
NonePod, OperationType, Params, Pod, PodId, PodProver, PodType, Predicate, StatementArg,
@ -44,7 +44,7 @@ pub struct MockMainPod {
statements: Vec<Statement>,
// All Merkle proofs
// TODO: Use a backend-specific representation
merkle_proofs: Vec<MerkleProof>,
merkle_proofs: Vec<MerkleClaimAndProof>,
}
impl fmt::Display for MockMainPod {
@ -227,6 +227,52 @@ impl MockMainPod {
statements
}
/// Extracts and pads Merkle proofs from Contains/NotContains ops.
pub(crate) fn extract_merkle_proofs(
params: &Params,
operations: &[middleware::Operation],
) -> Result<Vec<MerkleClaimAndProof>> {
let mut merkle_proofs = operations
.iter()
.flat_map(|op| match op {
middleware::Operation::ContainsFromEntries(
middleware::Statement::ValueOf(_, root),
middleware::Statement::ValueOf(_, key),
middleware::Statement::ValueOf(_, value),
pf,
) => Some(MerkleClaimAndProof::try_from_middleware(
params,
root,
key,
Some(value),
pf,
)),
middleware::Operation::NotContainsFromEntries(
middleware::Statement::ValueOf(_, root),
middleware::Statement::ValueOf(_, key),
pf,
) => Some(MerkleClaimAndProof::try_from_middleware(
params, root, key, None, pf,
)),
_ => None,
})
.collect::<Result<Vec<_>>>()?;
if merkle_proofs.len() > params.max_merkle_proofs {
return Err(anyhow!(
"The number of required Merkle proofs ({}) exceeds the maximum number ({}).",
merkle_proofs.len(),
params.max_merkle_proofs
));
} else {
fill_pad(
&mut merkle_proofs,
MerkleClaimAndProof::empty(params.max_depth_mt_gadget),
params.max_merkle_proofs,
);
Ok(merkle_proofs)
}
}
fn find_op_arg(
statements: &[Statement],
op_arg: &middleware::Statement,
@ -248,7 +294,7 @@ impl MockMainPod {
}
fn find_op_aux(
merkle_proofs: &[MerkleProof],
merkle_proofs: &[MerkleClaimAndProof],
op_aux: &middleware::OperationAux,
) -> Result<OperationAux> {
match op_aux {
@ -256,7 +302,14 @@ impl MockMainPod {
middleware::OperationAux::MerkleProof(pf_arg) => merkle_proofs
.iter()
.enumerate()
.find_map(|(i, pf)| (pf == pf_arg).then_some(i))
.find_map(|(i, pf)| {
pf.clone()
.try_into()
.ok()
.and_then(|mid_pf: merkletree::MerkleProof| {
(&mid_pf == pf_arg).then_some(i)
})
})
.map(OperationAux::MerkleProofIndex)
.ok_or(anyhow!(
"Merkle proof corresponding to op arg {} not found",
@ -268,7 +321,7 @@ impl MockMainPod {
pub(crate) fn process_private_statements_operations(
params: &Params,
statements: &[Statement],
merkle_proofs: &[MerkleProof],
merkle_proofs: &[MerkleClaimAndProof],
input_operations: &[middleware::Operation],
) -> Result<Vec<Operation>> {
let mut operations = Vec::new();
@ -336,15 +389,9 @@ impl MockMainPod {
// TODO: Insert a new public statement of ValueOf with `key=KEY_TYPE,
// value=PodType::MockMainPod`
let statements = Self::layout_statements(params, &inputs);
let merkle_proofs = inputs
.operations
.iter()
.flat_map(|op| match op {
middleware::Operation::ContainsFromEntries(_, _, _, pf) => Some(pf.clone()),
middleware::Operation::NotContainsFromEntries(_, _, pf) => Some(pf.clone()),
_ => None,
})
.collect::<Vec<_>>();
// Extract Merkle proofs and pad.
let merkle_proofs = Self::extract_merkle_proofs(params, &inputs.operations)?;
let operations = Self::process_private_statements_operations(
params,
&statements,