Skip to content

Commit f73f168

Browse files
rjl493456442blakehhuynh
authored andcommitted
trie: cleanup stateTrie (ethereum#25640)
It's a trivial PR to hide the error log when the trie node is not found in the database. The idea for this change is for all TryXXX functions, the error is already returned and we don't need to fire a log explicitly. Recently there are a few tickets ethereum#25613 ethereum#25589 reporting that the trie nodes are missing because of debug.SetHead. The root cause is after resetting, the chain rewinds to a historical point and re-imports the blocks on top. Since the node is already synced and started to accept transactions previously, these transactions are still kept in the txpool and verified by txpool with a live state. This live state is constructed based on the live trie database, which is changed fast by node referencing and de-referencing. Unfortunately, when we construct a live state(like the state in txpool), we don't reference the state we have. The blockchain will garbage collect the intermediate version nodes in another thread which leads the broken live state. The best solution for this is to forcibly obtain a reference for all live states we create and call release function once it's used up. But it might end up with more junks persisted into disk. Will try to find an elegant solution later in the following PR.
1 parent 07a1402 commit f73f168

File tree

1 file changed

+39
-46
lines changed

1 file changed

+39
-46
lines changed

trie/secure_trie.go

+39-46
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ func NewSecure(owner common.Hash, root common.Hash, db *Database) (*SecureTrie,
3535
return NewStateTrie(owner, root, db)
3636
}
3737

38-
// StateTrie wraps a trie with key hashing. In a secure trie, all
38+
// StateTrie wraps a trie with key hashing. In a stateTrie trie, all
3939
// access operations hash the key using keccak256. This prevents
4040
// calling code from creating long chains of nodes that
4141
// increase the access time.
4242
//
4343
// Contrary to a regular trie, a StateTrie can only be created with
4444
// New and must have an attached database. The database also stores
45-
// the preimage of each key.
45+
// the preimage of each key if preimage recording is enabled.
4646
//
4747
// StateTrie is not safe for concurrent use.
4848
type StateTrie struct {
@@ -53,17 +53,11 @@ type StateTrie struct {
5353
secKeyCacheOwner *StateTrie // Pointer to self, replace the key cache on mismatch
5454
}
5555

56-
// NewStateTrie creates a trie with an existing root node from a backing database
57-
// and optional intermediate in-memory node pool.
56+
// NewStateTrie creates a trie with an existing root node from a backing database.
5857
//
5958
// If root is the zero hash or the sha3 hash of an empty string, the
6059
// trie is initially empty. Otherwise, New will panic if db is nil
6160
// and returns MissingNodeError if the root node cannot be found.
62-
//
63-
// Accessing the trie loads nodes from the database or node pool on demand.
64-
// Loaded nodes are kept around until their 'cache generation' expires.
65-
// A new cache generation is created by each call to Commit.
66-
// cachelimit sets the number of past cache generations to keep.
6761
func NewStateTrie(owner common.Hash, root common.Hash, db *Database) (*StateTrie, error) {
6862
if db == nil {
6963
panic("trie.NewSecure called without a database")
@@ -87,63 +81,46 @@ func (t *StateTrie) Get(key []byte) []byte {
8781

8882
// TryGet returns the value for key stored in the trie.
8983
// The value bytes must not be modified by the caller.
90-
// If a node was not found in the database, a MissingNodeError is returned.
84+
// If the specified node is not in the trie, nil will be returned.
85+
// If a trie node is not found in the database, a MissingNodeError is returned.
9186
func (t *StateTrie) TryGet(key []byte) ([]byte, error) {
9287
return t.trie.TryGet(t.hashKey(key))
9388
}
9489

90+
// TryGetAccount attempts to retrieve an account with provided trie path.
91+
// If the specified account is not in the trie, nil will be returned.
92+
// If a trie node is not found in the database, a MissingNodeError is returned.
9593
func (t *StateTrie) TryGetAccount(key []byte) (*types.StateAccount, error) {
96-
var ret types.StateAccount
9794
res, err := t.trie.TryGet(t.hashKey(key))
98-
if err != nil {
99-
log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
100-
return &ret, err
101-
}
102-
if res == nil {
103-
return nil, nil
95+
if res == nil || err != nil {
96+
return nil, err
10497
}
105-
err = rlp.DecodeBytes(res, &ret)
106-
return &ret, err
98+
ret := new(types.StateAccount)
99+
err = rlp.DecodeBytes(res, ret)
100+
return ret, err
107101
}
108102

109103
// TryGetAccountWithPreHashedKey does the same thing as TryGetAccount, however
110104
// it expects a key that is already hashed. This constitutes an abstraction leak,
111105
// since the client code needs to know the key format.
112106
func (t *StateTrie) TryGetAccountWithPreHashedKey(key []byte) (*types.StateAccount, error) {
113-
var ret types.StateAccount
114107
res, err := t.trie.TryGet(key)
115-
if err != nil {
116-
log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
117-
return &ret, err
118-
}
119-
if res == nil {
120-
return nil, nil
108+
if res == nil || err != nil {
109+
return nil, err
121110
}
122-
err = rlp.DecodeBytes(res, &ret)
123-
return &ret, err
111+
ret := new(types.StateAccount)
112+
err = rlp.DecodeBytes(res, ret)
113+
return ret, err
124114
}
125115

126116
// TryGetNode attempts to retrieve a trie node by compact-encoded path. It is not
127117
// possible to use keybyte-encoding as the path might contain odd nibbles.
118+
// If the specified trie node is not in the trie, nil will be returned.
119+
// If a trie node is not found in the database, a MissingNodeError is returned.
128120
func (t *StateTrie) TryGetNode(path []byte) ([]byte, int, error) {
129121
return t.trie.TryGetNode(path)
130122
}
131123

132-
// TryUpdateAccount account will abstract the write of an account to the
133-
// secure trie.
134-
func (t *StateTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
135-
hk := t.hashKey(key)
136-
data, err := rlp.EncodeToBytes(acc)
137-
if err != nil {
138-
return err
139-
}
140-
if err := t.trie.TryUpdate(hk, data); err != nil {
141-
return err
142-
}
143-
t.getSecKeyCache()[string(hk)] = common.CopyBytes(key)
144-
return nil
145-
}
146-
147124
// Update associates key with value in the trie. Subsequent calls to
148125
// Get will return value. If value has length zero, any existing value
149126
// is deleted from the trie and calls to Get will return nil.
@@ -163,7 +140,7 @@ func (t *StateTrie) Update(key, value []byte) {
163140
// The value bytes must not be modified by the caller while they are
164141
// stored in the trie.
165142
//
166-
// If a node was not found in the database, a MissingNodeError is returned.
143+
// If a node is not found in the database, a MissingNodeError is returned.
167144
func (t *StateTrie) TryUpdate(key, value []byte) error {
168145
hk := t.hashKey(key)
169146
err := t.trie.TryUpdate(hk, value)
@@ -174,6 +151,21 @@ func (t *StateTrie) TryUpdate(key, value []byte) error {
174151
return nil
175152
}
176153

154+
// TryUpdateAccount account will abstract the write of an account to the
155+
// secure trie.
156+
func (t *StateTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
157+
hk := t.hashKey(key)
158+
data, err := rlp.EncodeToBytes(acc)
159+
if err != nil {
160+
return err
161+
}
162+
if err := t.trie.TryUpdate(hk, data); err != nil {
163+
return err
164+
}
165+
t.getSecKeyCache()[string(hk)] = common.CopyBytes(key)
166+
return nil
167+
}
168+
177169
// Delete removes any existing value for key from the trie.
178170
func (t *StateTrie) Delete(key []byte) {
179171
if err := t.TryDelete(key); err != nil {
@@ -182,14 +174,15 @@ func (t *StateTrie) Delete(key []byte) {
182174
}
183175

184176
// TryDelete removes any existing value for key from the trie.
185-
// If a node was not found in the database, a MissingNodeError is returned.
177+
// If the specified trie node is not in the trie, nothing will be changed.
178+
// If a node is not found in the database, a MissingNodeError is returned.
186179
func (t *StateTrie) TryDelete(key []byte) error {
187180
hk := t.hashKey(key)
188181
delete(t.getSecKeyCache(), string(hk))
189182
return t.trie.TryDelete(hk)
190183
}
191184

192-
// TryDeleteACcount abstracts an account deletion from the trie.
185+
// TryDeleteAccount abstracts an account deletion from the trie.
193186
func (t *StateTrie) TryDeleteAccount(key []byte) error {
194187
hk := t.hashKey(key)
195188
delete(t.getSecKeyCache(), string(hk))

0 commit comments

Comments
 (0)