@@ -24,7 +24,7 @@ use std::iter::IntoIterator;
2424
2525use crate :: backends:: counter;
2626use crate :: backends:: plonky2:: basetypes:: {
27- hash_fields, Hash , Value , D , F , HASH_SIZE , NULL , VALUE_SIZE ,
27+ hash_fields, Hash , Value , D , EMPTY , F , HASH_SIZE , NULL , VALUE_SIZE ,
2828} ;
2929use crate :: backends:: plonky2:: primitives:: merkletree:: MerkleProof ;
3030
@@ -34,6 +34,10 @@ pub struct MerkleProofCircuit<const MAX_DEPTH: usize> {
3434 value : Vec < Target > ,
3535 existence : BoolTarget ,
3636 siblings : Vec < HashOutTarget > ,
37+ // siblings_selectors: Vec<BoolTarget>,
38+ case_ii_selector : BoolTarget , // for case ii)
39+ other_key : Vec < Target > ,
40+ other_value : Vec < Target > ,
3741}
3842
3943impl < const MAX_DEPTH : usize > MerkleProofCircuit < MAX_DEPTH > {
@@ -48,22 +52,94 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
4852 // siblings are padded
4953 let siblings = builder. add_virtual_hashes ( MAX_DEPTH ) ;
5054
51- let h = Self :: compute_root_from_leaf ( builder, & key, & value, & siblings) ?;
52- builder. connect_hashes ( h, root) ;
55+ let case_ii_selector = builder. add_virtual_bool_target_safe ( ) ;
56+ let other_key = builder. add_virtual_targets ( VALUE_SIZE ) ;
57+ let other_value = builder. add_virtual_targets ( VALUE_SIZE ) ;
58+
59+ // We have 3 cases for when computing the Leaf's hash:
60+ // - existence: leaf contains the given key & value
61+ // - non-existence:
62+ // - case i) expected leaf does not exist
63+ // - case ii) expected leaf does exist but it has a different key
64+ //
65+ // The following table expresses the options with their in-circuit
66+ // selectors:
67+ // | existence | case_ii | leaf_hash |
68+ // | ----------- | --------- | ---------------------------- |
69+ // | 1 | 0 | H(key, value, 1) |
70+ // | 0 | 0 | EMPTY_HASH |
71+ // | 0 | 1 | H(other_key, other_value, 1) |
72+ // | 1 | 1 | invalid combination |
73+
74+ // First, ensure that both existence & case_ii are not true at the same
75+ // time:
76+ // 1. sum = existence + case_ii_selector
77+ let sum = builder. add ( existence. target , case_ii_selector. target ) ;
78+ // 2. sum * (sum-1) == 0
79+ builder. assert_bool ( BoolTarget :: new_unsafe ( sum) ) ;
80+
81+ // define the case_i_selector as true when both existence and
82+ // case_ii_selector are false:
83+ // case_i_selector = (1 - existence) * (1- case_ii_selector)
84+ let one = builder. one ( ) ;
85+ let existence_inv = builder. sub ( one, existence. target ) ;
86+ let case_ii_inv = builder. sub ( one, case_ii_selector. target ) ;
87+ let case_i_selector = BoolTarget :: new_unsafe ( builder. mul ( existence_inv, case_ii_inv) ) ;
88+
89+ // use (key,value) or (other_key, other_value) depending if it's a proof
90+ // of existence or of non-existence, ie:
91+ // k = key * existence + other_key * (1-existence)
92+ // v = value * existence + other_value * (1-existence)
93+ let k: Vec < Target > = ( 0 ..4 )
94+ . map ( |j| builder. select ( existence, key[ j] , other_key[ j] ) )
95+ . collect ( ) ;
96+ let v: Vec < Target > = ( 0 ..4 )
97+ . map ( |j| builder. select ( existence, value[ j] , other_value[ j] ) )
98+ . collect ( ) ;
99+
100+ // get leaf's hash for the selected k & v
101+ let h = Self :: kv_hash_target ( builder, & k, & v) ;
102+
103+ // if we're in the case i), use leaf_hash=EMPTY_HASH, else use the
104+ // previously computed hash h.
105+ let empty_hash = builder. constant_hash ( HashOut :: from ( NULL . 0 ) ) ;
106+ let leaf_hash = HashOutTarget :: from_vec (
107+ ( 0 ..4 )
108+ . map ( |j| builder. select ( case_i_selector, empty_hash. elements [ j] , h. elements [ j] ) )
109+ . collect ( ) ,
110+ ) ;
111+
112+ // get key's path
113+ let path = Self :: keypath_target ( builder, & key) ;
114+
115+ // compute the root for the given siblings and the computed leaf_hash
116+ // (this is for the three cases (existence, non-existence case i, and
117+ // non-existence case ii)
118+ let computed_root = Self :: compute_root_from_leaf (
119+ builder, & path, & leaf_hash, & siblings,
120+ // &siblings_selectors,
121+ ) ?;
122+ // ensure that the computed root matches the given root (which is a
123+ // public input)
124+ builder. connect_hashes ( computed_root, root) ;
53125
54126 Ok ( Self {
55127 existence,
56128 root,
57129 siblings,
58130 key,
59131 value,
132+ case_ii_selector,
133+ other_key,
134+ other_value,
60135 } )
61136 }
62137
63138 /// assigns the given values to the targets
64139 fn set_targets (
65140 & self ,
66141 pw : & mut PartialWitness < F > ,
142+ existence : bool ,
67143 root : Hash ,
68144 proof : MerkleProof ,
69145 key : Value ,
@@ -72,7 +148,7 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
72148 pw. set_hash_target ( self . root , HashOut :: from_vec ( root. 0 . to_vec ( ) ) ) ?;
73149 pw. set_target_arr ( & self . key , & key. 0 . to_vec ( ) ) ?;
74150 pw. set_target_arr ( & self . value , & value. 0 . to_vec ( ) ) ?;
75- pw. set_bool_target ( self . existence , proof . existence ) ?;
151+ pw. set_bool_target ( self . existence , existence) ?;
76152
77153 // pad siblings with zeros to length MAX_DEPTH
78154 let mut siblings = proof. siblings . clone ( ) ;
@@ -83,13 +159,25 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
83159 pw. set_hash_target ( self . siblings [ i] , HashOut :: from_vec ( sibling. 0 . to_vec ( ) ) ) ;
84160 }
85161
162+ if !existence && proof. other_leaf . is_some ( ) {
163+ // non-existence case ii) expected leaf does exist but it has a different key
164+ pw. set_bool_target ( self . case_ii_selector , true ) ?;
165+ pw. set_target_arr ( & self . other_key , & proof. other_leaf . unwrap ( ) . 0 . 0 . to_vec ( ) ) ?;
166+ pw. set_target_arr ( & self . other_value , & proof. other_leaf . unwrap ( ) . 1 . 0 . to_vec ( ) ) ?;
167+ } else {
168+ // existence & non-existence case i) expected leaf does not exist
169+ pw. set_bool_target ( self . case_ii_selector , false ) ?;
170+ pw. set_target_arr ( & self . other_key , & EMPTY . 0 . to_vec ( ) ) ?;
171+ pw. set_target_arr ( & self . other_value , & EMPTY . 0 . to_vec ( ) ) ?;
172+ }
173+
86174 Ok ( ( ) )
87175 }
88176
89177 fn compute_root_from_leaf (
90178 builder : & mut CircuitBuilder < F , D > ,
91- key : & Vec < Target > ,
92- value : & Vec < Target > ,
179+ path : & Vec < BoolTarget > ,
180+ leaf_hash : & HashOutTarget ,
93181 siblings : & Vec < HashOutTarget > ,
94182 ) -> Result < HashOutTarget > {
95183 assert ! ( siblings. len( ) <= MAX_DEPTH ) ;
@@ -116,58 +204,31 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
116204 . rev ( )
117205 . collect :: < Vec < _ > > ( ) ;
118206
119- // get key's path
120- let path = Self :: keypath_target ( builder, key) ;
121- // get leaf's hash
122- let mut h = Self :: kv_hash_target ( builder, key, value) ;
123-
207+ let mut h = leaf_hash. clone ( ) ;
124208 let one: Target = builder. one ( ) ; // constant in-circuit
125209 for ( i, ( sibling, selector) ) in std:: iter:: zip ( siblings, & sibling_selectors)
126210 . enumerate ( )
127211 . rev ( )
128212 {
129213 // to compute the hash, we want to do the following 3 steps:
130214 // Let s := path[i], then
131- // input_1 = sibling * s + h * (1-s)
132- // input_2 = sibling * (1-s) + h * s
215+ // input_1 = sibling * s + h * (1-s) = select(s, sibling, h)
216+ // input_2 = sibling * (1-s) + h * s = select(s, h, sibling)
133217 // new_h = hash([input_1, input_2])
134-
135- // TODO group multiple muls in a single gate
136- let bit: Target = path[ i] . target ;
137- let bit_inv: Target = builder. sub ( one, bit) ;
138-
139- let input_1_sibling: Vec < Target > = sibling
140- . elements
141- . iter ( )
142- . map ( |e| builder. mul ( * e, bit) )
143- . collect ( ) ;
144- let input_1_h: Vec < Target > = h
145- . elements
146- . iter ( )
147- . map ( |e| builder. mul ( * e, bit_inv) )
148- . collect ( ) ;
218+ // TODO explore if to group multiple muls in a single gate
219+ let bit: BoolTarget = path[ i] ;
149220 let input_1: Vec < Target > = ( 0 ..4 )
150- . map ( |j| builder. add ( input_1_sibling [ j] , input_1_h [ j] ) )
221+ . map ( |j| builder. select ( bit , sibling . elements [ j] , h . elements [ j] ) )
151222 . collect ( ) ;
152-
153- let input_2_sibling: Vec < Target > = sibling
154- . elements
155- . iter ( )
156- . map ( |e| builder. mul ( * e, bit_inv) )
157- . collect ( ) ;
158- let input_2_h: Vec < Target > = h. elements . iter ( ) . map ( |e| builder. mul ( * e, bit) ) . collect ( ) ;
159223 let input_2: Vec < Target > = ( 0 ..4 )
160- . map ( |j| builder. add ( input_2_sibling [ j] , input_2_h [ j] ) )
224+ . map ( |j| builder. select ( bit , h . elements [ j] , sibling . elements [ j] ) )
161225 . collect ( ) ;
162226
163227 let new_h = builder. hash_n_to_hash_no_pad :: < PoseidonHash > ( [ input_1, input_2] . concat ( ) ) ;
164228
165- // Let s := sibling_selectors[i], then h = new_h * s + h * (1-s)
166- let s: Target = selector. target ;
167- let s_inv: Target = builder. sub ( one, s) ;
168- let new_h_s: Vec < Target > = new_h. elements . iter ( ) . map ( |e| builder. mul ( * e, s) ) . collect ( ) ;
169- let h_s: Vec < Target > = h. elements . iter ( ) . map ( |e| builder. mul ( * e, s_inv) ) . collect ( ) ;
170- let h_targ = ( 0 ..4 ) . map ( |j| builder. add ( new_h_s[ j] , h_s[ j] ) ) . collect ( ) ;
229+ let h_targ: Vec < Target > = ( 0 ..4 )
230+ . map ( |j| builder. select ( * selector, new_h. elements [ j] , h. elements [ j] ) )
231+ . collect ( ) ;
171232 h = HashOutTarget :: from_vec ( h_targ) ;
172233 }
173234 Ok ( h)
@@ -305,43 +366,132 @@ pub mod tests {
305366 }
306367
307368 #[ test]
308- fn test_merkleproof_verify ( ) -> Result < ( ) > {
309- test_merkleproof_verify_opt :: < 10 > ( ) ?;
310- test_merkleproof_verify_opt :: < 16 > ( ) ?;
311- test_merkleproof_verify_opt :: < 32 > ( ) ?;
312- test_merkleproof_verify_opt :: < 40 > ( ) ?;
313- test_merkleproof_verify_opt :: < 64 > ( ) ?;
314- test_merkleproof_verify_opt :: < 128 > ( ) ?;
315- test_merkleproof_verify_opt :: < 130 > ( ) ?;
316- test_merkleproof_verify_opt :: < 250 > ( ) ?;
317- test_merkleproof_verify_opt :: < 256 > ( ) ?;
369+ fn test_merkleproof_verify_existence ( ) -> Result < ( ) > {
370+ test_merkleproof_verify_opt :: < 10 > ( true ) ?;
371+ test_merkleproof_verify_opt :: < 16 > ( true ) ?;
372+ test_merkleproof_verify_opt :: < 32 > ( true ) ?;
373+ test_merkleproof_verify_opt :: < 40 > ( true ) ?;
374+ test_merkleproof_verify_opt :: < 64 > ( true ) ?;
375+ test_merkleproof_verify_opt :: < 128 > ( true ) ?;
376+ test_merkleproof_verify_opt :: < 130 > ( true ) ?;
377+ test_merkleproof_verify_opt :: < 250 > ( true ) ?;
378+ test_merkleproof_verify_opt :: < 256 > ( true ) ?;
379+ Ok ( ( ) )
380+ }
381+ #[ test]
382+ fn test_merkleproof_verify_nonexistence ( ) -> Result < ( ) > {
383+ test_merkleproof_verify_opt :: < 10 > ( false ) ?;
384+ test_merkleproof_verify_opt :: < 16 > ( false ) ?;
385+ test_merkleproof_verify_opt :: < 32 > ( false ) ?;
386+ test_merkleproof_verify_opt :: < 40 > ( false ) ?;
387+ test_merkleproof_verify_opt :: < 64 > ( false ) ?;
388+ test_merkleproof_verify_opt :: < 128 > ( false ) ?;
389+ test_merkleproof_verify_opt :: < 130 > ( false ) ?;
390+ test_merkleproof_verify_opt :: < 250 > ( false ) ?;
391+ test_merkleproof_verify_opt :: < 256 > ( false ) ?;
318392 Ok ( ( ) )
319393 }
320394
321- fn test_merkleproof_verify_opt < const MD : usize > ( ) -> Result < ( ) > {
395+ // test logic to be reused both by the existence & nonexistence tests
396+ fn test_merkleproof_verify_opt < const MD : usize > ( existence : bool ) -> Result < ( ) > {
322397 let mut kvs: HashMap < Value , Value > = HashMap :: new ( ) ;
323- for i in 0 ..8 {
324- kvs. insert (
325- Value :: from ( hash_value ( & Value :: from ( i) ) ) ,
326- Value :: from ( 1000 + i) ,
327- ) ;
398+ for i in 0 ..10 {
399+ kvs. insert ( Value :: from ( hash_value ( & Value :: from ( i) ) ) , Value :: from ( i) ) ;
328400 }
329401
330402 let tree = MerkleTree :: new ( MD , & kvs) ?;
331403
332- let key = Value :: from ( hash_value ( & Value :: from ( 5 ) ) ) ;
333- let ( value, proof) = tree. prove ( & key) ?;
334- assert_eq ! ( value, Value :: from( 1005 ) ) ;
404+ let ( key, value, proof) = if existence {
405+ let key = Value :: from ( hash_value ( & Value :: from ( 5 ) ) ) ;
406+ let ( value, proof) = tree. prove ( & key) ?;
407+ assert_eq ! ( value, Value :: from( 5 ) ) ;
408+ ( key, value, proof)
409+ } else {
410+ let key = Value :: from ( hash_value ( & Value :: from ( 200 ) ) ) ;
411+ ( key, EMPTY , tree. prove_nonexistence ( & key) ?)
412+ } ;
413+ assert_eq ! ( proof. existence, existence) ;
335414
336- MerkleTree :: verify ( MD , tree. root ( ) , & proof, & key, & value) ?;
415+ if existence {
416+ MerkleTree :: verify ( MD , tree. root ( ) , & proof, & key, & value) ?;
417+ } else {
418+ MerkleTree :: verify_nonexistence ( MD , tree. root ( ) , & proof, & key) ?;
419+ }
420+
421+ // circuit
422+ let config = CircuitConfig :: standard_recursion_config ( ) ;
423+ let mut builder = CircuitBuilder :: < F , D > :: new ( config) ;
424+ let mut pw = PartialWitness :: < F > :: new ( ) ;
425+
426+ let targets = MerkleProofCircuit :: < MD > :: add_targets ( & mut builder) ?;
427+ targets. set_targets ( & mut pw, existence, tree. root ( ) , proof, key, value) ?;
428+
429+ // generate & verify proof
430+ let data = builder. build :: < C > ( ) ;
431+ let proof = data. prove ( pw) ?;
432+ data. verify ( proof) ?;
433+
434+ Ok ( ( ) )
435+ }
436+
437+ #[ test]
438+ fn test_merkletree_edgecases ( ) -> Result < ( ) > {
439+ // fill the tree as in https://0xparc.github.io/pod2/merkletree.html#example-3
440+ //
441+ // root
442+ // / \
443+ // () ()
444+ // / \ /
445+ // 0 2 ()
446+ // \
447+ // ()
448+ // /\
449+ // 5 13
450+
451+ let mut kvs = HashMap :: new ( ) ;
452+ kvs. insert ( Value :: from ( 0 ) , Value :: from ( 1000 ) ) ;
453+ kvs. insert ( Value :: from ( 2 ) , Value :: from ( 1002 ) ) ;
454+ kvs. insert ( Value :: from ( 5 ) , Value :: from ( 1005 ) ) ;
455+ kvs. insert ( Value :: from ( 13 ) , Value :: from ( 1013 ) ) ;
456+
457+ const MD : usize = 5 ;
458+ let tree = MerkleTree :: new ( MD , & kvs) ?;
459+ // existence
460+ test_merkletree_edgecase_opt :: < MD > ( & tree, Value :: from ( 5 ) ) ?;
461+ // non-existence case i) expected leaf does not exist
462+ test_merkletree_edgecase_opt :: < MD > ( & tree, Value :: from ( 1 ) ) ?;
463+ // non-existence case ii) expected leaf does exist but it has a different 'key'
464+ test_merkletree_edgecase_opt :: < MD > ( & tree, Value :: from ( 21 ) ) ?;
465+
466+ Ok ( ( ) )
467+ }
468+
469+ fn test_merkletree_edgecase_opt < const MD : usize > ( tree : & MerkleTree , key : Value ) -> Result < ( ) > {
470+ let contains = tree. contains ( & key) ?;
471+ // generate merkleproof
472+ let ( value, proof) = if contains {
473+ tree. prove ( & key) ?
474+ } else {
475+ let proof = tree. prove_nonexistence ( & key) ?;
476+ ( EMPTY , proof)
477+ } ;
478+
479+ assert_eq ! ( proof. existence, contains) ;
480+
481+ // verify the proof (non circuit)
482+ if proof. existence {
483+ MerkleTree :: verify ( MD , tree. root ( ) , & proof, & key, & value) ?;
484+ } else {
485+ MerkleTree :: verify_nonexistence ( MD , tree. root ( ) , & proof, & key) ?;
486+ }
337487
338488 // circuit
339489 let config = CircuitConfig :: standard_recursion_config ( ) ;
340490 let mut builder = CircuitBuilder :: < F , D > :: new ( config) ;
341491 let mut pw = PartialWitness :: < F > :: new ( ) ;
342492
343493 let targets = MerkleProofCircuit :: < MD > :: add_targets ( & mut builder) ?;
344- targets. set_targets ( & mut pw, tree. root ( ) , proof, key, value) ?;
494+ targets. set_targets ( & mut pw, proof . existence , tree. root ( ) , proof, key, value) ?;
345495
346496 // generate & verify proof
347497 let data = builder. build :: < C > ( ) ;
0 commit comments