Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trie: add difference iterator #3637

Merged
merged 6 commits into from
Feb 22, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 16 additions & 17 deletions core/state/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ import (
type NodeIterator struct {
state *StateDB // State being iterated

stateIt *trie.NodeIterator // Primary iterator for the global state trie
dataIt *trie.NodeIterator // Secondary iterator for the data trie of a contract
stateIt trie.NodeIterator // Primary iterator for the global state trie
dataIt trie.NodeIterator // Secondary iterator for the data trie of a contract

accountHash common.Hash // Hash of the node containing the account
codeHash common.Hash // Hash of the contract source code
code []byte // Source code associated with a contract

Hash common.Hash // Hash of the current entry being iterated (nil if not standalone)
Entry interface{} // Current state entry being iterated (internal representation)
Parent common.Hash // Hash of the first full ancestor node (nil if current is the root)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you delete this because it wasn't used anywhere? Any particular reason? Doesn't this make the iterator a lot less useful as there's no way to actually access the data being iterated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I deleted it because it isn't being used anywhere. Because the entry types are all private anyway, this field wasn't usable outside the package.


Error error // Failure set in case of an internal error in the iterator
Expand Down Expand Up @@ -80,9 +79,9 @@ func (it *NodeIterator) step() error {
}
// If we had data nodes previously, we surely have at least state nodes
if it.dataIt != nil {
if cont := it.dataIt.Next(); !cont {
if it.dataIt.Error != nil {
return it.dataIt.Error
if cont := it.dataIt.Next(true); !cont {
if it.dataIt.Error() != nil {
return it.dataIt.Error()
}
it.dataIt = nil
}
Expand All @@ -94,15 +93,15 @@ func (it *NodeIterator) step() error {
return nil
}
// Step to the next state trie node, terminating if we're out of nodes
if cont := it.stateIt.Next(); !cont {
if it.stateIt.Error != nil {
return it.stateIt.Error
if cont := it.stateIt.Next(true); !cont {
if it.stateIt.Error() != nil {
return it.stateIt.Error()
}
it.state, it.stateIt = nil, nil
return nil
}
// If the state trie node is an internal entry, leave as is
if !it.stateIt.Leaf {
if !it.stateIt.Leaf() {
return nil
}
// Otherwise we've reached an account node, initiate data iteration
Expand All @@ -112,15 +111,15 @@ func (it *NodeIterator) step() error {
Root common.Hash
CodeHash []byte
}
if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob), &account); err != nil {
if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil {
return err
}
dataTrie, err := trie.New(account.Root, it.state.db)
if err != nil {
return err
}
it.dataIt = trie.NewNodeIterator(dataTrie)
if !it.dataIt.Next() {
if !it.dataIt.Next(true) {
it.dataIt = nil
}
if !bytes.Equal(account.CodeHash, emptyCodeHash) {
Expand All @@ -130,15 +129,15 @@ func (it *NodeIterator) step() error {
return fmt.Errorf("code %x: %v", account.CodeHash, err)
}
}
it.accountHash = it.stateIt.Parent
it.accountHash = it.stateIt.Parent()
return nil
}

// retrieve pulls and caches the current state entry the iterator is traversing.
// The method returns whether there are any more data left for inspection.
func (it *NodeIterator) retrieve() bool {
// Clear out any previously set values
it.Hash, it.Entry = common.Hash{}, nil
it.Hash = common.Hash{}

// If the iteration's done, return no available data
if it.state == nil {
Expand All @@ -147,14 +146,14 @@ func (it *NodeIterator) retrieve() bool {
// Otherwise retrieve the current entry
switch {
case it.dataIt != nil:
it.Hash, it.Entry, it.Parent = it.dataIt.Hash, it.dataIt.Node, it.dataIt.Parent
it.Hash, it.Parent = it.dataIt.Hash(), it.dataIt.Parent()
if it.Parent == (common.Hash{}) {
it.Parent = it.accountHash
}
case it.code != nil:
it.Hash, it.Entry, it.Parent = it.codeHash, it.code, it.accountHash
it.Hash, it.Parent = it.codeHash, it.accountHash
case it.stateIt != nil:
it.Hash, it.Entry, it.Parent = it.stateIt.Hash, it.stateIt.Node, it.stateIt.Parent
it.Hash, it.Parent = it.stateIt.Hash(), it.stateIt.Parent()
}
return true
}