Skip to content

Commit f026dce

Browse files
committed
Handle some edge cases
1 parent 1c365c0 commit f026dce

File tree

3 files changed

+88
-72
lines changed

3 files changed

+88
-72
lines changed

src/backends/plonky2/circuits/common.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,9 @@ impl Flattenable for MerkleProofTarget {
222222
fn from_flattened(v: &[Target]) -> Self {
223223
let siblings_len = v.len() - 3 - NUM_HASH_OUT_ELTS - 4 * VALUE_SIZE;
224224
assert!(siblings_len % NUM_HASH_OUT_ELTS == 0);
225+
let max_depth = siblings_len / NUM_HASH_OUT_ELTS;
225226
Self {
226-
// TODO!
227-
max_depth: 0,
227+
max_depth,
228228
enabled: BoolTarget::new_unsafe(v[0]),
229229
root: HashOutTarget::from_vec((&v[1..1 + NUM_HASH_OUT_ELTS]).to_vec()),
230230
key: ValueTarget::from_slice(

src/backends/plonky2/circuits/mainpod.rs

Lines changed: 83 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
use anyhow::Result;
1+
use anyhow::{anyhow, Result};
22
use itertools::zip_eq;
33
use plonky2::{
44
hash::{hash_types::HashOutTarget, poseidon::PoseidonHash},
55
iop::{target::BoolTarget, witness::PartialWitness},
66
plonk::circuit_builder::CircuitBuilder,
77
};
88

9-
use crate::backends::plonky2::circuits::common::{
10-
CircuitBuilderPod, OperationTarget, StatementTarget, ValueTarget,
11-
};
129
use crate::backends::plonky2::mock::mainpod;
1310
use crate::backends::plonky2::signedpod::SignedPod;
1411
use crate::backends::plonky2::{
@@ -20,6 +17,13 @@ use crate::middleware::{
2017
hash_str, AnchoredKey, NativeOperation, NativePredicate, Params, PodType, Statement,
2118
StatementArg, ToFields, KEY_TYPE, SELF,
2219
};
20+
use crate::{
21+
backends::plonky2::{
22+
circuits::common::{CircuitBuilderPod, OperationTarget, StatementTarget, ValueTarget},
23+
primitives::merkletree,
24+
},
25+
middleware,
26+
};
2327

2428
use super::{
2529
common::Flattenable,
@@ -61,8 +65,8 @@ impl OperationVerifyGadget {
6165

6266
// Certain operations (Contains/NotContains) will refer to one
6367
// of the provided Merkle proofs (if any).
64-
// TODO: Could `merkle_proofs` be empty?
65-
let resolved_merkle_proof = builder.vec_ref(merkle_proofs, op.aux[0]);
68+
let resolved_merkle_proof =
69+
(merkle_proofs.len() > 0).then(|| builder.vec_ref(merkle_proofs, op.aux[0]));
6670

6771
// The verification may require aux data which needs to be stored in the
6872
// `OperationVerifyTarget` so that we can set during witness generation.
@@ -109,67 +113,75 @@ impl OperationVerifyGadget {
109113
builder: &mut CircuitBuilder<F, D>,
110114
st: &StatementTarget,
111115
op: &OperationTarget,
112-
resolved_merkle_proof: MerkleProofTarget,
116+
resolved_merkle_proof: Option<MerkleProofTarget>,
113117
resolved_op_args: &[StatementTarget],
114118
) -> BoolTarget {
115-
let op_code_ok = op.has_native_type(builder, NativeOperation::NotContainsFromEntries);
116-
117-
// Expect 2 op args of type `ValueOf`.
118-
let op_arg_type_checks = resolved_op_args
119-
.iter()
120-
.take(2)
121-
.map(|op_arg| op_arg.has_native_type(builder, &self.params, NativePredicate::ValueOf))
122-
.collect::<Vec<_>>();
123-
let op_arg_types_ok = builder.all(op_arg_type_checks);
124-
125-
// The values embedded in the op args must be values, i.e. the
126-
// last `STATEMENT_ARG_F_LEN - VALUE_SIZE` slots of each being
127-
// 0.
128-
let merkle_root_arg = &resolved_op_args[0].args[1];
129-
let key_arg = &resolved_op_args[1].args[1];
130-
let op_arg_range_checks = [
131-
builder.statement_arg_is_value(merkle_root_arg),
132-
builder.statement_arg_is_value(key_arg),
133-
];
134-
let op_arg_range_ok = builder.all(op_arg_range_checks);
135-
136-
// Check Merkle proof (verified elsewhere) against op args.
137-
let merkle_proof_checks = [
138-
/* The supplied Merkle proof must be enabled. */
139-
resolved_merkle_proof.enabled,
140-
/* ...and it must be a nonexistence proof. */
141-
builder.not(resolved_merkle_proof.existence),
142-
/* ...for the root-key pair in the resolved op args. */
143-
builder.is_equal_slice(
144-
&merkle_root_arg.elements[..VALUE_SIZE],
145-
&resolved_merkle_proof.root.elements,
146-
),
147-
builder.is_equal_slice(
148-
&key_arg.elements[..VALUE_SIZE],
149-
&resolved_merkle_proof.key.elements,
150-
),
151-
];
152-
153-
let merkle_proof_ok = builder.all(merkle_proof_checks);
154-
155-
// Check output statement
156-
let arg1_key = resolved_op_args[0].args[0].clone();
157-
let arg2_key = resolved_op_args[1].args[0].clone();
158-
let expected_statement = StatementTarget::new_native(
159-
builder,
160-
&self.params,
161-
NativePredicate::NotContains,
162-
&[arg1_key, arg2_key],
163-
);
164-
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
165-
166-
builder.all([
167-
op_code_ok,
168-
op_arg_types_ok,
169-
op_arg_range_ok,
170-
merkle_proof_ok,
171-
st_ok,
172-
])
119+
match resolved_merkle_proof {
120+
None => builder._false(),
121+
Some(resolved_merkle_proof) => {
122+
let op_code_ok =
123+
op.has_native_type(builder, NativeOperation::NotContainsFromEntries);
124+
125+
// Expect 2 op args of type `ValueOf`.
126+
let op_arg_type_checks = resolved_op_args
127+
.iter()
128+
.take(2)
129+
.map(|op_arg| {
130+
op_arg.has_native_type(builder, &self.params, NativePredicate::ValueOf)
131+
})
132+
.collect::<Vec<_>>();
133+
let op_arg_types_ok = builder.all(op_arg_type_checks);
134+
135+
// The values embedded in the op args must be values, i.e. the
136+
// last `STATEMENT_ARG_F_LEN - VALUE_SIZE` slots of each being
137+
// 0.
138+
let merkle_root_arg = &resolved_op_args[0].args[1];
139+
let key_arg = &resolved_op_args[1].args[1];
140+
let op_arg_range_checks = [
141+
builder.statement_arg_is_value(merkle_root_arg),
142+
builder.statement_arg_is_value(key_arg),
143+
];
144+
let op_arg_range_ok = builder.all(op_arg_range_checks);
145+
146+
// Check Merkle proof (verified elsewhere) against op args.
147+
let merkle_proof_checks = [
148+
/* The supplied Merkle proof must be enabled. */
149+
resolved_merkle_proof.enabled,
150+
/* ...and it must be a nonexistence proof. */
151+
builder.not(resolved_merkle_proof.existence),
152+
/* ...for the root-key pair in the resolved op args. */
153+
builder.is_equal_slice(
154+
&merkle_root_arg.elements[..VALUE_SIZE],
155+
&resolved_merkle_proof.root.elements,
156+
),
157+
builder.is_equal_slice(
158+
&key_arg.elements[..VALUE_SIZE],
159+
&resolved_merkle_proof.key.elements,
160+
),
161+
];
162+
163+
let merkle_proof_ok = builder.all(merkle_proof_checks);
164+
165+
// Check output statement
166+
let arg1_key = resolved_op_args[0].args[0].clone();
167+
let arg2_key = resolved_op_args[1].args[0].clone();
168+
let expected_statement = StatementTarget::new_native(
169+
builder,
170+
&self.params,
171+
NativePredicate::NotContains,
172+
&[arg1_key, arg2_key],
173+
);
174+
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
175+
176+
builder.all([
177+
op_code_ok,
178+
op_arg_types_ok,
179+
op_arg_range_ok,
180+
merkle_proof_ok,
181+
st_ok,
182+
])
183+
}
184+
}
173185
}
174186

175187
fn eval_eq_from_entries(
@@ -506,7 +518,11 @@ impl MainPodVerifyTarget {
506518
mp.enabled,
507519
mp.existence,
508520
mp.root,
509-
mp.clone().try_into()?,
521+
mp.clone().try_into().unwrap_or(merkletree::MerkleProof {
522+
existence: mp.existence,
523+
siblings: mp.siblings.clone(),
524+
other_leaf: None,
525+
}),
510526
mp.key,
511527
mp.value,
512528
)?;
@@ -618,7 +634,7 @@ mod tests {
618634
OperationAux::None,
619635
);
620636
let prev_statements = vec![Statement::None.into()];
621-
let merkle_proofs = vec![MerkleProof::empty(32)];
637+
let merkle_proofs = vec![];
622638
operation_verify(
623639
st.clone(),
624640
op,

src/backends/plonky2/mock/mainpod/operation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ impl MerkleProof {
6363
// TODO: Use `enabled` flag.
6464
pub fn empty(max_depth: usize) -> Self {
6565
Self {
66-
enabled: true,
67-
root: kv_hash(&EMPTY_VALUE, Some(EMPTY_VALUE)),
66+
enabled: false,
67+
root: EMPTY_HASH,
6868
key: Value::from(1),
6969
value: EMPTY_VALUE,
7070
existence: false,
7171
siblings: iter::repeat(EMPTY_HASH).take(max_depth).collect(),
72-
case_ii_selector: true,
72+
case_ii_selector: false,
7373
other_key: EMPTY_VALUE,
7474
other_value: EMPTY_VALUE,
7575
}

0 commit comments

Comments
 (0)