expose parent path from iterator

This commit is contained in:
i-norden 2023-04-14 19:53:53 -05:00
parent 1eaa707bf8
commit 494279f0b4

View File

@ -90,6 +90,10 @@ type NodeIterator interface {
// grandparent if the immediate parent is an internal node with no hash. // grandparent if the immediate parent is an internal node with no hash.
Parent() common.Hash Parent() common.Hash
// ParentPath returns the path of the parent of the current node. The path may be the one
// grandparent if the immediate parent is an internal node with no path.
ParentPath() []byte
// Path returns the hex-encoded path to the current node. // Path returns the hex-encoded path to the current node.
// Callers must not retain references to the return value after calling Next. // Callers must not retain references to the return value after calling Next.
// For leaf nodes, the last element of the path is the 'terminator symbol' 0x10. // For leaf nodes, the last element of the path is the 'terminator symbol' 0x10.
@ -134,11 +138,12 @@ type NodeIterator interface {
// nodeIteratorState represents the iteration state at one particular node of the // nodeIteratorState represents the iteration state at one particular node of the
// trie, which can be resumed at a later invocation. // trie, which can be resumed at a later invocation.
type nodeIteratorState struct { type nodeIteratorState struct {
hash common.Hash // Hash of the node being iterated (nil if not standalone) hash common.Hash // Hash of the node being iterated (nil if not standalone)
node node // Trie node being iterated node node // Trie node being iterated
parent common.Hash // Hash of the first full ancestor node (nil if current is the root) parent common.Hash // Hash of the first full ancestor node (nil if current is the root)
index int // Child to be processed next parentPath []byte // Path of the first full ancestor node
pathlen int // Length of the path to this node index int // Child to be processed next
pathlen int // Length of the path to this node
} }
type nodeIterator struct { type nodeIterator struct {
@ -193,6 +198,13 @@ func (it *nodeIterator) Parent() common.Hash {
return it.stack[len(it.stack)-1].parent return it.stack[len(it.stack)-1].parent
} }
func (it *nodeIterator) ParentPath() []byte {
if len(it.stack) == 0 {
return []byte{}
}
return it.stack[len(it.stack)-1].parentPath
}
func (it *nodeIterator) Leaf() bool { func (it *nodeIterator) Leaf() bool {
return hasTerm(it.path) return hasTerm(it.path)
} }
@ -425,16 +437,19 @@ func findChild(n *fullNode, index int, path []byte, ancestor common.Hash) (node,
state *nodeIteratorState state *nodeIteratorState
childPath []byte childPath []byte
) )
parentPath := make([]byte, len(path))
copy(parentPath, path)
for ; index < len(n.Children); index++ { for ; index < len(n.Children); index++ {
if n.Children[index] != nil { if n.Children[index] != nil {
child = n.Children[index] child = n.Children[index]
hash, _ := child.cache() hash, _ := child.cache()
state = &nodeIteratorState{ state = &nodeIteratorState{
hash: common.BytesToHash(hash), hash: common.BytesToHash(hash),
node: child, node: child,
parent: ancestor, parent: ancestor,
index: -1, parentPath: parentPath,
pathlen: len(path), index: -1,
pathlen: len(path),
} }
childPath = append(childPath, path...) childPath = append(childPath, path...)
childPath = append(childPath, byte(index)) childPath = append(childPath, byte(index))
@ -454,14 +469,17 @@ func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Has
} }
case *shortNode: case *shortNode:
// Short node, return the pointer singleton child // Short node, return the pointer singleton child
parentPath := make([]byte, len(it.path))
copy(parentPath, it.path)
if parent.index < 0 { if parent.index < 0 {
hash, _ := node.Val.cache() hash, _ := node.Val.cache()
state := &nodeIteratorState{ state := &nodeIteratorState{
hash: common.BytesToHash(hash), hash: common.BytesToHash(hash),
node: node.Val, node: node.Val,
parent: ancestor, parent: ancestor,
index: -1, parentPath: parentPath,
pathlen: len(it.path), index: -1,
pathlen: len(it.path),
} }
path := append(it.path, node.Key...) path := append(it.path, node.Key...)
return state, path, true return state, path, true
@ -500,14 +518,17 @@ func (it *nodeIterator) nextChildAt(parent *nodeIteratorState, ancestor common.H
} }
case *shortNode: case *shortNode:
// Short node, return the pointer singleton child // Short node, return the pointer singleton child
parentPath := make([]byte, len(it.path))
copy(parentPath, it.path)
if parent.index < 0 { if parent.index < 0 {
hash, _ := n.Val.cache() hash, _ := n.Val.cache()
state := &nodeIteratorState{ state := &nodeIteratorState{
hash: common.BytesToHash(hash), hash: common.BytesToHash(hash),
node: n.Val, node: n.Val,
parent: ancestor, parent: ancestor,
index: -1, parentPath: parentPath,
pathlen: len(it.path), index: -1,
pathlen: len(it.path),
} }
path := append(it.path, n.Key...) path := append(it.path, n.Key...)
return state, path, true return state, path, true
@ -575,6 +596,10 @@ func (it *differenceIterator) Parent() common.Hash {
return it.b.Parent() return it.b.Parent()
} }
func (it *differenceIterator) ParentPath() []byte {
return it.b.ParentPath()
}
func (it *differenceIterator) Leaf() bool { func (it *differenceIterator) Leaf() bool {
return it.b.Leaf() return it.b.Leaf()
} }
@ -691,6 +716,10 @@ func (it *unionIterator) Parent() common.Hash {
return (*it.items)[0].Parent() return (*it.items)[0].Parent()
} }
func (it *unionIterator) ParentPath() []byte {
return (*it.items)[0].ParentPath()
}
func (it *unionIterator) Leaf() bool { func (it *unionIterator) Leaf() bool {
return (*it.items)[0].Leaf() return (*it.items)[0].Leaf()
} }