diff options
author | Nick Johnson <arachnid@notdot.net> | 2017-02-23 06:49:34 +0800 |
---|---|---|
committer | Felix Lange <fjl@users.noreply.github.com> | 2017-02-23 06:49:34 +0800 |
commit | 555273495b413069e9422b04aa46251146c752b2 (patch) | |
tree | 969065770a87c26392449423a51d3f7e1ffe3c12 /core | |
parent | 024d41d0c2660d8f1dfbeb14921c7109e30493a2 (diff) | |
download | dexon-555273495b413069e9422b04aa46251146c752b2.tar.gz dexon-555273495b413069e9422b04aa46251146c752b2.tar.zst dexon-555273495b413069e9422b04aa46251146c752b2.zip |
trie: add difference iterator (#3637)
This PR implements a differenceIterator, which allows iterating over trie nodes
that exist in one trie but not in another. This is a prerequisite for most GC
strategies, in order to find obsolete nodes.
Diffstat (limited to 'core')
-rw-r--r-- | core/state/iterator.go | 33 |
1 files changed, 16 insertions, 17 deletions
diff --git a/core/state/iterator.go b/core/state/iterator.go index a58a15ad3..170aec983 100644 --- a/core/state/iterator.go +++ b/core/state/iterator.go @@ -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) Error error // Failure set in case of an internal error in the iterator @@ -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 } @@ -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 @@ -112,7 +111,7 @@ 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) @@ -120,7 +119,7 @@ func (it *NodeIterator) step() error { 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) { @@ -130,7 +129,7 @@ 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 } @@ -138,7 +137,7 @@ func (it *NodeIterator) step() error { // 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 { @@ -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 } |