fix path rewind

decrement by epsilon, and go up to parent from child 0
This commit is contained in:
Roy Crihfield 2023-08-30 00:24:09 +08:00
parent 9d890b2282
commit 9201eca2b4

View File

@ -129,10 +129,9 @@ func (tr *Tracker) Restore(makeIterator iter.IteratorConstructor) ([]trie.NodeIt
} }
// force the lower bound path to an even length (required by geth API/HexToKeyBytes) // force the lower bound path to an even length (required by geth API/HexToKeyBytes)
if len(recoveredPath)&0b1 == 1 { if len(recoveredPath)&1 == 1 {
// decrement first to avoid skipped nodes // to avoid skipped nodes, we must rewind by one index
decrementPath(recoveredPath) recoveredPath = rewindPath(recoveredPath)
recoveredPath = append(recoveredPath, 0)
} }
it := makeIterator(iter.HexToKeyBytes(recoveredPath)) it := makeIterator(iter.HexToKeyBytes(recoveredPath))
boundIt := iter.NewPrefixBoundIterator(it, endPath) boundIt := iter.NewPrefixBoundIterator(it, endPath)
@ -185,25 +184,22 @@ func (it *Iterator) Next(descend bool) bool {
return ret return ret
} }
// Subtracts 1 from the last byte in a path slice, carrying if needed. // Rewinds to the path of the previous (pre-order) node:
// Does nothing, returning false, for all-zero inputs (underflow). // If the last byte of the path is zero, pops it. Otherwise, decrements it
func decrementPath(path []byte) bool { // and pads with 0xF to 64 bytes (e.g. [1] => [0 f f f ...]).
// check for all zeros // Returns the passed path (which is also modified in place)
allzero := true func rewindPath(path []byte) []byte {
for i := 0; i < len(path); i++ { if len(path) == 0 {
allzero = allzero && path[i] == 0 return path
} }
if allzero { if path[len(path)-1] == 0 {
return false return path[:len(path)-1]
} }
for i := len(path) - 1; i >= 0; i-- { path[len(path)-1]--
val := path[i] padded := make([]byte, 64)
path[i]-- i := copy(padded, path)
if val == 0 { for ; i < len(padded); i++ {
path[i] = 0xf padded[i] = 0xf
} else {
return true
}
} }
return true return padded
} }