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
748d1c17
Commit
748d1c17
authored
May 19, 2016
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core, core/state, trie: enterprise hand-tuned multi-level caching
parent
a7434fd0
Changes
9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
244 additions
and
133 deletions
+244
-133
blockchain.go
core/blockchain.go
+6
-1
statedb.go
core/state/statedb.go
+22
-0
iterator.go
trie/iterator.go
+13
-11
node.go
trie/node.go
+39
-21
proof.go
trie/proof.go
+4
-4
secure_trie.go
trie/secure_trie.go
+2
-2
sync.go
trie/sync.go
+7
-6
trie.go
trie/trie.go
+150
-87
trie_test.go
trie/trie_test.go
+1
-1
No files found.
core/blockchain.go
View file @
748d1c17
...
...
@@ -819,6 +819,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
tstart
=
time
.
Now
()
nonceChecked
=
make
([]
bool
,
len
(
chain
))
statedb
*
state
.
StateDB
)
// Start the parallel nonce verifier.
...
...
@@ -885,7 +886,11 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
// Create a new statedb using the parent block and report an
// error if it fails.
statedb
,
err
:=
state
.
New
(
self
.
GetBlock
(
block
.
ParentHash
())
.
Root
(),
self
.
chainDb
)
if
statedb
==
nil
{
statedb
,
err
=
state
.
New
(
self
.
GetBlock
(
block
.
ParentHash
())
.
Root
(),
self
.
chainDb
)
}
else
{
err
=
statedb
.
Reset
(
chain
[
i
-
1
]
.
Root
())
}
if
err
!=
nil
{
reportBlock
(
block
,
err
)
return
i
,
err
...
...
core/state/statedb.go
View file @
748d1c17
...
...
@@ -68,6 +68,28 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
},
nil
}
// Reset clears out all emphemeral state objects from the state db, but keeps
// the underlying state trie to avoid reloading data for the next operations.
func
(
self
*
StateDB
)
Reset
(
root
common
.
Hash
)
error
{
var
(
err
error
tr
=
self
.
trie
)
if
self
.
trie
.
Hash
()
!=
root
{
if
tr
,
err
=
trie
.
NewSecure
(
root
,
self
.
db
);
err
!=
nil
{
return
err
}
}
*
self
=
StateDB
{
db
:
self
.
db
,
trie
:
tr
,
stateObjects
:
make
(
map
[
string
]
*
StateObject
),
refund
:
new
(
big
.
Int
),
logs
:
make
(
map
[
common
.
Hash
]
vm
.
Logs
),
}
return
nil
}
func
(
self
*
StateDB
)
StartRecord
(
thash
,
bhash
common
.
Hash
,
ti
int
)
{
self
.
thash
=
thash
self
.
bhash
=
bhash
...
...
trie/iterator.go
View file @
748d1c17
...
...
@@ -62,7 +62,7 @@ func (self *Iterator) next(node interface{}, key []byte, isIterStart bool) []byt
switch
node
:=
node
.
(
type
)
{
case
fullNode
:
if
len
(
key
)
>
0
{
k
:=
self
.
next
(
node
[
key
[
0
]],
key
[
1
:
],
isIterStart
)
k
:=
self
.
next
(
node
.
Children
[
key
[
0
]],
key
[
1
:
],
isIterStart
)
if
k
!=
nil
{
return
append
([]
byte
{
key
[
0
]},
k
...
)
}
...
...
@@ -74,7 +74,7 @@ func (self *Iterator) next(node interface{}, key []byte, isIterStart bool) []byt
}
for
i
:=
r
;
i
<
16
;
i
++
{
k
:=
self
.
key
(
node
[
i
])
k
:=
self
.
key
(
node
.
Children
[
i
])
if
k
!=
nil
{
return
append
([]
byte
{
i
},
k
...
)
}
...
...
@@ -130,12 +130,12 @@ func (self *Iterator) key(node interface{}) []byte {
}
return
append
(
k
,
self
.
key
(
node
.
Val
)
...
)
case
fullNode
:
if
node
[
16
]
!=
nil
{
self
.
Value
=
node
[
16
]
.
(
valueNode
)
if
node
.
Children
[
16
]
!=
nil
{
self
.
Value
=
node
.
Children
[
16
]
.
(
valueNode
)
return
[]
byte
{
16
}
}
for
i
:=
0
;
i
<
16
;
i
++
{
k
:=
self
.
key
(
node
[
i
])
k
:=
self
.
key
(
node
.
Children
[
i
])
if
k
!=
nil
{
return
append
([]
byte
{
byte
(
i
)},
k
...
)
}
...
...
@@ -175,7 +175,7 @@ type NodeIterator struct {
// NewNodeIterator creates an post-order trie iterator.
func
NewNodeIterator
(
trie
*
Trie
)
*
NodeIterator
{
if
bytes
.
Compare
(
trie
.
Root
(),
emptyRoot
.
Bytes
())
==
0
{
if
trie
.
Hash
()
==
emptyState
{
return
new
(
NodeIterator
)
}
return
&
NodeIterator
{
trie
:
trie
}
...
...
@@ -205,9 +205,11 @@ func (it *NodeIterator) step() error {
}
// Initialize the iterator if we've just started, or pop off the old node otherwise
if
len
(
it
.
stack
)
==
0
{
it
.
stack
=
append
(
it
.
stack
,
&
nodeIteratorState
{
node
:
it
.
trie
.
root
,
child
:
-
1
})
// Always start with a collapsed root
root
:=
it
.
trie
.
Hash
()
it
.
stack
=
append
(
it
.
stack
,
&
nodeIteratorState
{
node
:
hashNode
(
root
[
:
]),
child
:
-
1
})
if
it
.
stack
[
0
]
.
node
==
nil
{
return
fmt
.
Errorf
(
"root node missing: %x"
,
it
.
trie
.
Root
())
return
fmt
.
Errorf
(
"root node missing: %x"
,
it
.
trie
.
Hash
())
}
}
else
{
it
.
stack
=
it
.
stack
[
:
len
(
it
.
stack
)
-
1
]
...
...
@@ -225,11 +227,11 @@ func (it *NodeIterator) step() error {
}
if
node
,
ok
:=
parent
.
node
.
(
fullNode
);
ok
{
// Full node, traverse all children, then the node itself
if
parent
.
child
>=
len
(
node
)
{
if
parent
.
child
>=
len
(
node
.
Children
)
{
break
}
for
parent
.
child
++
;
parent
.
child
<
len
(
node
);
parent
.
child
++
{
if
current
:=
node
[
parent
.
child
];
current
!=
nil
{
for
parent
.
child
++
;
parent
.
child
<
len
(
node
.
Children
);
parent
.
child
++
{
if
current
:=
node
.
Children
[
parent
.
child
];
current
!=
nil
{
it
.
stack
=
append
(
it
.
stack
,
&
nodeIteratorState
{
node
:
current
,
parent
:
ancestor
,
child
:
-
1
})
break
}
...
...
trie/node.go
View file @
748d1c17
...
...
@@ -29,18 +29,36 @@ var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b
type
node
interface
{
fstring
(
string
)
string
cache
()
(
hashNode
,
bool
)
}
type
(
fullNode
[
17
]
node
fullNode
struct
{
Children
[
17
]
node
// Actual trie node data to encode/decode (needs custom encoder)
hash
hashNode
// Cached hash of the node to prevent rehashing (may be nil)
dirty
bool
// Cached flag whether the node's new or already stored
}
shortNode
struct
{
Key
[]
byte
Val
node
hash
hashNode
// Cached hash of the node to prevent rehashing (may be nil)
dirty
bool
// Cached flag whether the node's new or already stored
}
hashNode
[]
byte
valueNode
[]
byte
)
// EncodeRLP encodes a full node into the consensus RLP format.
func
(
n
fullNode
)
EncodeRLP
(
w
io
.
Writer
)
error
{
return
rlp
.
Encode
(
w
,
n
.
Children
)
}
// Cache accessors to retrieve precalculated values (avoid lengthy type switches).
func
(
n
fullNode
)
cache
()
(
hashNode
,
bool
)
{
return
n
.
hash
,
n
.
dirty
}
func
(
n
shortNode
)
cache
()
(
hashNode
,
bool
)
{
return
n
.
hash
,
n
.
dirty
}
func
(
n
hashNode
)
cache
()
(
hashNode
,
bool
)
{
return
nil
,
true
}
func
(
n
valueNode
)
cache
()
(
hashNode
,
bool
)
{
return
nil
,
true
}
// Pretty printing.
func
(
n
fullNode
)
String
()
string
{
return
n
.
fstring
(
""
)
}
func
(
n
shortNode
)
String
()
string
{
return
n
.
fstring
(
""
)
}
...
...
@@ -49,7 +67,7 @@ func (n valueNode) String() string { return n.fstring("") }
func
(
n
fullNode
)
fstring
(
ind
string
)
string
{
resp
:=
fmt
.
Sprintf
(
"[
\n
%s "
,
ind
)
for
i
,
node
:=
range
n
{
for
i
,
node
:=
range
n
.
Children
{
if
node
==
nil
{
resp
+=
fmt
.
Sprintf
(
"%s: <nil> "
,
indices
[
i
])
}
else
{
...
...
@@ -68,16 +86,16 @@ func (n valueNode) fstring(ind string) string {
return
fmt
.
Sprintf
(
"%x "
,
[]
byte
(
n
))
}
func
mustDecodeNode
(
dbkey
,
buf
[]
byte
)
node
{
n
,
err
:=
decodeNode
(
buf
)
func
mustDecodeNode
(
hash
,
buf
[]
byte
)
node
{
n
,
err
:=
decodeNode
(
hash
,
buf
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"node %x: %v"
,
dbkey
,
err
))
panic
(
fmt
.
Sprintf
(
"node %x: %v"
,
hash
,
err
))
}
return
n
}
// decodeNode parses the RLP encoding of a trie node.
func
decodeNode
(
buf
[]
byte
)
(
node
,
error
)
{
func
decodeNode
(
hash
,
buf
[]
byte
)
(
node
,
error
)
{
if
len
(
buf
)
==
0
{
return
nil
,
io
.
ErrUnexpectedEOF
}
...
...
@@ -87,18 +105,18 @@ func decodeNode(buf []byte) (node, error) {
}
switch
c
,
_
:=
rlp
.
CountValues
(
elems
);
c
{
case
2
:
n
,
err
:=
decodeShort
(
elems
)
n
,
err
:=
decodeShort
(
hash
,
buf
,
elems
)
return
n
,
wrapError
(
err
,
"short"
)
case
17
:
n
,
err
:=
decodeFull
(
elems
)
n
,
err
:=
decodeFull
(
hash
,
buf
,
elems
)
return
n
,
wrapError
(
err
,
"full"
)
default
:
return
nil
,
fmt
.
Errorf
(
"invalid number of list elements: %v"
,
c
)
}
}
func
decodeShort
(
buf
[]
byte
)
(
node
,
error
)
{
kbuf
,
rest
,
err
:=
rlp
.
SplitString
(
buf
)
func
decodeShort
(
hash
,
buf
,
elems
[]
byte
)
(
node
,
error
)
{
kbuf
,
rest
,
err
:=
rlp
.
SplitString
(
elems
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -109,30 +127,30 @@ func decodeShort(buf []byte) (node, error) {
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid value node: %v"
,
err
)
}
return
shortNode
{
key
,
valueNode
(
val
)},
nil
return
shortNode
{
key
,
valueNode
(
val
)
,
hash
,
false
},
nil
}
r
,
_
,
err
:=
decodeRef
(
rest
)
if
err
!=
nil
{
return
nil
,
wrapError
(
err
,
"val"
)
}
return
shortNode
{
key
,
r
},
nil
return
shortNode
{
key
,
r
,
hash
,
false
},
nil
}
func
decodeFull
(
buf
[]
byte
)
(
fullNode
,
error
)
{
var
n
fullNode
func
decodeFull
(
hash
,
buf
,
elems
[]
byte
)
(
fullNode
,
error
)
{
n
:=
fullNode
{
hash
:
hash
}
for
i
:=
0
;
i
<
16
;
i
++
{
cld
,
rest
,
err
:=
decodeRef
(
buf
)
cld
,
rest
,
err
:=
decodeRef
(
elems
)
if
err
!=
nil
{
return
n
,
wrapError
(
err
,
fmt
.
Sprintf
(
"[%d]"
,
i
))
}
n
[
i
],
buf
=
cld
,
rest
n
.
Children
[
i
],
elems
=
cld
,
rest
}
val
,
_
,
err
:=
rlp
.
SplitString
(
buf
)
val
,
_
,
err
:=
rlp
.
SplitString
(
elems
)
if
err
!=
nil
{
return
n
,
err
}
if
len
(
val
)
>
0
{
n
[
16
]
=
valueNode
(
val
)
n
.
Children
[
16
]
=
valueNode
(
val
)
}
return
n
,
nil
}
...
...
@@ -152,7 +170,7 @@ func decodeRef(buf []byte) (node, []byte, error) {
err
:=
fmt
.
Errorf
(
"oversized embedded node (size is %d bytes, want size < %d)"
,
size
,
hashLen
)
return
nil
,
buf
,
err
}
n
,
err
:=
decodeNode
(
buf
)
n
,
err
:=
decodeNode
(
nil
,
buf
)
return
n
,
rest
,
err
case
kind
==
rlp
.
String
&&
len
(
val
)
==
0
:
// empty node
...
...
trie/proof.go
View file @
748d1c17
...
...
@@ -54,7 +54,7 @@ func (t *Trie) Prove(key []byte) []rlp.RawValue {
}
nodes
=
append
(
nodes
,
n
)
case
fullNode
:
tn
=
n
[
key
[
0
]]
tn
=
n
.
Children
[
key
[
0
]]
key
=
key
[
1
:
]
nodes
=
append
(
nodes
,
n
)
case
hashNode
:
...
...
@@ -77,7 +77,7 @@ func (t *Trie) Prove(key []byte) []rlp.RawValue {
for
i
,
n
:=
range
nodes
{
// Don't bother checking for errors here since hasher panics
// if encoding doesn't work and we're not writing to any database.
n
,
_
=
t
.
hasher
.
replace
Children
(
n
,
nil
)
n
,
_
,
_
=
t
.
hasher
.
hash
Children
(
n
,
nil
)
hn
,
_
:=
t
.
hasher
.
store
(
n
,
nil
,
false
)
if
_
,
ok
:=
hn
.
(
hashNode
);
ok
||
i
==
0
{
// If the node's database encoding is a hash (or is the
...
...
@@ -103,7 +103,7 @@ func VerifyProof(rootHash common.Hash, key []byte, proof []rlp.RawValue) (value
if
!
bytes
.
Equal
(
sha
.
Sum
(
nil
),
wantHash
)
{
return
nil
,
fmt
.
Errorf
(
"bad proof node %d: hash mismatch"
,
i
)
}
n
,
err
:=
decodeNode
(
buf
)
n
,
err
:=
decodeNode
(
wantHash
,
buf
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"bad proof node %d: %v"
,
i
,
err
)
}
...
...
@@ -139,7 +139,7 @@ func get(tn node, key []byte) ([]byte, node) {
tn
=
n
.
Val
key
=
key
[
len
(
n
.
Key
)
:
]
case
fullNode
:
tn
=
n
[
key
[
0
]]
tn
=
n
.
Children
[
key
[
0
]]
key
=
key
[
1
:
]
case
hashNode
:
return
key
,
n
...
...
trie/secure_trie.go
View file @
748d1c17
...
...
@@ -162,11 +162,11 @@ func (t *SecureTrie) CommitTo(db DatabaseWriter) (root common.Hash, err error) {
}
t
.
secKeyCache
=
make
(
map
[
string
][]
byte
)
}
n
,
err
:=
t
.
hashRoot
(
db
)
n
,
clean
,
err
:=
t
.
hashRoot
(
db
)
if
err
!=
nil
{
return
(
common
.
Hash
{}),
err
}
t
.
root
=
n
t
.
root
=
clea
n
return
common
.
BytesToHash
(
n
.
(
hashNode
)),
nil
}
...
...
trie/sync.go
View file @
748d1c17
...
...
@@ -75,8 +75,9 @@ func (s *TrieSync) AddSubTrie(root common.Hash, depth int, parent common.Hash, c
if
root
==
emptyRoot
{
return
}
blob
,
_
:=
s
.
database
.
Get
(
root
.
Bytes
())
if
local
,
err
:=
decodeNode
(
blob
);
local
!=
nil
&&
err
==
nil
{
key
:=
root
.
Bytes
()
blob
,
_
:=
s
.
database
.
Get
(
key
)
if
local
,
err
:=
decodeNode
(
key
,
blob
);
local
!=
nil
&&
err
==
nil
{
return
}
// Assemble the new sub-trie sync request
...
...
@@ -152,7 +153,7 @@ func (s *TrieSync) Process(results []SyncResult) (int, error) {
continue
}
// Decode the node data content and update the request
node
,
err
:=
decodeNode
(
item
.
Data
)
node
,
err
:=
decodeNode
(
item
.
Hash
[
:
],
item
.
Data
)
if
err
!=
nil
{
return
i
,
err
}
...
...
@@ -213,9 +214,9 @@ func (s *TrieSync) children(req *request) ([]*request, error) {
}}
case
fullNode
:
for
i
:=
0
;
i
<
17
;
i
++
{
if
node
[
i
]
!=
nil
{
if
node
.
Children
[
i
]
!=
nil
{
children
=
append
(
children
,
child
{
node
:
&
node
[
i
],
node
:
&
node
.
Children
[
i
],
depth
:
req
.
depth
+
1
,
})
}
...
...
@@ -238,7 +239,7 @@ func (s *TrieSync) children(req *request) ([]*request, error) {
if
node
,
ok
:=
(
*
child
.
node
)
.
(
hashNode
);
ok
{
// Try to resolve the node from the local database
blob
,
_
:=
s
.
database
.
Get
(
node
)
if
local
,
err
:=
decodeNode
(
blob
);
local
!=
nil
&&
err
==
nil
{
if
local
,
err
:=
decodeNode
(
node
[
:
],
blob
);
local
!=
nil
&&
err
==
nil
{
*
child
.
node
=
local
continue
}
...
...
trie/trie.go
View file @
748d1c17
This diff is collapsed.
Click to expand it.
trie/trie_test.go
View file @
748d1c17
...
...
@@ -295,7 +295,7 @@ func TestReplication(t *testing.T) {
for
_
,
val
:=
range
vals2
{
updateString
(
trie2
,
val
.
k
,
val
.
v
)
}
if
trie2
.
Hash
()
!=
exp
{
if
hash
:=
trie2
.
Hash
();
hash
!=
exp
{
t
.
Errorf
(
"root failure. expected %x got %x"
,
exp
,
hash
)
}
}
...
...
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