1- use anyhow:: Result ;
1+ use anyhow:: { anyhow , Result } ;
22use itertools:: zip_eq;
33use 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- } ;
129use crate :: backends:: plonky2:: mock:: mainpod;
1310use crate :: backends:: plonky2:: signedpod:: SignedPod ;
1411use 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
2428use 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,
0 commit comments