core/state, triedb/database: refactor state reader (#30712)
Co-authored-by: Martin HS <martin@swende.se>
This commit is contained in:
parent
55fdbb7e7b
commit
74ef47462f
|
@ -186,9 +186,9 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
|
||||||
// is optional and may be partially useful if it's not fully
|
// is optional and may be partially useful if it's not fully
|
||||||
// generated.
|
// generated.
|
||||||
if db.snap != nil {
|
if db.snap != nil {
|
||||||
sr, err := newStateReader(stateRoot, db.snap)
|
snap := db.snap.Snapshot(stateRoot)
|
||||||
if err == nil {
|
if snap != nil {
|
||||||
readers = append(readers, sr) // snap reader is optional
|
readers = append(readers, newStateReader(snap)) // snap reader is optional
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set up the trie reader, which is expected to always be available
|
// Set up the trie reader, which is expected to always be available
|
||||||
|
|
|
@ -21,13 +21,13 @@ import (
|
||||||
"maps"
|
"maps"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/ethereum/go-ethereum/trie/utils"
|
"github.com/ethereum/go-ethereum/trie/utils"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
"github.com/ethereum/go-ethereum/triedb/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reader defines the interface for accessing accounts and storage slots
|
// Reader defines the interface for accessing accounts and storage slots
|
||||||
|
@ -52,23 +52,18 @@ type Reader interface {
|
||||||
Copy() Reader
|
Copy() Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
// stateReader is a wrapper over the state snapshot and implements the Reader
|
// stateReader wraps a database state reader.
|
||||||
// interface. It provides an efficient way to access flat state.
|
|
||||||
type stateReader struct {
|
type stateReader struct {
|
||||||
snap snapshot.Snapshot
|
reader database.StateReader
|
||||||
buff crypto.KeccakState
|
buff crypto.KeccakState
|
||||||
}
|
}
|
||||||
|
|
||||||
// newStateReader constructs a flat state reader with on the specified state root.
|
// newStateReader constructs a state reader with on the given state root.
|
||||||
func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error) {
|
func newStateReader(reader database.StateReader) *stateReader {
|
||||||
snap := snaps.Snapshot(root)
|
|
||||||
if snap == nil {
|
|
||||||
return nil, errors.New("snapshot is not available")
|
|
||||||
}
|
|
||||||
return &stateReader{
|
return &stateReader{
|
||||||
snap: snap,
|
reader: reader,
|
||||||
buff: crypto.NewKeccakState(),
|
buff: crypto.NewKeccakState(),
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account implements Reader, retrieving the account specified by the address.
|
// Account implements Reader, retrieving the account specified by the address.
|
||||||
|
@ -78,18 +73,18 @@ func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error
|
||||||
//
|
//
|
||||||
// The returned account might be nil if it's not existent.
|
// The returned account might be nil if it's not existent.
|
||||||
func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) {
|
func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
ret, err := r.snap.Account(crypto.HashData(r.buff, addr.Bytes()))
|
account, err := r.reader.Account(crypto.HashData(r.buff, addr.Bytes()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if ret == nil {
|
if account == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
acct := &types.StateAccount{
|
acct := &types.StateAccount{
|
||||||
Nonce: ret.Nonce,
|
Nonce: account.Nonce,
|
||||||
Balance: ret.Balance,
|
Balance: account.Balance,
|
||||||
CodeHash: ret.CodeHash,
|
CodeHash: account.CodeHash,
|
||||||
Root: common.BytesToHash(ret.Root),
|
Root: common.BytesToHash(account.Root),
|
||||||
}
|
}
|
||||||
if len(acct.CodeHash) == 0 {
|
if len(acct.CodeHash) == 0 {
|
||||||
acct.CodeHash = types.EmptyCodeHash.Bytes()
|
acct.CodeHash = types.EmptyCodeHash.Bytes()
|
||||||
|
@ -110,7 +105,7 @@ func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error)
|
||||||
func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||||
addrHash := crypto.HashData(r.buff, addr.Bytes())
|
addrHash := crypto.HashData(r.buff, addr.Bytes())
|
||||||
slotHash := crypto.HashData(r.buff, key.Bytes())
|
slotHash := crypto.HashData(r.buff, key.Bytes())
|
||||||
ret, err := r.snap.Storage(addrHash, slotHash)
|
ret, err := r.reader.Storage(addrHash, slotHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
@ -131,8 +126,8 @@ func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash
|
||||||
// Copy implements Reader, returning a deep-copied snap reader.
|
// Copy implements Reader, returning a deep-copied snap reader.
|
||||||
func (r *stateReader) Copy() Reader {
|
func (r *stateReader) Copy() Reader {
|
||||||
return &stateReader{
|
return &stateReader{
|
||||||
snap: r.snap,
|
reader: r.reader,
|
||||||
buff: crypto.NewKeccakState(),
|
buff: crypto.NewKeccakState(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeReader wraps the Node method of a backing trie reader.
|
// NodeReader wraps the Node method of a backing trie reader.
|
||||||
|
@ -37,3 +38,31 @@ type NodeDatabase interface {
|
||||||
// An error will be returned if the specified state is not available.
|
// An error will be returned if the specified state is not available.
|
||||||
NodeReader(stateRoot common.Hash) (NodeReader, error)
|
NodeReader(stateRoot common.Hash) (NodeReader, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StateReader wraps the Account and Storage method of a backing state reader.
|
||||||
|
type StateReader interface {
|
||||||
|
// Account directly retrieves the account associated with a particular hash in
|
||||||
|
// the slim data format. An error will be returned if the read operation exits
|
||||||
|
// abnormally. Specifically, if the layer is already stale.
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// - the returned account object is safe to modify
|
||||||
|
// - no error will be returned if the requested account is not found in database
|
||||||
|
Account(hash common.Hash) (*types.SlimAccount, error)
|
||||||
|
|
||||||
|
// Storage directly retrieves the storage data associated with a particular hash,
|
||||||
|
// within a particular account. An error will be returned if the read operation
|
||||||
|
// exits abnormally.
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// - the returned storage data is not a copy, please don't modify it
|
||||||
|
// - no error will be returned if the requested slot is not found in database
|
||||||
|
Storage(accountHash, storageHash common.Hash) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateDatabase wraps the methods of a backing state store.
|
||||||
|
type StateDatabase interface {
|
||||||
|
// StateReader returns a state reader associated with the specific state.
|
||||||
|
// An error will be returned if the specified state is not available.
|
||||||
|
StateReader(stateRoot common.Hash) (StateReader, error)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue