Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
5a057a8d
Commit
5a057a8d
authored
Jan 06, 2016
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/state, trie: surface iterator entry hashes
parent
7e29b0b5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
114 additions
and
20 deletions
+114
-20
iterator.go
core/state/iterator.go
+9
-5
iterator_test.go
core/state/iterator_test.go
+57
-0
sync_test.go
core/state/sync_test.go
+1
-2
iterator.go
trie/iterator.go
+15
-10
iterator_test.go
trie/iterator_test.go
+31
-1
sync_test.go
trie/sync_test.go
+1
-2
No files found.
core/state/iterator.go
View file @
5a057a8d
...
...
@@ -33,8 +33,11 @@ type NodeIterator struct {
stateIt
*
trie
.
NodeIterator
// Primary iterator for the global state trie
dataIt
*
trie
.
NodeIterator
// Secondary iterator for the data trie of a contract
code
[]
byte
// Source code associated with a contract
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)
}
...
...
@@ -103,6 +106,7 @@ func (it *NodeIterator) step() {
it
.
dataIt
=
nil
}
if
bytes
.
Compare
(
account
.
CodeHash
,
emptyCodeHash
)
!=
0
{
it
.
codeHash
=
common
.
BytesToHash
(
account
.
CodeHash
)
it
.
code
,
err
=
it
.
state
.
db
.
Get
(
account
.
CodeHash
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"code %x: %v"
,
account
.
CodeHash
,
err
))
...
...
@@ -114,7 +118,7 @@ func (it *NodeIterator) step() {
// The method returns whether there are any more data left for inspection.
func
(
it
*
NodeIterator
)
retrieve
()
bool
{
// Clear out any previously set values
it
.
Entry
=
nil
it
.
Hash
,
it
.
Entry
=
common
.
Hash
{},
nil
// If the iteration's done, return no available data
if
it
.
state
==
nil
{
...
...
@@ -123,11 +127,11 @@ func (it *NodeIterator) retrieve() bool {
// Otherwise retrieve the current entry
switch
{
case
it
.
dataIt
!=
nil
:
it
.
Entry
=
it
.
dataIt
.
Node
it
.
Hash
,
it
.
Entry
=
it
.
dataIt
.
Hash
,
it
.
dataIt
.
Node
case
it
.
code
!=
nil
:
it
.
Entry
=
it
.
code
it
.
Hash
,
it
.
Entry
=
it
.
codeHash
,
it
.
code
case
it
.
stateIt
!=
nil
:
it
.
Entry
=
it
.
stateIt
.
Node
it
.
Hash
,
it
.
Entry
=
it
.
stateIt
.
Hash
,
it
.
stateIt
.
Node
}
return
true
}
core/state/iterator_test.go
0 → 100644
View file @
5a057a8d
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
state
import
(
"bytes"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
)
// Tests that the node iterator indeed walks over the entire database contents.
func
TestNodeIteratorCoverage
(
t
*
testing
.
T
)
{
// Create some arbitrary test state to iterate
db
,
root
,
_
:=
makeTestState
()
state
,
err
:=
New
(
root
,
db
)
if
err
!=
nil
{
t
.
Fatalf
(
"failed to create state trie at %x: %v"
,
root
,
err
)
}
// Gather all the node hashes found by the iterator
hashes
:=
make
(
map
[
common
.
Hash
]
struct
{})
for
it
:=
NewNodeIterator
(
state
);
it
.
Next
();
{
if
it
.
Hash
!=
(
common
.
Hash
{})
{
hashes
[
it
.
Hash
]
=
struct
{}{}
}
}
// Cross check the hashes and the database itself
for
hash
,
_
:=
range
hashes
{
if
_
,
err
:=
db
.
Get
(
hash
.
Bytes
());
err
!=
nil
{
t
.
Errorf
(
"failed to retrieve reported node %x: %v"
,
hash
,
err
)
}
}
for
_
,
key
:=
range
db
.
(
*
ethdb
.
MemDatabase
)
.
Keys
()
{
if
bytes
.
HasPrefix
(
key
,
[]
byte
(
"secure-key-"
))
{
continue
}
if
_
,
ok
:=
hashes
[
common
.
BytesToHash
(
key
)];
!
ok
{
t
.
Errorf
(
"state entry not reported %x"
,
key
)
}
}
}
core/state/sync_test.go
View file @
5a057a8d
...
...
@@ -116,8 +116,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) (failure error)
if
err
!=
nil
{
return
}
it
:=
NewNodeIterator
(
state
)
for
it
.
Next
()
{
for
it
:=
NewNodeIterator
(
state
);
it
.
Next
();
{
}
return
nil
}
...
...
trie/iterator.go
View file @
5a057a8d
...
...
@@ -20,6 +20,7 @@ import (
"bytes"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
...
...
@@ -152,8 +153,9 @@ func (self *Iterator) key(node interface{}) []byte {
// nodeIteratorState represents the iteration state at one particular node of the
// trie, which can be resumed at a later invocation.
type
nodeIteratorState
struct
{
node
node
// Trie node being iterated
child
int
// Child to be processed next
hash
common
.
Hash
// Hash of the node being iterated (nil if not standalone)
node
node
// Trie node being iterated
child
int
// Child to be processed next
}
// NodeIterator is an iterator to traverse the trie post-order.
...
...
@@ -161,9 +163,10 @@ type NodeIterator struct {
trie
*
Trie
// Trie being iterated
stack
[]
*
nodeIteratorState
// Hierarchy of trie nodes persisting the iteration state
Node
node
// Current node being iterated (internal representation)
Leaf
bool
// Flag whether the current node is a value (data) node
LeafBlob
[]
byte
// Data blob contained within a leaf (otherwise nil)
Hash
common
.
Hash
// Hash of the current node being iterated (nil if not standalone)
Node
node
// Current node being iterated (internal representation)
Leaf
bool
// Flag whether the current node is a value (data) node
LeafBlob
[]
byte
// Data blob contained within a leaf (otherwise nil)
}
// NewNodeIterator creates an post-order trie iterator.
...
...
@@ -221,18 +224,18 @@ func (it *NodeIterator) step() {
}
parent
.
child
++
it
.
stack
=
append
(
it
.
stack
,
&
nodeIteratorState
{
node
:
node
.
Val
,
child
:
-
1
})
}
else
if
node
,
ok
:=
parent
.
node
.
(
hashNode
);
ok
{
}
else
if
hash
,
ok
:=
parent
.
node
.
(
hashNode
);
ok
{
// Hash node, resolve the hash child from the database, then the node itself
if
parent
.
child
>=
0
{
break
}
parent
.
child
++
node
,
err
:=
it
.
trie
.
resolveHash
(
node
,
nil
,
nil
)
node
,
err
:=
it
.
trie
.
resolveHash
(
hash
,
nil
,
nil
)
if
err
!=
nil
{
panic
(
err
)
}
it
.
stack
=
append
(
it
.
stack
,
&
nodeIteratorState
{
node
:
node
,
child
:
-
1
})
it
.
stack
=
append
(
it
.
stack
,
&
nodeIteratorState
{
hash
:
common
.
BytesToHash
(
hash
),
node
:
node
,
child
:
-
1
})
}
else
{
break
}
...
...
@@ -246,14 +249,16 @@ func (it *NodeIterator) step() {
// The method returns whether there are any more data left for inspection.
func
(
it
*
NodeIterator
)
retrieve
()
bool
{
// Clear out any previously set values
it
.
Node
,
it
.
Leaf
,
it
.
LeafBlob
=
nil
,
false
,
nil
it
.
Hash
,
it
.
Node
,
it
.
Leaf
,
it
.
LeafBlob
=
common
.
Hash
{},
nil
,
false
,
nil
// If the iteration's done, return no available data
if
it
.
trie
==
nil
{
return
false
}
// Otherwise retrieve the current node and resolve leaf accessors
it
.
Node
=
it
.
stack
[
len
(
it
.
stack
)
-
1
]
.
node
state
:=
it
.
stack
[
len
(
it
.
stack
)
-
1
]
it
.
Hash
,
it
.
Node
=
state
.
hash
,
state
.
node
if
value
,
ok
:=
it
.
Node
.
(
valueNode
);
ok
{
it
.
Leaf
,
it
.
LeafBlob
=
true
,
[]
byte
(
value
)
}
...
...
trie/iterator_test.go
View file @
5a057a8d
...
...
@@ -16,7 +16,12 @@
package
trie
import
"testing"
import
(
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
)
func
TestIterator
(
t
*
testing
.
T
)
{
trie
:=
newEmpty
()
...
...
@@ -47,3 +52,28 @@ func TestIterator(t *testing.T) {
}
}
}
// Tests that the node iterator indeed walks over the entire database contents.
func
TestNodeIteratorCoverage
(
t
*
testing
.
T
)
{
// Create some arbitrary test trie to iterate
db
,
trie
,
_
:=
makeTestTrie
()
// Gather all the node hashes found by the iterator
hashes
:=
make
(
map
[
common
.
Hash
]
struct
{})
for
it
:=
NewNodeIterator
(
trie
);
it
.
Next
();
{
if
it
.
Hash
!=
(
common
.
Hash
{})
{
hashes
[
it
.
Hash
]
=
struct
{}{}
}
}
// Cross check the hashes and the database itself
for
hash
,
_
:=
range
hashes
{
if
_
,
err
:=
db
.
Get
(
hash
.
Bytes
());
err
!=
nil
{
t
.
Errorf
(
"failed to retrieve reported node %x: %v"
,
hash
,
err
)
}
}
for
_
,
key
:=
range
db
.
(
*
ethdb
.
MemDatabase
)
.
Keys
()
{
if
_
,
ok
:=
hashes
[
common
.
BytesToHash
(
key
)];
!
ok
{
t
.
Errorf
(
"state entry not reported %x"
,
key
)
}
}
}
trie/sync_test.go
View file @
5a057a8d
...
...
@@ -96,8 +96,7 @@ func checkTrieConsistency(db Database, root common.Hash) (failure error) {
if
err
!=
nil
{
return
}
it
:=
NewNodeIterator
(
trie
)
for
it
.
Next
()
{
for
it
:=
NewNodeIterator
(
trie
);
it
.
Next
();
{
}
return
nil
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment