Skip to content

Commit 0b852e0

Browse files
gballetshekhirin
authored andcommitted
core/state: add account address to Trie slot accessors (ethereum#26934)
This changes the Trie interface to add the plain account address as a parameter to all storage-related methods. After the introduction of the TryAccount* functions, TryGet, TryUpdate and TryDelete are now only meant to read an account's storage. In their current form, they assume that an account storage is stored in a separate trie, and that the hashing of the slot is independent of its account's address. The proposed structure for a stateless storage breaks these two assumptions: the hashing of a slot key requires the address and all slots and accounts are stored in a single trie. This PR therefore adds an address parameter to the interface. It is ignored in the MPT version, so this change has no functional impact, however it will reduce the diff size when merging verkle trees.
1 parent f88d91e commit 0b852e0

File tree

7 files changed

+47
-41
lines changed

7 files changed

+47
-41
lines changed

core/state/database.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ type Trie interface {
6868
// TODO(fjl): remove this when StateTrie is removed
6969
GetKey([]byte) []byte
7070

71-
// TryGet returns the value for key stored in the trie. The value bytes must
72-
// not be modified by the caller. If a node was not found in the database, a
73-
// trie.MissingNodeError is returned.
74-
TryGet(key []byte) ([]byte, error)
71+
// TryGetStorage returns the value for key stored in the trie. The value bytes
72+
// must not be modified by the caller. If a node was not found in the database,
73+
// a trie.MissingNodeError is returned.
74+
TryGetStorage(addr common.Address, key []byte) ([]byte, error)
7575

7676
// TryGetAccount abstracts an account read from the trie. It retrieves the
7777
// account blob from the trie with provided account address and decodes it
@@ -81,20 +81,20 @@ type Trie interface {
8181
// be returned.
8282
TryGetAccount(address common.Address) (*types.StateAccount, error)
8383

84-
// TryUpdate associates key with value in the trie. If value has length zero, any
85-
// existing value is deleted from the trie. The value bytes must not be modified
84+
// TryUpdateStorage associates key with value in the trie. If value has length zero,
85+
// any existing value is deleted from the trie. The value bytes must not be modified
8686
// by the caller while they are stored in the trie. If a node was not found in the
8787
// database, a trie.MissingNodeError is returned.
88-
TryUpdate(key, value []byte) error
88+
TryUpdateStorage(addr common.Address, key, value []byte) error
8989

9090
// TryUpdateAccount abstracts an account write to the trie. It encodes the
9191
// provided account object with associated algorithm and then updates it
9292
// in the trie with provided address.
9393
TryUpdateAccount(address common.Address, account *types.StateAccount) error
9494

95-
// TryDelete removes any existing value for key from the trie. If a node was not
96-
// found in the database, a trie.MissingNodeError is returned.
97-
TryDelete(key []byte) error
95+
// TryDeleteStorage removes any existing value for key from the trie. If a node
96+
// was not found in the database, a trie.MissingNodeError is returned.
97+
TryDeleteStorage(addr common.Address, key []byte) error
9898

9999
// TryDeleteAccount abstracts an account deletion from the trie.
100100
TryDeleteAccount(address common.Address) error

core/state/state_object.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
201201
s.db.setError(err)
202202
return common.Hash{}
203203
}
204-
enc, err = tr.TryGet(key.Bytes())
204+
enc, err = tr.TryGetStorage(s.address, key.Bytes())
205205
if metrics.EnabledExpensive {
206206
s.db.StorageReads += time.Since(start)
207207
}
@@ -253,7 +253,7 @@ func (s *stateObject) finalise(prefetch bool) {
253253
}
254254
}
255255
if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash {
256-
s.db.prefetcher.prefetch(s.addrHash, s.data.Root, slotsToPrefetch)
256+
s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, slotsToPrefetch)
257257
}
258258
if len(s.dirtyStorage) > 0 {
259259
s.dirtyStorage = make(Storage)
@@ -294,15 +294,15 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
294294

295295
var v []byte
296296
if (value == common.Hash{}) {
297-
if err := tr.TryDelete(key[:]); err != nil {
297+
if err := tr.TryDeleteStorage(s.address, key[:]); err != nil {
298298
s.db.setError(err)
299299
return nil, err
300300
}
301301
s.db.StorageDeleted += 1
302302
} else {
303303
// Encoding []byte cannot fail, ok to ignore the error.
304304
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:]))
305-
if err := tr.TryUpdate(key[:], v); err != nil {
305+
if err := tr.TryUpdateStorage(s.address, key[:], v); err != nil {
306306
s.db.setError(err)
307307
return nil, err
308308
}

core/state/statedb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
871871
addressesToPrefetch = append(addressesToPrefetch, common.CopyBytes(addr[:])) // Copy needed for closure
872872
}
873873
if s.prefetcher != nil && len(addressesToPrefetch) > 0 {
874-
s.prefetcher.prefetch(common.Hash{}, s.originalRoot, addressesToPrefetch)
874+
s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, addressesToPrefetch)
875875
}
876876
// Invalidate journal because reverting across transactions is not allowed.
877877
s.clearJournalAndRefund()

core/state/trie_prefetcher.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (p *triePrefetcher) copy() *triePrefetcher {
141141
}
142142

143143
// prefetch schedules a batch of trie items to prefetch.
144-
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, keys [][]byte) {
144+
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte) {
145145
// If the prefetcher is an inactive one, bail out
146146
if p.fetches != nil {
147147
return
@@ -150,7 +150,7 @@ func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, keys [][]
150150
id := p.trieID(owner, root)
151151
fetcher := p.fetchers[id]
152152
if fetcher == nil {
153-
fetcher = newSubfetcher(p.db, p.root, owner, root)
153+
fetcher = newSubfetcher(p.db, p.root, owner, root, addr)
154154
p.fetchers[id] = fetcher
155155
}
156156
fetcher.schedule(keys)
@@ -205,11 +205,12 @@ func (p *triePrefetcher) trieID(owner common.Hash, root common.Hash) string {
205205
// main prefetcher is paused and either all requested items are processed or if
206206
// the trie being worked on is retrieved from the prefetcher.
207207
type subfetcher struct {
208-
db Database // Database to load trie nodes through
209-
state common.Hash // Root hash of the state to prefetch
210-
owner common.Hash // Owner of the trie, usually account hash
211-
root common.Hash // Root hash of the trie to prefetch
212-
trie Trie // Trie being populated with nodes
208+
db Database // Database to load trie nodes through
209+
state common.Hash // Root hash of the state to prefetch
210+
owner common.Hash // Owner of the trie, usually account hash
211+
root common.Hash // Root hash of the trie to prefetch
212+
addr common.Address // Address of the account that the trie belongs to
213+
trie Trie // Trie being populated with nodes
213214

214215
tasks [][]byte // Items queued up for retrieval
215216
lock sync.Mutex // Lock protecting the task queue
@@ -226,12 +227,13 @@ type subfetcher struct {
226227

227228
// newSubfetcher creates a goroutine to prefetch state items belonging to a
228229
// particular root hash.
229-
func newSubfetcher(db Database, state common.Hash, owner common.Hash, root common.Hash) *subfetcher {
230+
func newSubfetcher(db Database, state common.Hash, owner common.Hash, root common.Hash, addr common.Address) *subfetcher {
230231
sf := &subfetcher{
231232
db: db,
232233
state: state,
233234
owner: owner,
234235
root: root,
236+
addr: addr,
235237
wake: make(chan struct{}, 1),
236238
stop: make(chan struct{}),
237239
term: make(chan struct{}),
@@ -336,7 +338,11 @@ func (sf *subfetcher) loop() {
336338
if _, ok := sf.seen[string(task)]; ok {
337339
sf.dups++
338340
} else {
339-
sf.trie.TryGet(task)
341+
if len(task) == common.AddressLength {
342+
sf.trie.TryGetAccount(common.BytesToAddress(task))
343+
} else {
344+
sf.trie.TryGetStorage(sf.addr, task)
345+
}
340346
sf.seen[string(task)] = struct{}{}
341347
}
342348
}

core/state/trie_prefetcher_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,19 @@ func TestCopyAndClose(t *testing.T) {
4747
db := filledStateDB()
4848
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
4949
skey := common.HexToHash("aaa")
50-
prefetcher.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
51-
prefetcher.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
50+
prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
51+
prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
5252
time.Sleep(1 * time.Second)
5353
a := prefetcher.trie(common.Hash{}, db.originalRoot)
54-
prefetcher.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
54+
prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
5555
b := prefetcher.trie(common.Hash{}, db.originalRoot)
5656
cpy := prefetcher.copy()
57-
cpy.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
58-
cpy.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
57+
cpy.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
58+
cpy.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
5959
c := cpy.trie(common.Hash{}, db.originalRoot)
6060
prefetcher.close()
6161
cpy2 := cpy.copy()
62-
cpy2.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
62+
cpy2.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
6363
d := cpy2.trie(common.Hash{}, db.originalRoot)
6464
cpy.close()
6565
cpy2.close()
@@ -72,7 +72,7 @@ func TestUseAfterClose(t *testing.T) {
7272
db := filledStateDB()
7373
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
7474
skey := common.HexToHash("aaa")
75-
prefetcher.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
75+
prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
7676
a := prefetcher.trie(common.Hash{}, db.originalRoot)
7777
prefetcher.close()
7878
b := prefetcher.trie(common.Hash{}, db.originalRoot)
@@ -88,7 +88,7 @@ func TestCopyClose(t *testing.T) {
8888
db := filledStateDB()
8989
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
9090
skey := common.HexToHash("aaa")
91-
prefetcher.prefetch(common.Hash{}, db.originalRoot, [][]byte{skey.Bytes()})
91+
prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()})
9292
cpy := prefetcher.copy()
9393
a := prefetcher.trie(common.Hash{}, db.originalRoot)
9494
b := cpy.trie(common.Hash{}, db.originalRoot)

light/trie.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ type odrTrie struct {
105105
trie *trie.Trie
106106
}
107107

108-
func (t *odrTrie) TryGet(key []byte) ([]byte, error) {
108+
func (t *odrTrie) TryGetStorage(_ common.Address, key []byte) ([]byte, error) {
109109
key = crypto.Keccak256(key)
110110
var res []byte
111111
err := t.do(key, func() (err error) {
@@ -142,14 +142,14 @@ func (t *odrTrie) TryUpdateAccount(address common.Address, acc *types.StateAccou
142142
})
143143
}
144144

145-
func (t *odrTrie) TryUpdate(key, value []byte) error {
145+
func (t *odrTrie) TryUpdateStorage(_ common.Address, key, value []byte) error {
146146
key = crypto.Keccak256(key)
147147
return t.do(key, func() error {
148148
return t.trie.TryUpdate(key, value)
149149
})
150150
}
151151

152-
func (t *odrTrie) TryDelete(key []byte) error {
152+
func (t *odrTrie) TryDeleteStorage(_ common.Address, key []byte) error {
153153
key = crypto.Keccak256(key)
154154
return t.do(key, func() error {
155155
return t.trie.TryDelete(key)

trie/secure_trie.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func NewStateTrie(id *ID, db *Database) (*StateTrie, error) {
7575
// Get returns the value for key stored in the trie.
7676
// The value bytes must not be modified by the caller.
7777
func (t *StateTrie) Get(key []byte) []byte {
78-
res, err := t.TryGet(key)
78+
res, err := t.TryGetStorage(common.Address{}, key)
7979
if err != nil {
8080
log.Error("Unhandled trie error in StateTrie.Get", "err", err)
8181
}
@@ -86,7 +86,7 @@ func (t *StateTrie) Get(key []byte) []byte {
8686
// The value bytes must not be modified by the caller.
8787
// If the specified node is not in the trie, nil will be returned.
8888
// If a trie node is not found in the database, a MissingNodeError is returned.
89-
func (t *StateTrie) TryGet(key []byte) ([]byte, error) {
89+
func (t *StateTrie) TryGetStorage(_ common.Address, key []byte) ([]byte, error) {
9090
return t.trie.TryGet(t.hashKey(key))
9191
}
9292

@@ -131,7 +131,7 @@ func (t *StateTrie) TryGetNode(path []byte) ([]byte, int, error) {
131131
// The value bytes must not be modified by the caller while they are
132132
// stored in the trie.
133133
func (t *StateTrie) Update(key, value []byte) {
134-
if err := t.TryUpdate(key, value); err != nil {
134+
if err := t.TryUpdateStorage(common.Address{}, key, value); err != nil {
135135
log.Error("Unhandled trie error in StateTrie.Update", "err", err)
136136
}
137137
}
@@ -144,7 +144,7 @@ func (t *StateTrie) Update(key, value []byte) {
144144
// stored in the trie.
145145
//
146146
// If a node is not found in the database, a MissingNodeError is returned.
147-
func (t *StateTrie) TryUpdate(key, value []byte) error {
147+
func (t *StateTrie) TryUpdateStorage(_ common.Address, key, value []byte) error {
148148
hk := t.hashKey(key)
149149
err := t.trie.TryUpdate(hk, value)
150150
if err != nil {
@@ -171,15 +171,15 @@ func (t *StateTrie) TryUpdateAccount(address common.Address, acc *types.StateAcc
171171

172172
// Delete removes any existing value for key from the trie.
173173
func (t *StateTrie) Delete(key []byte) {
174-
if err := t.TryDelete(key); err != nil {
174+
if err := t.TryDeleteStorage(common.Address{}, key); err != nil {
175175
log.Error("Unhandled trie error in StateTrie.Delete", "err", err)
176176
}
177177
}
178178

179179
// TryDelete removes any existing value for key from the trie.
180180
// If the specified trie node is not in the trie, nothing will be changed.
181181
// If a node is not found in the database, a MissingNodeError is returned.
182-
func (t *StateTrie) TryDelete(key []byte) error {
182+
func (t *StateTrie) TryDeleteStorage(_ common.Address, key []byte) error {
183183
hk := t.hashKey(key)
184184
delete(t.getSecKeyCache(), string(hk))
185185
return t.trie.TryDelete(hk)

0 commit comments

Comments
 (0)