mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
trie/bintrie: fix NodeIterator Empty node handling
Fix three issues in the binary trie NodeIterator: 1. Empty nodes now properly backtrack to parent and continue iteration instead of terminating the entire walk early. 2. HashedNode resolver handles nil data (all-zeros hash) gracefully by treating it as Empty rather than panicking. 3. Parent update after node resolution guards against stack underflow when resolving the root node itself.
This commit is contained in:
parent
35b91092c5
commit
6cc4dc5f10
1 changed files with 24 additions and 8 deletions
|
|
@ -119,10 +119,17 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
|
|||
return it.Next(descend)
|
||||
case HashedNode:
|
||||
// resolve the node
|
||||
data, err := it.trie.nodeResolver(it.Path(), common.Hash(node))
|
||||
resolverPath := it.Path()
|
||||
data, err := it.trie.nodeResolver(resolverPath, common.Hash(node))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if data == nil {
|
||||
// Empty/nil node — treat as Empty, backtrack
|
||||
it.current = Empty{}
|
||||
it.stack[len(it.stack)-1].Node = it.current
|
||||
return it.Next(descend)
|
||||
}
|
||||
it.current, err = DeserializeNodeWithHash(data, len(it.stack)-1, common.Hash(node))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
@ -130,16 +137,25 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
|
|||
|
||||
// update the stack and parent with the resolved node
|
||||
it.stack[len(it.stack)-1].Node = it.current
|
||||
parent := &it.stack[len(it.stack)-2]
|
||||
if parent.Index == 0 {
|
||||
parent.Node.(*InternalNode).left = it.current
|
||||
} else {
|
||||
parent.Node.(*InternalNode).right = it.current
|
||||
if len(it.stack) >= 2 {
|
||||
parent := &it.stack[len(it.stack)-2]
|
||||
if parent.Index == 0 {
|
||||
parent.Node.(*InternalNode).left = it.current
|
||||
} else {
|
||||
parent.Node.(*InternalNode).right = it.current
|
||||
}
|
||||
}
|
||||
return it.Next(descend)
|
||||
case Empty:
|
||||
// do nothing
|
||||
return false
|
||||
// Empty node - go back to parent and continue
|
||||
if len(it.stack) <= 1 {
|
||||
it.lastErr = errIteratorEnd
|
||||
return false
|
||||
}
|
||||
it.stack = it.stack[:len(it.stack)-1]
|
||||
it.current = it.stack[len(it.stack)-1].Node
|
||||
it.stack[len(it.stack)-1].Index++
|
||||
return it.Next(descend)
|
||||
default:
|
||||
panic("invalid node type")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue