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
d754091a
Unverified
Commit
d754091a
authored
Nov 22, 2019
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/state/snapshot: unlink snapshots from blocks, quad->linear cleanup
parent
cdf3f016
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
203 additions
and
206 deletions
+203
-206
blockchain.go
core/blockchain.go
+5
-5
accessors_snapshot.go
core/rawdb/accessors_snapshot.go
+19
-21
schema.go
core/rawdb/schema.go
+2
-2
difflayer.go
core/state/snapshot/difflayer.go
+16
-11
difflayer_journal.go
core/state/snapshot/difflayer_journal.go
+4
-21
difflayer_test.go
core/state/snapshot/difflayer_test.go
+21
-35
disklayer.go
core/state/snapshot/disklayer.go
+15
-7
generate.go
core/state/snapshot/generate.go
+5
-6
generate_test.go
core/state/snapshot/generate_test.go
+5
-5
snapshot.go
core/state/snapshot/snapshot.go
+96
-79
snapshot_test.go
core/state/snapshot/snapshot_test.go
+5
-6
statedb.go
core/state/statedb.go
+10
-8
No files found.
core/blockchain.go
View file @
d754091a
...
...
@@ -140,10 +140,10 @@ type BlockChain struct {
chainConfig
*
params
.
ChainConfig
// Chain & network configuration
cacheConfig
*
CacheConfig
// Cache configuration for pruning
db
ethdb
.
Database
// Low level persistent database to store final content in
snaps
*
snapshot
.
Snapshot
Tree
// Snapshot tree for fast trie leaf access
triegc
*
prque
.
Prque
// Priority queue mapping block numbers to tries to gc
gcproc
time
.
Duration
// Accumulates canonical block processing for trie dumping
db
ethdb
.
Database
// Low level persistent database to store final content in
snaps
*
snapshot
.
Tree
// Snapshot tree for fast trie leaf access
triegc
*
prque
.
Prque
// Priority queue mapping block numbers to tries to gc
gcproc
time
.
Duration
// Accumulates canonical block processing for trie dumping
hc
*
HeaderChain
rmLogsFeed
event
.
Feed
...
...
@@ -301,7 +301,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
}
// Load any existing snapshot, regenerating it if loading failed
head
:=
bc
.
CurrentBlock
()
if
bc
.
snaps
,
err
=
snapshot
.
New
(
bc
.
db
,
"snapshot.rlp"
,
head
.
NumberU64
(),
head
.
Root
());
err
!=
nil
{
if
bc
.
snaps
,
err
=
snapshot
.
New
(
bc
.
db
,
"snapshot.rlp"
,
head
.
Root
());
err
!=
nil
{
return
nil
,
err
}
// Take ownership of this particular state
...
...
core/rawdb/accessors_snapshot.go
View file @
d754091a
...
...
@@ -17,38 +17,36 @@
package
rawdb
import
(
"encoding/binary"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
)
// ReadSnapshot
Block retrieves the number and root of the block whose state is
//
contained in
the persisted snapshot.
func
ReadSnapshot
Block
(
db
ethdb
.
KeyValueReader
)
(
uint64
,
common
.
Hash
)
{
data
,
_
:=
db
.
Get
(
snapshot
Block
Key
)
if
len
(
data
)
!=
8
+
common
.
HashLength
{
return
0
,
common
.
Hash
{}
// ReadSnapshot
Root retrieves the root of the block whose state is contained in
// the persisted snapshot.
func
ReadSnapshot
Root
(
db
ethdb
.
KeyValueReader
)
common
.
Hash
{
data
,
_
:=
db
.
Get
(
snapshot
Root
Key
)
if
len
(
data
)
!=
common
.
HashLength
{
return
common
.
Hash
{}
}
return
binary
.
BigEndian
.
Uint64
(
data
[
:
8
]),
common
.
BytesToHash
(
data
[
8
:
]
)
return
common
.
BytesToHash
(
data
)
}
// WriteSnapshot
Block stores the number and root of the block whose state is
//
contained in
the persisted snapshot.
func
WriteSnapshot
Block
(
db
ethdb
.
KeyValueWriter
,
number
uint64
,
root
common
.
Hash
)
{
if
err
:=
db
.
Put
(
snapshot
BlockKey
,
append
(
encodeBlockNumber
(
number
),
root
.
Bytes
()
...
)
);
err
!=
nil
{
log
.
Crit
(
"Failed to store snaps
not block's number and
root"
,
"err"
,
err
)
// WriteSnapshot
Root stores the root of the block whose state is contained in
// the persisted snapshot.
func
WriteSnapshot
Root
(
db
ethdb
.
KeyValueWriter
,
root
common
.
Hash
)
{
if
err
:=
db
.
Put
(
snapshot
RootKey
,
root
[
:
]
);
err
!=
nil
{
log
.
Crit
(
"Failed to store snaps
hot
root"
,
"err"
,
err
)
}
}
// DeleteSnapshot
Block deletes the number and hash of the block whose state is
//
contained in the persisted snapshot. Since snapshots are not immutable, this
//
method can be used during updates, so a crash or failure will mark the entire
//
snapshot
invalid.
func
DeleteSnapshot
Block
(
db
ethdb
.
KeyValueWriter
)
{
if
err
:=
db
.
Delete
(
snapshot
Block
Key
);
err
!=
nil
{
log
.
Crit
(
"Failed to remove snaps
not block's number and hash
"
,
"err"
,
err
)
// DeleteSnapshot
Root deletes the hash of the block whose state is contained in
//
the persisted snapshot. Since snapshots are not immutable, this method can
//
be used during updates, so a crash or failure will mark the entire snapshot
// invalid.
func
DeleteSnapshot
Root
(
db
ethdb
.
KeyValueWriter
)
{
if
err
:=
db
.
Delete
(
snapshot
Root
Key
);
err
!=
nil
{
log
.
Crit
(
"Failed to remove snaps
hot root
"
,
"err"
,
err
)
}
}
...
...
core/rawdb/schema.go
View file @
d754091a
...
...
@@ -41,8 +41,8 @@ var (
// fastTrieProgressKey tracks the number of trie entries imported during fast sync.
fastTrieProgressKey
=
[]
byte
(
"TrieSync"
)
// snapshot
Block
Key tracks the number and hash of the last snapshot.
snapshot
BlockKey
=
[]
byte
(
"SnapshotBlock
"
)
// snapshot
Root
Key tracks the number and hash of the last snapshot.
snapshot
RootKey
=
[]
byte
(
"SnapshotRoot
"
)
// Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes).
headerPrefix
=
[]
byte
(
"h"
)
// headerPrefix + num (uint64 big endian) + hash -> header
...
...
core/state/snapshot/difflayer.go
View file @
d754091a
...
...
@@ -36,9 +36,8 @@ type diffLayer struct {
parent
snapshot
// Parent snapshot modified by this one, never nil
memory
uint64
// Approximate guess as to how much memory we use
number
uint64
// Block number to which this snapshot diff belongs to
root
common
.
Hash
// Root hash to which this snapshot diff belongs to
stale
bool
// Signals that the layer became stale (state progressed)
root
common
.
Hash
// Root hash to which this snapshot diff belongs to
stale
bool
// Signals that the layer became stale (state progressed)
accountList
[]
common
.
Hash
// List of account for iteration. If it exists, it's sorted, otherwise it's nil
accountData
map
[
common
.
Hash
][]
byte
// Keyed accounts for direct retrival (nil means deleted)
...
...
@@ -50,11 +49,10 @@ type diffLayer struct {
// newDiffLayer creates a new diff on top of an existing snapshot, whether that's a low
// level persistent database or a hierarchical diff already.
func
newDiffLayer
(
parent
snapshot
,
number
uint64
,
root
common
.
Hash
,
accounts
map
[
common
.
Hash
][]
byte
,
storage
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
*
diffLayer
{
func
newDiffLayer
(
parent
snapshot
,
root
common
.
Hash
,
accounts
map
[
common
.
Hash
][]
byte
,
storage
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
*
diffLayer
{
// Create the new layer with some pre-allocated data segments
dl
:=
&
diffLayer
{
parent
:
parent
,
number
:
number
,
root
:
root
,
accountData
:
accounts
,
storageData
:
storage
,
...
...
@@ -63,7 +61,6 @@ func newDiffLayer(parent snapshot, number uint64, root common.Hash, accounts map
for
_
,
data
:=
range
accounts
{
dl
.
memory
+=
uint64
(
len
(
data
))
}
// Fill the storage hashes and sort them for the iterator
dl
.
storageList
=
make
(
map
[
common
.
Hash
][]
common
.
Hash
)
...
...
@@ -93,9 +90,18 @@ func newDiffLayer(parent snapshot, number uint64, root common.Hash, accounts map
return
dl
}
// Info returns the block number and root hash for which this snapshot was made.
func
(
dl
*
diffLayer
)
Info
()
(
uint64
,
common
.
Hash
)
{
return
dl
.
number
,
dl
.
root
// Root returns the root hash for which this snapshot was made.
func
(
dl
*
diffLayer
)
Root
()
common
.
Hash
{
return
dl
.
root
}
// Stale return whether this layer has become stale (was flattened across) or if
// it's still live.
func
(
dl
*
diffLayer
)
Stale
()
bool
{
dl
.
lock
.
RLock
()
defer
dl
.
lock
.
RUnlock
()
return
dl
.
stale
}
// Account directly retrieves the account associated with a particular hash in
...
...
@@ -164,7 +170,7 @@ func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
// Update creates a new layer on top of the existing snapshot diff tree with
// the specified data items.
func
(
dl
*
diffLayer
)
Update
(
blockRoot
common
.
Hash
,
accounts
map
[
common
.
Hash
][]
byte
,
storage
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
*
diffLayer
{
return
newDiffLayer
(
dl
,
dl
.
number
+
1
,
blockRoot
,
accounts
,
storage
)
return
newDiffLayer
(
dl
,
blockRoot
,
accounts
,
storage
)
}
// flatten pushes all data from this point downwards, flattening everything into
...
...
@@ -213,7 +219,6 @@ func (dl *diffLayer) flatten() snapshot {
// Return the combo parent
return
&
diffLayer
{
parent
:
parent
.
parent
,
number
:
dl
.
number
,
root
:
dl
.
root
,
storageList
:
parent
.
storageList
,
storageData
:
parent
.
storageData
,
...
...
core/state/snapshot/difflayer_journal.go
View file @
d754091a
...
...
@@ -43,18 +43,12 @@ type journalStorage struct {
// diff and verifying that it can be linked to the requested parent.
func
loadDiffLayer
(
parent
snapshot
,
r
*
rlp
.
Stream
)
(
snapshot
,
error
)
{
// Read the next diff journal entry
var
(
number
uint64
root
common
.
Hash
)
if
err
:=
r
.
Decode
(
&
number
);
err
!=
nil
{
var
root
common
.
Hash
if
err
:=
r
.
Decode
(
&
root
);
err
!=
nil
{
// The first read may fail with EOF, marking the end of the journal
if
err
==
io
.
EOF
{
return
parent
,
nil
}
return
nil
,
fmt
.
Errorf
(
"load diff number: %v"
,
err
)
}
if
err
:=
r
.
Decode
(
&
root
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"load diff root: %v"
,
err
)
}
var
accounts
[]
journalAccount
...
...
@@ -77,13 +71,7 @@ func loadDiffLayer(parent snapshot, r *rlp.Stream) (snapshot, error) {
}
storageData
[
entry
.
Hash
]
=
slots
}
// Validate the block number to avoid state corruption
if
parent
,
ok
:=
parent
.
(
*
diffLayer
);
ok
{
if
number
!=
parent
.
number
+
1
{
return
nil
,
fmt
.
Errorf
(
"snapshot chain broken: block #%d after #%d"
,
number
,
parent
.
number
)
}
}
return
loadDiffLayer
(
newDiffLayer
(
parent
,
number
,
root
,
accountData
,
storageData
),
r
)
return
loadDiffLayer
(
newDiffLayer
(
parent
,
root
,
accountData
,
storageData
),
r
)
}
// journal is the internal version of Journal that also returns the journal file
...
...
@@ -113,13 +101,8 @@ func (dl *diffLayer) journal() (io.WriteCloser, error) {
writer
.
Close
()
return
nil
,
ErrSnapshotStale
}
buf
:=
bufio
.
NewWriter
(
writer
)
// Everything below was journalled, persist this layer too
if
err
:=
rlp
.
Encode
(
buf
,
dl
.
number
);
err
!=
nil
{
buf
.
Flush
()
writer
.
Close
()
return
nil
,
err
}
buf
:=
bufio
.
NewWriter
(
writer
)
if
err
:=
rlp
.
Encode
(
buf
,
dl
.
root
);
err
!=
nil
{
buf
.
Flush
()
writer
.
Close
()
...
...
core/state/snapshot/difflayer_test.go
View file @
d754091a
...
...
@@ -61,11 +61,11 @@ func TestMergeBasics(t *testing.T) {
}
}
// Add some (identical) layers on top
parent
:=
newDiffLayer
(
emptyLayer
{},
1
,
common
.
Hash
{},
accounts
,
storage
)
child
:=
newDiffLayer
(
parent
,
1
,
common
.
Hash
{},
accounts
,
storage
)
child
=
newDiffLayer
(
child
,
1
,
common
.
Hash
{},
accounts
,
storage
)
child
=
newDiffLayer
(
child
,
1
,
common
.
Hash
{},
accounts
,
storage
)
child
=
newDiffLayer
(
child
,
1
,
common
.
Hash
{},
accounts
,
storage
)
parent
:=
newDiffLayer
(
emptyLayer
{},
common
.
Hash
{},
accounts
,
storage
)
child
:=
newDiffLayer
(
parent
,
common
.
Hash
{},
accounts
,
storage
)
child
=
newDiffLayer
(
child
,
common
.
Hash
{},
accounts
,
storage
)
child
=
newDiffLayer
(
child
,
common
.
Hash
{},
accounts
,
storage
)
child
=
newDiffLayer
(
child
,
common
.
Hash
{},
accounts
,
storage
)
// And flatten
merged
:=
(
child
.
flatten
())
.
(
*
diffLayer
)
...
...
@@ -122,7 +122,7 @@ func TestMergeDelete(t *testing.T) {
}
// Add some flip-flopping layers on top
parent
:=
newDiffLayer
(
emptyLayer
{},
1
,
common
.
Hash
{},
flip
(),
storage
)
parent
:=
newDiffLayer
(
emptyLayer
{},
common
.
Hash
{},
flip
(),
storage
)
child
:=
parent
.
Update
(
common
.
Hash
{},
flop
(),
storage
)
child
=
child
.
Update
(
common
.
Hash
{},
flip
(),
storage
)
child
=
child
.
Update
(
common
.
Hash
{},
flop
(),
storage
)
...
...
@@ -139,10 +139,6 @@ func TestMergeDelete(t *testing.T) {
// And flatten
merged
:=
(
child
.
flatten
())
.
(
*
diffLayer
)
// check number
if
got
,
exp
:=
merged
.
number
,
child
.
number
;
got
!=
exp
{
t
.
Errorf
(
"merged layer: wrong number - exp %d got %d"
,
exp
,
got
)
}
if
data
,
_
:=
merged
.
Account
(
h1
);
data
==
nil
{
t
.
Errorf
(
"merged layer: expected %x to be non-nil"
,
h1
)
}
...
...
@@ -169,7 +165,7 @@ func TestInsertAndMerge(t *testing.T) {
{
var
accounts
=
make
(
map
[
common
.
Hash
][]
byte
)
var
storage
=
make
(
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
parent
=
newDiffLayer
(
emptyLayer
{},
1
,
common
.
Hash
{},
accounts
,
storage
)
parent
=
newDiffLayer
(
emptyLayer
{},
common
.
Hash
{},
accounts
,
storage
)
}
{
var
accounts
=
make
(
map
[
common
.
Hash
][]
byte
)
...
...
@@ -178,7 +174,7 @@ func TestInsertAndMerge(t *testing.T) {
accstorage
:=
make
(
map
[
common
.
Hash
][]
byte
)
storage
[
acc
]
=
accstorage
storage
[
acc
][
slot
]
=
[]
byte
{
0x01
}
child
=
newDiffLayer
(
parent
,
2
,
common
.
Hash
{},
accounts
,
storage
)
child
=
newDiffLayer
(
parent
,
common
.
Hash
{},
accounts
,
storage
)
}
// And flatten
merged
:=
(
child
.
flatten
())
.
(
*
diffLayer
)
...
...
@@ -200,11 +196,12 @@ func (emptyLayer) Journal() error {
panic
(
"implement me"
)
}
func
(
emptyLayer
)
Info
()
(
uint64
,
common
.
Hash
)
{
return
0
,
common
.
Hash
{}
func
(
emptyLayer
)
Stale
()
bool
{
panic
(
"implement me"
)
}
func
(
emptyLayer
)
Number
()
uint64
{
return
0
func
(
emptyLayer
)
Root
()
common
.
Hash
{
return
common
.
Hash
{}
}
func
(
emptyLayer
)
Account
(
hash
common
.
Hash
)
(
*
Account
,
error
)
{
...
...
@@ -227,8 +224,6 @@ func (emptyLayer) Storage(accountHash, storageHash common.Hash) ([]byte, error)
// BenchmarkSearch-6 500000 3723 ns/op (10k per layer, only top-level RLock()
func
BenchmarkSearch
(
b
*
testing
.
B
)
{
// First, we set up 128 diff layers, with 1K items each
blocknum
:=
uint64
(
0
)
fill
:=
func
(
parent
snapshot
)
*
diffLayer
{
accounts
:=
make
(
map
[
common
.
Hash
][]
byte
)
storage
:=
make
(
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
...
...
@@ -236,10 +231,8 @@ func BenchmarkSearch(b *testing.B) {
for
i
:=
0
;
i
<
10000
;
i
++
{
accounts
[
randomHash
()]
=
randomAccount
()
}
blocknum
++
return
newDiffLayer
(
parent
,
blocknum
,
common
.
Hash
{},
accounts
,
storage
)
return
newDiffLayer
(
parent
,
common
.
Hash
{},
accounts
,
storage
)
}
var
layer
snapshot
layer
=
emptyLayer
{}
for
i
:=
0
;
i
<
128
;
i
++
{
...
...
@@ -261,8 +254,6 @@ func BenchmarkSearch(b *testing.B) {
// BenchmarkSearchSlot-6 100000 14551 ns/op (when checking parent number using atomic)
func
BenchmarkSearchSlot
(
b
*
testing
.
B
)
{
// First, we set up 128 diff layers, with 1K items each
blocknum
:=
uint64
(
0
)
accountKey
:=
common
.
Hash
{}
storageKey
:=
common
.
HexToHash
(
"0x1337"
)
accountRLP
:=
randomAccount
()
...
...
@@ -278,16 +269,13 @@ func BenchmarkSearchSlot(b *testing.B) {
accStorage
[
randomHash
()]
=
value
storage
[
accountKey
]
=
accStorage
}
blocknum
++
return
newDiffLayer
(
parent
,
blocknum
,
common
.
Hash
{},
accounts
,
storage
)
return
newDiffLayer
(
parent
,
common
.
Hash
{},
accounts
,
storage
)
}
var
layer
snapshot
layer
=
emptyLayer
{}
for
i
:=
0
;
i
<
128
;
i
++
{
layer
=
fill
(
layer
)
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
layer
.
Storage
(
accountKey
,
storageKey
)
...
...
@@ -300,7 +288,7 @@ func BenchmarkSearchSlot(b *testing.B) {
// Without sorting and tracking accountlist
// BenchmarkFlatten-6 300 5511511 ns/op
func
BenchmarkFlatten
(
b
*
testing
.
B
)
{
fill
:=
func
(
parent
snapshot
,
blocknum
int
)
*
diffLayer
{
fill
:=
func
(
parent
snapshot
)
*
diffLayer
{
accounts
:=
make
(
map
[
common
.
Hash
][]
byte
)
storage
:=
make
(
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
...
...
@@ -317,7 +305,7 @@ func BenchmarkFlatten(b *testing.B) {
}
storage
[
accountKey
]
=
accStorage
}
return
newDiffLayer
(
parent
,
uint64
(
blocknum
),
common
.
Hash
{},
accounts
,
storage
)
return
newDiffLayer
(
parent
,
common
.
Hash
{},
accounts
,
storage
)
}
b
.
ResetTimer
()
...
...
@@ -327,7 +315,7 @@ func BenchmarkFlatten(b *testing.B) {
var
layer
snapshot
layer
=
emptyLayer
{}
for
i
:=
1
;
i
<
128
;
i
++
{
layer
=
fill
(
layer
,
i
)
layer
=
fill
(
layer
)
}
b
.
StartTimer
()
...
...
@@ -336,7 +324,6 @@ func BenchmarkFlatten(b *testing.B) {
if
!
ok
{
break
}
layer
=
dl
.
flatten
()
}
b
.
StopTimer
()
...
...
@@ -351,7 +338,7 @@ func BenchmarkFlatten(b *testing.B) {
// BenchmarkJournal-6 1 1471373923 ns/ops
// BenchmarkJournal-6 1 1208083335 ns/op // bufio writer
func
BenchmarkJournal
(
b
*
testing
.
B
)
{
fill
:=
func
(
parent
snapshot
,
blocknum
int
)
*
diffLayer
{
fill
:=
func
(
parent
snapshot
)
*
diffLayer
{
accounts
:=
make
(
map
[
common
.
Hash
][]
byte
)
storage
:=
make
(
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
...
...
@@ -368,15 +355,14 @@ func BenchmarkJournal(b *testing.B) {
}
storage
[
accountKey
]
=
accStorage
}
return
newDiffLayer
(
parent
,
uint64
(
blocknum
),
common
.
Hash
{},
accounts
,
storage
)
return
newDiffLayer
(
parent
,
common
.
Hash
{},
accounts
,
storage
)
}
var
layer
snapshot
layer
=
&
diskLayer
{
journal
:
path
.
Join
(
os
.
TempDir
(),
"difflayer_journal.tmp"
),
}
for
i
:=
1
;
i
<
128
;
i
++
{
layer
=
fill
(
layer
,
i
)
layer
=
fill
(
layer
)
}
b
.
ResetTimer
()
...
...
core/state/snapshot/disklayer.go
View file @
d754091a
...
...
@@ -32,16 +32,24 @@ type diskLayer struct {
db
ethdb
.
KeyValueStore
// Key-value store containing the base snapshot
cache
*
bigcache
.
BigCache
// Cache to avoid hitting the disk for direct access
number
uint64
// Block number of the base snapshot
root
common
.
Hash
// Root hash of the base snapshot
stale
bool
// Signals that the layer became stale (state progressed)
root
common
.
Hash
// Root hash of the base snapshot
stale
bool
// Signals that the layer became stale (state progressed)
lock
sync
.
RWMutex
}
// Info returns the block number and root hash for which this snapshot was made.
func
(
dl
*
diskLayer
)
Info
()
(
uint64
,
common
.
Hash
)
{
return
dl
.
number
,
dl
.
root
// Root returns root hash for which this snapshot was made.
func
(
dl
*
diskLayer
)
Root
()
common
.
Hash
{
return
dl
.
root
}
// Stale return whether this layer has become stale (was flattened across) or if
// it's still live.
func
(
dl
*
diskLayer
)
Stale
()
bool
{
dl
.
lock
.
RLock
()
defer
dl
.
lock
.
RUnlock
()
return
dl
.
stale
}
// Account directly retrieves the account associated with a particular hash in
...
...
@@ -123,7 +131,7 @@ func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
// the specified data items. Note, the maps are retained by the method to avoid
// copying everything.
func
(
dl
*
diskLayer
)
Update
(
blockHash
common
.
Hash
,
accounts
map
[
common
.
Hash
][]
byte
,
storage
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
)
*
diffLayer
{
return
newDiffLayer
(
dl
,
dl
.
number
+
1
,
blockHash
,
accounts
,
storage
)
return
newDiffLayer
(
dl
,
blockHash
,
accounts
,
storage
)
}
// Journal commits an entire diff hierarchy to disk into a single journal file.
...
...
core/state/snapshot/generate.go
View file @
d754091a
...
...
@@ -85,7 +85,7 @@ func wipeSnapshot(db ethdb.KeyValueStore) error {
}
it
.
Release
()
rawdb
.
DeleteSnapshot
Block
(
batch
)
rawdb
.
DeleteSnapshot
Root
(
batch
)
if
err
:=
batch
.
Write
();
err
!=
nil
{
return
err
}
...
...
@@ -107,7 +107,7 @@ func wipeSnapshot(db ethdb.KeyValueStore) error {
}
// generateSnapshot regenerates a brand new snapshot based on an existing state database and head block.
func
generateSnapshot
(
db
ethdb
.
KeyValueStore
,
journal
string
,
headNumber
uint64
,
headR
oot
common
.
Hash
)
(
snapshot
,
error
)
{
func
generateSnapshot
(
db
ethdb
.
KeyValueStore
,
journal
string
,
r
oot
common
.
Hash
)
(
snapshot
,
error
)
{
// Wipe any previously existing snapshot from the database
if
err
:=
wipeSnapshot
(
db
);
err
!=
nil
{
return
nil
,
err
...
...
@@ -124,7 +124,7 @@ func generateSnapshot(db ethdb.KeyValueStore, journal string, headNumber uint64,
batch
:=
db
.
NewBatch
()
triedb
:=
trie
.
NewDatabase
(
db
)
accTrie
,
err
:=
trie
.
NewSecure
(
headR
oot
,
triedb
)
accTrie
,
err
:=
trie
.
NewSecure
(
r
oot
,
triedb
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -186,7 +186,7 @@ func generateSnapshot(db ethdb.KeyValueStore, journal string, headNumber uint64,
fmt
.
Printf
(
"Totals: %9s (%d accs, %d nodes) + %9s (%d slots, %d nodes)
\n
"
,
accountSize
.
TerminalString
(),
accountCount
,
accIt
.
Nodes
,
storageSize
.
TerminalString
(),
storageCount
,
storageNodes
)
// Update the snapshot block marker and write any remainder data
rawdb
.
WriteSnapshot
Block
(
batch
,
headNumber
,
headR
oot
)
rawdb
.
WriteSnapshot
Root
(
batch
,
r
oot
)
batch
.
Write
()
batch
.
Reset
()
...
...
@@ -207,7 +207,6 @@ func generateSnapshot(db ethdb.KeyValueStore, journal string, headNumber uint64,
journal
:
journal
,
db
:
db
,
cache
:
cache
,
number
:
headNumber
,
root
:
headRoot
,
root
:
root
,
},
nil
}
core/state/snapshot/generate_test.go
View file @
d754091a
...
...
@@ -47,7 +47,7 @@ func TestWipe(t *testing.T) {
rawdb
.
WriteStorageSnapshot
(
db
,
account
,
randomHash
(),
randomHash
()
.
Bytes
())
}
}
rawdb
.
WriteSnapshot
Block
(
db
,
123
,
randomHash
())
rawdb
.
WriteSnapshot
Root
(
db
,
randomHash
())
// Add some random non-snapshot data too to make wiping harder
for
i
:=
0
;
i
<
65536
;
i
++
{
...
...
@@ -76,8 +76,8 @@ func TestWipe(t *testing.T) {
if
items
!=
128
+
128
*
1024
{
t
.
Fatalf
(
"snapshot size mismatch: have %d, want %d"
,
items
,
128
+
128
*
1024
)
}
if
number
,
hash
:=
rawdb
.
ReadSnapshotBlock
(
db
);
number
!=
123
||
hash
==
(
common
.
Hash
{})
{
t
.
Errorf
(
"snapshot block marker mismatch: have
#%d [%#x], want #%d [<not-nil>]"
,
number
,
hash
,
123
)
if
hash
:=
rawdb
.
ReadSnapshotRoot
(
db
);
hash
==
(
common
.
Hash
{})
{
t
.
Errorf
(
"snapshot block marker mismatch: have
%#x, want <not-nil>"
,
hash
)
}
// Wipe all snapshot entries from the database
if
err
:=
wipeSnapshot
(
db
);
err
!=
nil
{
...
...
@@ -93,8 +93,8 @@ func TestWipe(t *testing.T) {
t
.
Errorf
(
"snapshot entry remained after wipe: %x"
,
key
)
}
}
if
number
,
hash
:=
rawdb
.
ReadSnapshotBlock
(
db
);
number
!=
0
||
hash
!=
(
common
.
Hash
{})
{
t
.
Errorf
(
"snapshot block marker remained after wipe:
#%d [%#x]"
,
number
,
hash
)
if
hash
:=
rawdb
.
ReadSnapshotRoot
(
db
);
hash
!=
(
common
.
Hash
{})
{
t
.
Errorf
(
"snapshot block marker remained after wipe:
%#x"
,
hash
)
}
// Iterate over the database and ensure miscellaneous items are present
items
=
0
...
...
core/state/snapshot/snapshot.go
View file @
d754091a
This diff is collapsed.
Click to expand it.
core/state/snapshot/snapshot_test.go
View file @
d754091a
...
...
@@ -37,7 +37,7 @@ func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) {
root
:
common
.
HexToHash
(
"0x01"
),
cache
:
cache
,
}
snaps
:=
&
Snapshot
Tree
{
snaps
:=
&
Tree
{
layers
:
map
[
common
.
Hash
]
snapshot
{
base
.
root
:
base
,
},
...
...
@@ -83,7 +83,7 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) {
root
:
common
.
HexToHash
(
"0x01"
),
cache
:
cache
,
}
snaps
:=
&
Snapshot
Tree
{
snaps
:=
&
Tree
{
layers
:
map
[
common
.
Hash
]
snapshot
{
base
.
root
:
base
,
},
...
...
@@ -132,7 +132,7 @@ func TestDiffLayerExternalInvalidationFullFlatten(t *testing.T) {
root
:
common
.
HexToHash
(
"0x01"
),
cache
:
cache
,
}
snaps
:=
&
Snapshot
Tree
{
snaps
:=
&
Tree
{
layers
:
map
[
common
.
Hash
]
snapshot
{
base
.
root
:
base
,
},
...
...
@@ -181,7 +181,7 @@ func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) {
root
:
common
.
HexToHash
(
"0x01"
),
cache
:
cache
,
}
snaps
:=
&
Snapshot
Tree
{
snaps
:=
&
Tree
{
layers
:
map
[
common
.
Hash
]
snapshot
{
base
.
root
:
base
,
},
...
...
@@ -213,7 +213,6 @@ func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) {
if
got
:=
len
(
snaps
.
layers
);
got
!=
exp
{
t
.
Errorf
(
"layers modified, got %d exp %d"
,
got
,
exp
)
}
// Flatten the diff layer into the bottom accumulator
if
err
:=
snaps
.
Cap
(
common
.
HexToHash
(
"0x04"
),
2
,
1024
*
1024
);
err
!=
nil
{
t
.
Fatalf
(
"failed to flatten diff layer into accumulator: %v"
,
err
)
...
...
@@ -247,7 +246,7 @@ func TestPostCapBasicDataAccess(t *testing.T) {
root
:
common
.
HexToHash
(
"0x01"
),
cache
:
cache
,
}
snaps
:=
&
Snapshot
Tree
{
snaps
:=
&
Tree
{
layers
:
map
[
common
.
Hash
]
snapshot
{
base
.
root
:
base
,
},
...
...
core/state/statedb.go
View file @
d754091a
...
...
@@ -68,7 +68,7 @@ type StateDB struct {
db
Database
trie
Trie
snaps
*
snapshot
.
Snapshot
Tree
snaps
*
snapshot
.
Tree
snap
snapshot
.
Snapshot
snapAccounts
map
[
common
.
Hash
][]
byte
snapStorage
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
...
...
@@ -117,7 +117,7 @@ type StateDB struct {
}
// Create a new state from a given trie.
func
New
(
root
common
.
Hash
,
db
Database
,
snaps
*
snapshot
.
Snapshot
Tree
)
(
*
StateDB
,
error
)
{
func
New
(
root
common
.
Hash
,
db
Database
,
snaps
*
snapshot
.
Tree
)
(
*
StateDB
,
error
)
{
tr
,
err
:=
db
.
OpenTrie
(
root
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -840,12 +840,14 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
if
metrics
.
EnabledExpensive
{
defer
func
(
start
time
.
Time
)
{
s
.
SnapshotCommits
+=
time
.
Since
(
start
)
}(
time
.
Now
())
}
_
,
parentRoot
:=
s
.
snap
.
Info
()
if
err
:=
s
.
snaps
.
Update
(
root
,
parentRoot
,
s
.
snapAccounts
,
s
.
snapStorage
);
err
!=
nil
{
log
.
Warn
(
"Failed to update snapshot tree"
,
"from"
,
parentRoot
,
"to"
,
root
,
"err"
,
err
)
}
if
err
:=
s
.
snaps
.
Cap
(
root
,
16
,
4
*
1024
*
1024
);
err
!=
nil
{
log
.
Warn
(
"Failed to cap snapshot tree"
,
"root"
,
root
,
"layers"
,
16
,
"memory"
,
4
*
1024
*
1024
,
"err"
,
err
)
// Only update if there's a state transition (skip empty Clique blocks)
if
parent
:=
s
.
snap
.
Root
();
parent
!=
root
{
if
err
:=
s
.
snaps
.
Update
(
root
,
parent
,
s
.
snapAccounts
,
s
.
snapStorage
);
err
!=
nil
{
log
.
Warn
(
"Failed to update snapshot tree"
,
"from"
,
parent
,
"to"
,
root
,
"err"
,
err
)
}
if
err
:=
s
.
snaps
.
Cap
(
root
,
16
,
4
*
1024
*
1024
);
err
!=
nil
{
log
.
Warn
(
"Failed to cap snapshot tree"
,
"root"
,
root
,
"layers"
,
16
,
"memory"
,
4
*
1024
*
1024
,
"err"
,
err
)
}
}
s
.
snap
,
s
.
snapAccounts
,
s
.
snapStorage
=
nil
,
nil
,
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