Skip to content

Commit 23f6c8a

Browse files
committed
open trie when first invoke
1 parent f4de333 commit 23f6c8a

3 files changed

Lines changed: 52 additions & 11 deletions

File tree

core/state/database.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,13 @@ func (db *CachingDB) Snapshot() *snapshot.Tree {
248248
func (db *CachingDB) SetSnapshot(snap *snapshot.Tree) {
249249
db.snap = snap
250250
}
251+
252+
// mustCopyTrie returns a deep-copied trie.
253+
func mustCopyTrie(t Trie) Trie {
254+
switch t := t.(type) {
255+
case *trie.StateTrie:
256+
return t.Copy()
257+
default:
258+
panic(fmt.Errorf("unknown trie type %T", t))
259+
}
260+
}

core/state/iterator.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import (
3232
type NodeIterator struct {
3333
state *StateDB // State being iterated
3434

35+
tr Trie // Primary account trie for traversal
36+
3537
stateIt trie.NodeIterator // Primary iterator for the global state trie
3638
dataIt trie.NodeIterator // Secondary iterator for the data trie of a contract
3739

@@ -74,9 +76,20 @@ func (it *NodeIterator) step() error {
7476
if it.state == nil {
7577
return nil
7678
}
79+
if it.tr == nil {
80+
tr, err := it.state.db.OpenTrie(it.state.originalRoot)
81+
if err != nil {
82+
return err
83+
}
84+
it.tr = tr
85+
}
7786
// Initialize the iterator if we've just started
7887
if it.stateIt == nil {
79-
it.stateIt = it.state.trie.NodeIterator(nil)
88+
stateIt := it.tr.NodeIterator(nil)
89+
if stateIt == nil {
90+
return errors.New("state iter is nil")
91+
}
92+
it.stateIt = stateIt
8093
}
8194
// If we had data nodes previously, we surely have at least state nodes
8295
if it.dataIt != nil {
@@ -111,15 +124,14 @@ func (it *NodeIterator) step() error {
111124
return err
112125
}
113126
// Lookup the preimage of account hash
114-
preimage := it.state.trie.GetKey(it.stateIt.LeafKey())
127+
preimage := it.tr.GetKey(it.stateIt.LeafKey())
115128
if preimage == nil {
116129
return errors.New("account address is not available")
117130
}
118131
address := common.BytesToAddress(preimage)
119132

120133
// Traverse the storage slots belong to the account
121-
dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root, it.state.trie)
122-
//dataTrie, err := it.state.db.OpenStorageTrie(common.BytesToAddress(it.stateIt.LeafKey()), account.Root)
134+
dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root, it.tr)
123135
if err != nil {
124136
return err
125137
}

core/state/statedb.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,8 @@ type StateDB struct {
166166

167167
// Create a new state from a given trie.
168168
func New(root common.Hash, db Database) (*StateDB, error) {
169-
tr, err := db.OpenTrie(root)
170-
if err != nil {
171-
return nil, err
172-
}
173169
sdb := &StateDB{
174170
db: db,
175-
trie: tr,
176171
originalRoot: root,
177172
accounts: make(map[common.Hash][]byte),
178173
storages: make(map[common.Hash]map[common.Hash][]byte),
@@ -671,6 +666,14 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
671666
// If snapshot unavailable or reading from it failed, load from the database
672667
if data == nil {
673668
start := time.Now()
669+
if s.trie == nil {
670+
tr, err := s.db.OpenTrie(s.originalRoot)
671+
if err != nil {
672+
return nil
673+
}
674+
s.trie = tr
675+
676+
}
674677
enc, err := s.trie.TryGet(addr.Bytes())
675678
s.AccountReads += time.Since(start)
676679
if err != nil {
@@ -782,8 +785,7 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common
782785
func (s *StateDB) Copy() *StateDB {
783786
// Copy all the basic fields, initialize the memory ones
784787
state := &StateDB{
785-
db: s.db,
786-
trie: s.db.CopyTrie(s.trie),
788+
db: s.db,
787789
//hasher: crypto.NewKeccakState(),
788790
originalRoot: s.originalRoot,
789791
accounts: copySet(s.accounts),
@@ -808,6 +810,9 @@ func (s *StateDB) Copy() *StateDB {
808810
// miner to operate trie-backed only.
809811
snap: s.snap,
810812
}
813+
if s.trie != nil {
814+
state.trie = mustCopyTrie(s.trie)
815+
}
811816
// Deep copy cached state objects.
812817
for addr, obj := range s.stateObjects {
813818
state.stateObjects[addr] = obj.deepCopy(state)
@@ -913,6 +918,20 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
913918
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
914919
// Finalise all the dirty storage states and write them into the tries
915920
s.Finalise(deleteEmptyObjects)
921+
// Initialize the trie if it's not constructed yet. If the prefetch
922+
// is enabled, the trie constructed below will be replaced by the
923+
// prefetched one.
924+
//
925+
// This operation must be done before state object storage hashing,
926+
// as it assumes the main trie is already loaded.
927+
if s.trie == nil {
928+
tr, err := s.db.OpenTrie(s.originalRoot)
929+
if err != nil {
930+
s.setError(err)
931+
return common.Hash{}
932+
}
933+
s.trie = tr
934+
}
916935

917936
// If there was a trie prefetcher operating, terminate it async so that the
918937
// individual storage tries can be updated as soon as the disk load finishes.

0 commit comments

Comments
 (0)