@@ -958,7 +958,7 @@ where
958958 // The just-popped branch is completely processed; we know there can be no more keys
959959 // with that prefix. Set the lower bound which can be returned from this method to
960960 // be the next possible prefix, if any.
961- uncalculated_lower_bound = cached_path . increment ( ) ;
961+ uncalculated_lower_bound = increment_and_strip_trailing_zeros ( & cached_path ) ;
962962
963963 continue
964964 }
@@ -1009,7 +1009,7 @@ where
10091009
10101010 // Update the `uncalculated_lower_bound` to indicate that the child whose bit
10111011 // was just set is completely processed.
1012- uncalculated_lower_bound = child_path . increment ( ) ;
1012+ uncalculated_lower_bound = increment_and_strip_trailing_zeros ( & child_path ) ;
10131013
10141014 // Push the current cached branch back onto the stack before looping.
10151015 self . cached_branch_stack . push ( ( cached_path, cached_branch) ) ;
@@ -1053,7 +1053,7 @@ where
10531053 // There is no cached data for the sub-trie at this child, we must recalculate the
10541054 // sub-trie root (this child) using the leaves. Return the range of keys based on the
10551055 // child path.
1056- let child_path_upper = child_path . increment ( ) ;
1056+ let child_path_upper = increment_and_strip_trailing_zeros ( & child_path ) ;
10571057 trace ! (
10581058 target: TRACE_TARGET ,
10591059 lower=?child_path,
@@ -1352,6 +1352,26 @@ enum PopCachedBranchOutcome {
13521352 CalculateLeaves ( ( Nibbles , Option < Nibbles > ) ) ,
13531353}
13541354
1355+ /// Increments the nibbles and strips any trailing zeros.
1356+ ///
1357+ /// This function wraps `Nibbles::increment` and when it returns a value with trailing zeros,
1358+ /// it strips those zeros using bit manipulation on the underlying U256.
1359+ fn increment_and_strip_trailing_zeros ( nibbles : & Nibbles ) -> Option < Nibbles > {
1360+ let mut result = nibbles. increment ( ) ?;
1361+
1362+ // If result is empty, just return it
1363+ if result. is_empty ( ) {
1364+ return Some ( result) ;
1365+ }
1366+
1367+ // Get access to the underlying U256 to detect trailing zeros
1368+ let uint_val = * result. as_mut_uint_unchecked ( ) ;
1369+ let non_zero_prefix_len = 64 - ( uint_val. trailing_zeros ( ) / 4 ) ;
1370+ result. truncate ( non_zero_prefix_len) ;
1371+
1372+ Some ( result)
1373+ }
1374+
13551375#[ cfg( test) ]
13561376mod tests {
13571377 use super :: * ;
@@ -1650,4 +1670,28 @@ mod tests {
16501670 // Assert the proof
16511671 harness. assert_proof ( targets) . expect ( "Proof generation failed" ) ;
16521672 }
1673+
1674+ #[ test]
1675+ fn test_increment_and_strip_trailing_zeros ( ) {
1676+ let test_cases: Vec < ( Nibbles , Option < Nibbles > ) > = vec ! [
1677+ // Basic increment without trailing zeros
1678+ ( Nibbles :: from_nibbles( [ 0x1 , 0x2 , 0x3 ] ) , Some ( Nibbles :: from_nibbles( [ 0x1 , 0x2 , 0x4 ] ) ) ) ,
1679+ // Increment with trailing zeros - should be stripped
1680+ ( Nibbles :: from_nibbles( [ 0x0 , 0x0 , 0xF ] ) , Some ( Nibbles :: from_nibbles( [ 0x0 , 0x1 ] ) ) ) ,
1681+ ( Nibbles :: from_nibbles( [ 0x0 , 0xF , 0xF ] ) , Some ( Nibbles :: from_nibbles( [ 0x1 ] ) ) ) ,
1682+ // Overflow case
1683+ ( Nibbles :: from_nibbles( [ 0xF , 0xF , 0xF ] ) , None ) ,
1684+ // Empty nibbles
1685+ ( Nibbles :: new( ) , None ) ,
1686+ // Single nibble
1687+ ( Nibbles :: from_nibbles( [ 0x5 ] ) , Some ( Nibbles :: from_nibbles( [ 0x6 ] ) ) ) ,
1688+ // All Fs except last - results in trailing zeros after increment
1689+ ( Nibbles :: from_nibbles( [ 0xE , 0xF , 0xF ] ) , Some ( Nibbles :: from_nibbles( [ 0xF ] ) ) ) ,
1690+ ] ;
1691+
1692+ for ( input, expected) in test_cases {
1693+ let result = increment_and_strip_trailing_zeros ( & input) ;
1694+ assert_eq ! ( result, expected, "Failed for input: {:?}" , input) ;
1695+ }
1696+ }
16531697}
0 commit comments