@@ -510,7 +510,9 @@ pub fn verify_inclusion_proof(
510510 f_n >>= 1 ;
511511 s_n >>= 1 ;
512512 }
513- // 5. Compare sn to 0. Compare r against the root_hash. If sn is equal to 0 and r and the root_hash are equal, then the log has proven the inclusion of hash. Otherwise, fail the proof verification.
513+ // 5. Compare sn to 0. Compare r against the root_hash. If sn is equal to 0
514+ // and r and the root_hash are equal, then the log has proven the
515+ // inclusion of hash. Otherwise, fail the proof verification.
514516 if s_n == 0 && r == root_hash {
515517 Ok ( ( ) )
516518 } else {
@@ -646,10 +648,6 @@ pub fn verify_consistency_proof(
646648/// # Errors
647649///
648650/// Will return an error if proof verification fails.
649- ///
650- /// # Panics
651- ///
652- /// Will panic if there are internal math errors.
653651pub fn verify_subtree_consistency_proof (
654652 proof : & Proof ,
655653 n : u64 ,
@@ -658,101 +656,79 @@ pub fn verify_subtree_consistency_proof(
658656 subtree_hash : Hash ,
659657) -> Result < ( ) , TlogError > {
660658 let Subtree { lo : start, hi : end } = * m;
661- // 1. If end is n, run the following:
662- if end == n {
663- // 1. Set fn to start and sn to end - 1.
664- let mut f_n = start;
665- let mut s_n = end - 1 ;
666- // 2. Set r to node_hash.
667- let mut r = subtree_hash;
668- // 3. Until LSB(fn) is set or sn is 0, right-shift fn and sn equally.
669- while !lsb_set ( f_n) && s_n != 0 {
670- f_n >>= 1 ;
671- s_n >>= 1 ;
672- }
673- // 4. For each value p in the proof array:
674- for p in proof {
675- // 1. If sn is 0, then stop iteration and fail the proof verification.
676- if s_n == 0 {
677- return Err ( TlogError :: InvalidProof ) ;
678- }
679- // 2. Set r to HASH(0x01, || p || r).
680- r = node_hash ( * p, r) ;
681- // 3. Until LSB(sn) is set, right-shift sn.
682- while !lsb_set ( s_n) {
683- s_n >>= 1 ;
684- }
685- // 4. Right-shift sn once more.
686- s_n >>= 1 ;
687- }
688- // 5. Compare sn to 0 and r to root_hash. If either is not equal, fail the proof verification. If all are equal, accept the proof.
689- if s_n == 0 && r == root_hash {
690- Ok ( ( ) )
691- } else {
692- Err ( TlogError :: InvalidProof )
693- }
659+
660+ // If `m` is a subtree of the tree of size `n`, `n` cannot be zero.
661+ if n == 0 {
662+ return Err ( TlogError :: InvalidProof ) ;
694663 }
695- // 2. Otherwise, run the following:
696- else {
697- // 1. If proof is an empty array, stop and fail verification.
664+
665+ // 1. Set `fn` to `start`, `sn` to `end - 1`, and `tn` to `n - 1`.
666+ let mut f_n = start;
667+ let mut s_n = end - 1 ;
668+ let mut t_n = n - 1 ;
669+ let mut f_r: Hash ;
670+ let mut s_r: Hash ;
671+ // 2. Right-shift `fn`, `sn`, and `tn` equally until either `fn` is `sn`
672+ // or both `sn` is not `tn` and `LSB(sn)` is not set.
673+ while ( ( s_n == t_n) || lsb_set ( s_n) ) && f_n != s_n {
674+ f_n >>= 1 ;
675+ s_n >>= 1 ;
676+ t_n >>= 1 ;
677+ }
678+ // 3. If `fn` is `sn`, set `fr` and `sr` to `node_hash`.
679+ let proof_offset;
680+ if f_n == s_n {
681+ f_r = subtree_hash;
682+ s_r = subtree_hash;
683+ proof_offset = 0 ;
684+ } else
685+ // Otherwise:
686+ {
687+ // 1. If `proof` is an empty array, stop and fail verification.
698688 if proof. is_empty ( ) {
699689 return Err ( TlogError :: InvalidProof ) ;
700690 }
701- // 2. If end - start is an exact power of 2, prepend node_hash to the proof array.
702- let mut proof = proof. clone ( ) ;
703- if ( end - start) . is_power_of_two ( ) {
704- proof. insert ( 0 , subtree_hash) ;
705- }
706- // 3. Set fn to start, sn to end - 1, and tn to n - 1.
707- let mut f_n = start;
708- let mut s_n = end - 1 ;
709- let mut t_n = n - 1 ;
710- // 4. Until LSB(sn) is not set or fn is equal to sn, right-shift fn, sn, and tn equally.
711- while lsb_set ( s_n) && f_n != s_n {
712- f_n >>= 1 ;
713- s_n >>= 1 ;
714- t_n >>= 1 ;
691+ // 2. Remove the first value of the `proof` array and set `fr` and `sr` to the removed value.
692+ f_r = proof[ 0 ] ;
693+ s_r = proof[ 0 ] ;
694+ proof_offset = 1 ;
695+ }
696+ // 4. For each value `c` in the `proof` array:
697+ for & c in proof. iter ( ) . skip ( proof_offset) {
698+ // 1. If `tn` is `0`, then stop the iteration and fail the proof verification.
699+ if t_n == 0 {
700+ return Err ( TlogError :: InvalidProof ) ;
715701 }
716- // 5. Set both fr and sr to the first value in the proof array.
717- let mut f_r = proof[ 0 ] ;
718- let mut s_r = proof[ 0 ] ;
719- // 6. For each subsequent value c in the proof array:
720- for c in proof. into_iter ( ) . skip ( 1 ) {
721- // 1. If tn is 0, then stop the iteration and fail the proof verification.
722- if t_n == 0 {
723- return Err ( TlogError :: InvalidProof ) ;
702+ // 2. If `LSB(sn)` is set, or if `sn` is equal to `tn`, then:
703+ if lsb_set ( s_n) || s_n == t_n {
704+ // 1. If `fn < sn`, set `fr` to `HASH(0x01 || c || fr)`.
705+ if f_n < s_n {
706+ f_r = node_hash ( c, f_r) ;
724707 }
725- // 2. If LSB(sn) is set, or if sn is equal to tn, then:
726- if lsb_set ( s_n) || s_n == t_n {
727- // 1. If fn < sn, set fr to HASH(0x01 || c || fr).
728- if f_n < s_n {
729- f_r = node_hash ( c, f_r) ;
730- }
731- // 2. Set sr to HASH(0x01 || c || sr).
732- s_r = node_hash ( c, s_r) ;
733- // 3. Until LSB(sn) is set, right-shift fn, sn, and tn equally.
734- while !lsb_set ( s_n) {
735- f_n >>= 1 ;
736- s_n >>= 1 ;
737- t_n >>= 1 ;
738- }
739- }
740- // 3. Otherwise:
741- else {
742- // 1. Set sr to HASH(0x01 || sr || c).
743- s_r = node_hash ( s_r, c) ;
708+ // 2. Set `sr` to `HASH(0x01 || c || sr)`.
709+ s_r = node_hash ( c, s_r) ;
710+ // 3. Until `LSB(sn)` is set, right-shift `fn`, `sn`, and `tn` equally.
711+ while !lsb_set ( s_n) {
712+ f_n >>= 1 ;
713+ s_n >>= 1 ;
714+ t_n >>= 1 ;
744715 }
745- // 4. Right-shift fn, sn, and tn once more.
746- f_n >>= 1 ;
747- s_n >>= 1 ;
748- t_n >>= 1 ;
749716 }
750- // 7. Compare tn to 0, fr to node_hash, and sr to root_hash. If any are not equal, fail the proof verification. If all are equal, accept the proof.
751- if t_n == 0 && f_r == subtree_hash && s_r == root_hash {
752- Ok ( ( ) )
753- } else {
754- Err ( TlogError :: InvalidProof )
717+ // 3. Otherwise:
718+ else {
719+ // 1. Set `sr` to `HASH(0x01 || sr || c)`.
720+ s_r = node_hash ( s_r, c) ;
755721 }
722+ // 4. Right-shift `fn`, `sn`, and `tn` once more.
723+ f_n >>= 1 ;
724+ s_n >>= 1 ;
725+ t_n >>= 1 ;
726+ }
727+ // 5. Compare `tn` to `0`, `fr` to `node_hash`, and `sr` to `root_hash`. If any are not equal, fail the proof verification. If all are equal, accept the proof.
728+ if t_n == 0 && f_r == subtree_hash && s_r == root_hash {
729+ Ok ( ( ) )
730+ } else {
731+ Err ( TlogError :: InvalidProof )
756732 }
757733}
758734
@@ -1321,6 +1297,8 @@ mod tests {
13211297 verify_consistency_proof ( & vec ! [ ] , 0 , EMPTY_HASH , 0 , EMPTY_HASH ) . unwrap ( ) ;
13221298 verify_consistency_proof ( & vec ! [ ] , 0 , EMPTY_HASH , 1 , EMPTY_HASH ) . unwrap_err ( ) ;
13231299 verify_consistency_proof ( & vec ! [ ] , 0 , Hash :: default ( ) , 0 , EMPTY_HASH ) . unwrap_err ( ) ;
1300+ verify_consistency_proof ( & vec ! [ Hash :: default ( ) ] , 0 , Hash :: default ( ) , 1 , EMPTY_HASH )
1301+ . unwrap_err ( ) ;
13241302
13251303 // Tree with single leaf.
13261304 verify_inclusion_proof ( & vec ! [ ] , 1 , Hash :: default ( ) , 0 , Hash :: default ( ) ) . unwrap ( ) ;
0 commit comments