trie, core/state: Add 'children' parameter to TrieIterator.next()

This commit is contained in:
Nick Johnson 2017-01-16 17:37:35 +00:00
parent 71a442ffbc
commit 4d7c0cae72
4 changed files with 16 additions and 10 deletions

View file

@ -80,7 +80,7 @@ func (it *NodeIterator) step() error {
} }
// If we had data nodes previously, we surely have at least state nodes // If we had data nodes previously, we surely have at least state nodes
if it.dataIt != nil { if it.dataIt != nil {
if cont := it.dataIt.Next(); !cont { if cont := it.dataIt.Next(true); !cont {
if it.dataIt.Error != nil { if it.dataIt.Error != nil {
return it.dataIt.Error return it.dataIt.Error
} }
@ -94,7 +94,7 @@ func (it *NodeIterator) step() error {
return nil return nil
} }
// Step to the next state trie node, terminating if we're out of nodes // Step to the next state trie node, terminating if we're out of nodes
if cont := it.stateIt.Next(); !cont { if cont := it.stateIt.Next(true); !cont {
if it.stateIt.Error != nil { if it.stateIt.Error != nil {
return it.stateIt.Error return it.stateIt.Error
} }
@ -120,7 +120,7 @@ func (it *NodeIterator) step() error {
return err return err
} }
it.dataIt = trie.NewNodeIterator(dataTrie) it.dataIt = trie.NewNodeIterator(dataTrie)
if !it.dataIt.Next() { if !it.dataIt.Next(true) {
it.dataIt = nil it.dataIt = nil
} }
if !bytes.Equal(account.CodeHash, emptyCodeHash) { if !bytes.Equal(account.CodeHash, emptyCodeHash) {

View file

@ -40,7 +40,7 @@ func NewIterator(trie *Trie) *Iterator {
// Next moves the iterator forward one key-value entry. // Next moves the iterator forward one key-value entry.
func (it *Iterator) Next() bool { func (it *Iterator) Next() bool {
for it.nodeIt.Next() { for it.nodeIt.Next(true) {
if it.nodeIt.Leaf { if it.nodeIt.Leaf {
it.Key = it.makeKey() it.Key = it.makeKey()
it.Value = it.nodeIt.LeafBlob it.Value = it.nodeIt.LeafBlob
@ -104,14 +104,15 @@ func NewNodeIterator(trie *Trie) *NodeIterator {
// Next moves the iterator to the next node, returning whether there are any // Next moves the iterator to the next node, returning whether there are any
// further nodes. In case of an internal error this method returns false and // further nodes. In case of an internal error this method returns false and
// sets the Error field to the encountered failure. // sets the Error field to the encountered failure. If `children` is false,
func (it *NodeIterator) Next() bool { // skips iterating over any subnodes of the current node.
func (it *NodeIterator) Next(children bool) bool {
// If the iterator failed previously, don't do anything // If the iterator failed previously, don't do anything
if it.Error != nil { if it.Error != nil {
return false return false
} }
// Otherwise step forward with the iterator and report any errors // Otherwise step forward with the iterator and report any errors
if err := it.step(); err != nil { if err := it.step(children); err != nil {
it.Error = err it.Error = err
return false return false
} }
@ -119,7 +120,7 @@ func (it *NodeIterator) Next() bool {
} }
// step moves the iterator to the next node of the trie. // step moves the iterator to the next node of the trie.
func (it *NodeIterator) step() error { func (it *NodeIterator) step(children bool) error {
if it.trie == nil { if it.trie == nil {
// Abort if we reached the end of the iteration // Abort if we reached the end of the iteration
return nil return nil
@ -135,6 +136,11 @@ func (it *NodeIterator) step() error {
return nil return nil
} }
if !children {
// If we're skipping children, pop the current node first
it.stack = it.stack[:len(it.stack)-1]
}
// Continue iteration to the next child // Continue iteration to the next child
for { for {
if len(it.stack) == 0 { if len(it.stack) == 0 {

View file

@ -101,7 +101,7 @@ func TestNodeIteratorCoverage(t *testing.T) {
// Gather all the node hashes found by the iterator // Gather all the node hashes found by the iterator
hashes := make(map[common.Hash]struct{}) hashes := make(map[common.Hash]struct{})
for it := NewNodeIterator(trie); it.Next(); { for it := NewNodeIterator(trie); it.Next(true); {
if it.Hash != (common.Hash{}) { if it.Hash != (common.Hash{}) {
hashes[it.Hash] = struct{}{} hashes[it.Hash] = struct{}{}
} }

View file

@ -81,7 +81,7 @@ func checkTrieConsistency(db Database, root common.Hash) error {
return nil // // Consider a non existent state consistent return nil // // Consider a non existent state consistent
} }
it := NewNodeIterator(trie) it := NewNodeIterator(trie)
for it.Next() { for it.Next(true) {
} }
return it.Error return it.Error
} }