aboutsummaryrefslogtreecommitdiffstats
path: root/core/state
diff options
context:
space:
mode:
authorNick Johnson <arachnid@notdot.net>2017-02-23 06:49:34 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-02-23 06:49:34 +0800
commit555273495b413069e9422b04aa46251146c752b2 (patch)
tree969065770a87c26392449423a51d3f7e1ffe3c12 /core/state
parent024d41d0c2660d8f1dfbeb14921c7109e30493a2 (diff)
downloaddexon-555273495b413069e9422b04aa46251146c752b2.tar
dexon-555273495b413069e9422b04aa46251146c752b2.tar.gz
dexon-555273495b413069e9422b04aa46251146c752b2.tar.bz2
dexon-555273495b413069e9422b04aa46251146c752b2.tar.lz
dexon-555273495b413069e9422b04aa46251146c752b2.tar.xz
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/state')
-rw-r--r--core/state/iterator.go33
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
}