Skip to content

Commit 128e8ac

Browse files
rjl493456442holiman
authored andcommitted
core/state, triedb/database: refactor state reader (ethereum#30712)
Co-authored-by: Martin HS <[email protected]>
1 parent 3f5ffee commit 128e8ac

File tree

3 files changed

+50
-26
lines changed

3 files changed

+50
-26
lines changed

core/state/database.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,9 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
186186
// is optional and may be partially useful if it's not fully
187187
// generated.
188188
if db.snap != nil {
189-
sr, err := newStateReader(stateRoot, db.snap)
190-
if err == nil {
191-
readers = append(readers, sr) // snap reader is optional
189+
snap := db.snap.Snapshot(stateRoot)
190+
if snap != nil {
191+
readers = append(readers, newStateReader(snap)) // snap reader is optional
192192
}
193193
}
194194
// Set up the trie reader, which is expected to always be available

core/state/reader.go

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ import (
2121
"maps"
2222

2323
"github.com/ethereum/go-ethereum/common"
24-
"github.com/ethereum/go-ethereum/core/state/snapshot"
2524
"github.com/ethereum/go-ethereum/core/types"
2625
"github.com/ethereum/go-ethereum/crypto"
2726
"github.com/ethereum/go-ethereum/rlp"
2827
"github.com/ethereum/go-ethereum/trie"
2928
"github.com/ethereum/go-ethereum/trie/utils"
3029
"github.com/ethereum/go-ethereum/triedb"
30+
"github.com/ethereum/go-ethereum/triedb/database"
3131
)
3232

3333
// Reader defines the interface for accessing accounts and storage slots
@@ -52,23 +52,18 @@ type Reader interface {
5252
Copy() Reader
5353
}
5454

55-
// stateReader is a wrapper over the state snapshot and implements the Reader
56-
// interface. It provides an efficient way to access flat state.
55+
// stateReader wraps a database state reader.
5756
type stateReader struct {
58-
snap snapshot.Snapshot
59-
buff crypto.KeccakState
57+
reader database.StateReader
58+
buff crypto.KeccakState
6059
}
6160

62-
// newStateReader constructs a flat state reader with on the specified state root.
63-
func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error) {
64-
snap := snaps.Snapshot(root)
65-
if snap == nil {
66-
return nil, errors.New("snapshot is not available")
67-
}
61+
// newStateReader constructs a state reader with on the given state root.
62+
func newStateReader(reader database.StateReader) *stateReader {
6863
return &stateReader{
69-
snap: snap,
70-
buff: crypto.NewKeccakState(),
71-
}, nil
64+
reader: reader,
65+
buff: crypto.NewKeccakState(),
66+
}
7267
}
7368

7469
// Account implements Reader, retrieving the account specified by the address.
@@ -78,18 +73,18 @@ func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error
7873
//
7974
// The returned account might be nil if it's not existent.
8075
func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) {
81-
ret, err := r.snap.Account(crypto.HashData(r.buff, addr.Bytes()))
76+
account, err := r.reader.Account(crypto.HashData(r.buff, addr.Bytes()))
8277
if err != nil {
8378
return nil, err
8479
}
85-
if ret == nil {
80+
if account == nil {
8681
return nil, nil
8782
}
8883
acct := &types.StateAccount{
89-
Nonce: ret.Nonce,
90-
Balance: ret.Balance,
91-
CodeHash: ret.CodeHash,
92-
Root: common.BytesToHash(ret.Root),
84+
Nonce: account.Nonce,
85+
Balance: account.Balance,
86+
CodeHash: account.CodeHash,
87+
Root: common.BytesToHash(account.Root),
9388
}
9489
if len(acct.CodeHash) == 0 {
9590
acct.CodeHash = types.EmptyCodeHash.Bytes()
@@ -110,7 +105,7 @@ func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error)
110105
func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
111106
addrHash := crypto.HashData(r.buff, addr.Bytes())
112107
slotHash := crypto.HashData(r.buff, key.Bytes())
113-
ret, err := r.snap.Storage(addrHash, slotHash)
108+
ret, err := r.reader.Storage(addrHash, slotHash)
114109
if err != nil {
115110
return common.Hash{}, err
116111
}
@@ -131,8 +126,8 @@ func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash
131126
// Copy implements Reader, returning a deep-copied snap reader.
132127
func (r *stateReader) Copy() Reader {
133128
return &stateReader{
134-
snap: r.snap,
135-
buff: crypto.NewKeccakState(),
129+
reader: r.reader,
130+
buff: crypto.NewKeccakState(),
136131
}
137132
}
138133

triedb/database/database.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package database
1818

1919
import (
2020
"github.com/ethereum/go-ethereum/common"
21+
"github.com/ethereum/go-ethereum/core/types"
2122
)
2223

2324
// NodeReader wraps the Node method of a backing trie reader.
@@ -37,3 +38,31 @@ type NodeDatabase interface {
3738
// An error will be returned if the specified state is not available.
3839
NodeReader(stateRoot common.Hash) (NodeReader, error)
3940
}
41+
42+
// StateReader wraps the Account and Storage method of a backing state reader.
43+
type StateReader interface {
44+
// Account directly retrieves the account associated with a particular hash in
45+
// the slim data format. An error will be returned if the read operation exits
46+
// abnormally. Specifically, if the layer is already stale.
47+
//
48+
// Note:
49+
// - the returned account object is safe to modify
50+
// - no error will be returned if the requested account is not found in database
51+
Account(hash common.Hash) (*types.SlimAccount, error)
52+
53+
// Storage directly retrieves the storage data associated with a particular hash,
54+
// within a particular account. An error will be returned if the read operation
55+
// exits abnormally.
56+
//
57+
// Note:
58+
// - the returned storage data is not a copy, please don't modify it
59+
// - no error will be returned if the requested slot is not found in database
60+
Storage(accountHash, storageHash common.Hash) ([]byte, error)
61+
}
62+
63+
// StateDatabase wraps the methods of a backing state store.
64+
type StateDatabase interface {
65+
// StateReader returns a state reader associated with the specific state.
66+
// An error will be returned if the specified state is not available.
67+
StateReader(stateRoot common.Hash) (StateReader, error)
68+
}

0 commit comments

Comments
 (0)