@@ -50,9 +50,10 @@ pub struct MerkleClaimAndProofTarget {
5050 pub ( crate ) other_value : ValueTarget ,
5151}
5252
53- /// Allows to verify both proofs of existence and proofs non-existence with the same circuit. If
54- /// only proofs of existence are needed, use `verify_merkle_proof_existence_circuit`, which
55- /// requires less amount of constraints.
53+ /// Allows to verify both proofs of existence and proofs non-existence with the
54+ /// same circuit. If only proofs of existence are needed, use
55+ /// `verify_merkle_proof_existence_circuit`, which requires less amount of
56+ /// constraints.
5657pub fn verify_merkle_proof_circuit (
5758 builder : & mut CircuitBuilder < F , D > ,
5859 proof : & MerkleClaimAndProofTarget ,
@@ -203,12 +204,14 @@ pub struct MerkleProofExistenceTarget {
203204 pub ( crate ) siblings : Vec < HashOutTarget > ,
204205}
205206
206- /// Allows to verify proofs of existence only. If proofs of non-existence are needed, use
207- /// `verify_merkle_proof_circuit`.
207+ /// Allows to verify proofs of existence only. If proofs of non-existence are
208+ /// needed, use `verify_merkle_proof_circuit`.
209+ /// It returns the computed path, in case is needed at other parts of the upper
210+ /// logic to avoid recomputing it again.
208211pub fn verify_merkle_proof_existence_circuit (
209212 builder : & mut CircuitBuilder < F , D > ,
210213 proof : & MerkleProofExistenceTarget ,
211- ) {
214+ ) -> Vec < BoolTarget > {
212215 let max_depth = proof. max_depth ;
213216 let measure = measure_gates_begin ! ( builder, format!( "MerkleProofExist_{}" , max_depth) ) ;
214217
@@ -234,6 +237,8 @@ pub fn verify_merkle_proof_existence_circuit(
234237 builder. connect ( computed_root[ j] , expected_root[ j] ) ;
235238 }
236239 measure_gates_end ! ( builder, measure) ;
240+
241+ return path;
237242}
238243
239244impl MerkleProofExistenceTarget {
@@ -386,10 +391,9 @@ fn kv_hash_target(
386391 builder. hash_n_to_hash_no_pad :: < PoseidonHash > ( inputs)
387392}
388393
389- /// Verifies that the merkletree state
390- /// transition (from old_root to new_root) has been done correctly for the given
391- /// new_key. This will allow verifying correct new leaf insertion, and leaf
392- /// edition&deletion (if needed).
394+ /// Verifies that the merkletree state transition (from old_root to new_root)
395+ /// has been done correctly for the given new_key. This will allow verifying
396+ /// correct new leaf insertion, and leaf edition&deletion (if needed).
393397pub struct MerkleProofStateTransitionTarget {
394398 pub ( crate ) max_depth : usize ,
395399 // `enabled` determines if the merkleproof state transition verification is enabled
@@ -421,9 +425,10 @@ pub fn verify_merkle_state_transition_circuit(
421425 // for now, only type=0 (insertion proof) is supported
422426 builder. connect ( proof. typ , zero) ;
423427
424- // check that for the old_root, the new_key does not exist in the tree
428+ // 1) check that for the old_root, the new_key does not exist in the tree
425429 verify_merkle_proof_circuit ( builder, & proof. proof_non_existence ) ;
426430
431+ // 2) check that for the new_root, the new_key does exist in the tree
427432 let new_key_proof = MerkleProofExistenceTarget {
428433 max_depth : proof. max_depth ,
429434 enabled : proof. enabled ,
@@ -432,25 +437,30 @@ pub fn verify_merkle_state_transition_circuit(
432437 value : proof. new_value ,
433438 siblings : proof. new_siblings . clone ( ) ,
434439 } ;
435- verify_merkle_proof_existence_circuit ( builder, & new_key_proof) ;
440+ let new_leaf_path = verify_merkle_proof_existence_circuit ( builder, & new_key_proof) ;
436441
437- // assert that proof_non_existence.existence==false
442+ // 3.1) assert that proof_non_existence.existence==false
438443 builder. conditional_assert_eq (
439444 proof. enabled . target ,
440445 proof. proof_non_existence . existence . target ,
441446 zero,
442447 ) ;
448+ // 3.2) assert that proof.enabled matches with proof_non_existance.enabled
449+ builder. connect (
450+ proof. proof_non_existence . enabled . target ,
451+ proof. enabled . target ,
452+ ) ;
443453
444- // assert proof_non_existence.root==old_root, and that it uses new_key &
454+ // 4) assert proof_non_existence.root==old_root, and that it uses new_key &
445455 // new_value
446456 for j in 0 ..HASH_SIZE {
447- // assert that proof.proof_non_existence.root == proof.old_root
457+ // 4.1) assert that proof.proof_non_existence.root == proof.old_root
448458 builder. conditional_assert_eq (
449459 proof. enabled . target ,
450460 proof. proof_non_existence . root . elements [ j] ,
451461 proof. old_root . elements [ j] ,
452462 ) ;
453- // assert that the non-existence proof uses the new_key & new_value
463+ // 4.2) assert that the non-existence proof uses the new_key & new_value
454464 builder. conditional_assert_eq (
455465 proof. enabled . target ,
456466 proof. proof_non_existence . key . elements [ j] ,
@@ -463,26 +473,39 @@ pub fn verify_merkle_state_transition_circuit(
463473 ) ;
464474 }
465475
466- // sanity check
467- builder. connect (
468- proof. proof_non_existence . enabled . target ,
469- proof. enabled . target ,
476+ // prepare values for check 5.3).
477+ let other_key_is_empty =
478+ proof
479+ . proof_non_existence
480+ . other_key
481+ . elements
482+ . iter ( )
483+ . fold ( builder. _true ( ) , |acc, e| {
484+ let e_is_zero = builder. is_equal ( * e, zero) ;
485+ builder. and ( acc, e_is_zero)
486+ } ) ;
487+ let old_key_not_empty = builder. not ( other_key_is_empty) ;
488+ let old_leaf_path = keypath_target (
489+ proof. max_depth ,
490+ builder,
491+ & proof. proof_non_existence . other_key ,
470492 ) ;
471493
472- // check that old_siblings & new_siblings match as expected.
473- // Let d=divergence_level, assert that:
474- // 1) old_siblings[i] == new_siblings[i] ∀ i \ {d}
475- // 2) at i==d, if old_siblings[i] != new_siblings[i]:
476- // old_siblings[i] == EMPTY_HASH
477- // new_siblings[i] == old_leaf_hash
494+ // 5) check that old_siblings & new_siblings match as expected. Let
495+ // d=divergence_level, assert that:
496+ // 5.1) old_siblings[i] == new_siblings[i] ∀ i \ {d}
497+ // 5.2) at i==d, if old_siblings[i] != new_siblings[i]: old_siblings[i] ==
498+ // EMPTY_HASH new_siblings[i] == old_leaf_hash
499+ // 5.3) assert that if old_key!=empty, both old_leaf_path&new_leaf_path
500+ // should diverge at the inputted divergence level
478501 let old_siblings = proof. proof_non_existence . siblings . clone ( ) ;
479502 let new_siblings = proof. new_siblings . clone ( ) ;
480503 for i in 0 ..proof. max_depth {
481504 let i_targ = builder. constant ( F :: from_canonical_u64 ( i as u64 ) ) ;
482505 let is_divergence_level = builder. is_equal ( i_targ, proof. divergence_level ) ;
483506
484- // 1) for all i except for i==divergence_level, assert that the siblings
485- // are the same
507+ // 5. 1) for all i except for i==divergence_level, assert that the
508+ // siblings are the same
486509 let old_sibling_i: Vec < Target > = ( 0 ..HASH_SIZE )
487510 . map ( |j| builder. select ( is_divergence_level, zero, old_siblings[ i] . elements [ j] ) )
488511 . collect ( ) ;
@@ -493,10 +516,10 @@ pub fn verify_merkle_state_transition_circuit(
493516 builder. conditional_assert_eq ( proof. enabled . target , old_sibling_i[ j] , new_sibling_i[ j] ) ;
494517 }
495518
496- // 2) when i==d && if old_siblings[i] != new_siblings[i], check that:
497- // old_siblings[i] == EMPTY_HASH && new_siblings[i] == old_leaf_hash
519+ // 5. 2) when i==d && if old_siblings[i] != new_siblings[i], check that:
520+ // old_siblings[i] == EMPTY_HASH && new_siblings[i] == old_leaf_hash
498521
499- // in_case_2 =true if: i==d (= is_divergence_level) && old_siblings[i]!=new_siblings[i]
522+ // in_case_5_2 =true if: i==d (= is_divergence_level) && old_siblings[i]!=new_siblings[i]
500523 let old_is_eq_new = zip_eq ( old_siblings[ i] . elements , new_siblings[ i] . elements ) . fold (
501524 builder. _true ( ) ,
502525 |acc, ( old, new) | {
@@ -505,15 +528,15 @@ pub fn verify_merkle_state_transition_circuit(
505528 } ,
506529 ) ;
507530 let old_is_noteq_new = builder. not ( old_is_eq_new) ;
508- let in_case_2 = builder. and ( old_is_noteq_new, is_divergence_level) ;
531+ let in_case_5_2 = builder. and ( old_is_noteq_new, is_divergence_level) ;
509532
510533 // do the case2's checks
511534 let old_leaf_hash = kv_hash_target (
512535 builder,
513536 & proof. proof_non_existence . other_key ,
514537 & proof. proof_non_existence . other_value ,
515538 ) ;
516- let sel = builder. and ( proof. enabled , in_case_2 ) ;
539+ let sel = builder. and ( proof. enabled , in_case_5_2 ) ;
517540 for j in 0 ..HASH_SIZE {
518541 builder. conditional_assert_eq ( sel. target , old_siblings[ i] . elements [ j] , zero) ;
519542 builder. conditional_assert_eq (
@@ -522,6 +545,18 @@ pub fn verify_merkle_state_transition_circuit(
522545 old_leaf_hash. elements [ j] ,
523546 ) ;
524547 }
548+
549+ // 5.3) assert that if old_key!=empty, both old_leaf_path&new_leaf_path
550+ // should diverge at the inputted divergence level.
551+ let old_key_not_empty_and_divergence_level =
552+ builder. and ( old_key_not_empty, is_divergence_level) ;
553+ let paths_eq_at_d = builder. is_equal ( old_leaf_path[ i] . target , new_leaf_path[ i] . target ) ;
554+ builder. conditional_assert_eq (
555+ old_key_not_empty_and_divergence_level. target ,
556+ // expect them to not be equal, ie. the is_equal check to be 0
557+ paths_eq_at_d. target ,
558+ zero,
559+ ) ;
525560 }
526561
527562 measure_gates_end ! ( builder, measure) ;
@@ -937,11 +972,18 @@ pub mod tests {
937972 }
938973
939974 fn run_state_transition_circuit (
975+ expect_pass : bool ,
940976 max_depth : usize ,
941977 state_transition_proof : & MerkleProofStateTransition ,
942978 ) -> Result < ( ) > {
943979 // sanity check, run the out-circuit proof verification
944- MerkleTree :: verify_state_transition ( max_depth, & state_transition_proof) ?;
980+ if expect_pass {
981+ MerkleTree :: verify_state_transition ( max_depth, & state_transition_proof) ?;
982+ } else {
983+ // expect out-circuit verification to fail
984+ let _ =
985+ MerkleTree :: verify_state_transition ( max_depth, & state_transition_proof) . is_err ( ) ;
986+ }
945987
946988 let config = CircuitConfig :: standard_recursion_config ( ) ;
947989 let mut builder = CircuitBuilder :: < F , D > :: new ( config) ;
@@ -953,8 +995,12 @@ pub mod tests {
953995
954996 // generate & verify proof
955997 let data = builder. build :: < C > ( ) ;
956- let proof = data. prove ( pw) ?;
957- data. verify ( proof) ?;
998+ if expect_pass {
999+ let proof = data. prove ( pw) ?;
1000+ data. verify ( proof) ?;
1001+ } else {
1002+ assert ! ( data. prove( pw) . is_err( ) ) ; // expect prove to fail
1003+ }
9581004 Ok ( ( ) )
9591005 }
9601006
@@ -974,7 +1020,7 @@ pub mod tests {
9741020 let key = RawValue :: from ( 37 ) ;
9751021 let value = RawValue :: from ( 1037 ) ;
9761022 let state_transition_proof = tree. insert ( & key, & value) ?;
977- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1023+ run_state_transition_circuit ( true , max_depth, & state_transition_proof) ?;
9781024 assert_eq ! ( state_transition_proof. old_root, old_root) ;
9791025 assert_eq ! ( state_transition_proof. new_root, tree. root( ) ) ;
9801026
@@ -984,7 +1030,7 @@ pub mod tests {
9841030 let key = RawValue :: from ( 21 ) ;
9851031 let value = RawValue :: from ( 1021 ) ;
9861032 let state_transition_proof = tree. insert ( & key, & value) ?;
987- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1033+ run_state_transition_circuit ( true , max_depth, & state_transition_proof) ?;
9881034 assert_eq ! ( state_transition_proof. old_root, old_root) ;
9891035 assert_eq ! ( state_transition_proof. new_root, tree. root( ) ) ;
9901036
@@ -993,7 +1039,7 @@ pub mod tests {
9931039 let key = RawValue :: from ( 101 ) ;
9941040 let value = RawValue :: from ( 1101 ) ;
9951041 let state_transition_proof = tree. insert ( & key, & value) ?;
996- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1042+ run_state_transition_circuit ( true , max_depth, & state_transition_proof) ?;
9971043 assert_eq ! ( state_transition_proof. old_root, old_root) ;
9981044 assert_eq ! ( state_transition_proof. new_root, tree. root( ) ) ;
9991045
@@ -1011,7 +1057,7 @@ pub mod tests {
10111057 let key = RawValue :: from ( 4294967295 ) ; // 0xffffffff
10121058 let value = RawValue :: from ( 4294967295 ) ;
10131059 let state_transition_proof = tree. insert ( & key, & value) ?;
1014- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1060+ run_state_transition_circuit ( true , max_depth, & state_transition_proof) ?;
10151061 assert_eq ! ( state_transition_proof. old_root, old_root) ;
10161062 assert_eq ! ( state_transition_proof. new_root, tree. root( ) ) ;
10171063
@@ -1022,7 +1068,7 @@ pub mod tests {
10221068 let key = RawValue :: from ( 4026531839 ) ; // 0xefffffff
10231069 let value = RawValue :: from ( 4026531839 ) ;
10241070 let state_transition_proof = tree. insert ( & key, & value) ?;
1025- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1071+ run_state_transition_circuit ( true , max_depth, & state_transition_proof) ?;
10261072 assert_eq ! ( state_transition_proof. old_root, old_root) ;
10271073 assert_eq ! ( state_transition_proof. new_root, tree. root( ) ) ;
10281074
@@ -1045,7 +1091,7 @@ pub mod tests {
10451091 let key = RawValue :: from ( 37 ) ;
10461092 let value = RawValue :: from ( 1037 ) ;
10471093 let state_transition_proof = tree. insert ( & key, & value) ?;
1048- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1094+ run_state_transition_circuit ( true , max_depth, & state_transition_proof) ?;
10491095 assert_eq ! ( state_transition_proof. old_root, old_root) ;
10501096 assert_eq ! ( state_transition_proof. new_root, tree. root( ) ) ;
10511097
@@ -1055,7 +1101,7 @@ pub mod tests {
10551101 let key = RawValue :: from ( 21 ) ;
10561102 let value = RawValue :: from ( 1021 ) ;
10571103 let state_transition_proof = tree. insert ( & key, & value) ?;
1058- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1104+ run_state_transition_circuit ( true , max_depth, & state_transition_proof) ?;
10591105 assert_eq ! ( state_transition_proof. old_root, old_root) ;
10601106 assert_eq ! ( state_transition_proof. new_root, tree. root( ) ) ;
10611107
@@ -1064,6 +1110,7 @@ pub mod tests {
10641110 let key = RawValue :: from ( 101 ) ;
10651111 let value = RawValue :: from ( 1101 ) ;
10661112 let mut state_transition_proof = tree. insert ( & key, & value) ?;
1113+
10671114 // Tamper with state transition.
10681115 const OFFSET : usize = 20 ;
10691116 let other_leaf = state_transition_proof
@@ -1087,7 +1134,8 @@ pub mod tests {
10871134 ) ?;
10881135 state_transition_proof. siblings = altered_proof. siblings ;
10891136 state_transition_proof. new_root = altered_root;
1090- run_state_transition_circuit ( max_depth, & state_transition_proof) ?;
1137+
1138+ run_state_transition_circuit ( false , max_depth, & state_transition_proof) ?;
10911139 assert_eq ! ( state_transition_proof. old_root, old_root) ;
10921140 assert_ne ! ( state_transition_proof. new_root, tree. root( ) ) ; // Tamper check
10931141 Ok ( ( ) )
0 commit comments