fix: need to pass block_hash to StateObject and Database
This commit is contained in:
parent
ede0af3c26
commit
6b25cde9dd
28
database.go
28
database.go
@ -5,14 +5,10 @@ import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/VictoriaMetrics/fastcache"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/jackc/pgx/pgxpool"
|
||||
)
|
||||
@ -35,29 +31,29 @@ var (
|
||||
type Database interface {
|
||||
ContractCode(addrHash common.Hash, codeHash common.Hash) ([]byte, error)
|
||||
ContractCodeSize(addrHash common.Hash, codeHash common.Hash) (int, error)
|
||||
StateAccount(address common.Address) (*types.StateAccount, error)
|
||||
StorageSlot(addressHash, slotHash common.Hash) ([]byte, error)
|
||||
StateAccount(addressHash, blockHash common.Hash) (*types.StateAccount, error)
|
||||
StorageValue(addressHash, slotHash, blockHash common.Hash) ([]byte, error)
|
||||
}
|
||||
|
||||
var _ Database = &stateDatabase{}
|
||||
|
||||
type stateDatabase struct {
|
||||
pgdb *pgxpool.Pool
|
||||
trieDB *trie.Database
|
||||
codeSizeCache *lru.Cache
|
||||
codeCache *fastcache.Cache
|
||||
}
|
||||
|
||||
func NewStateDatabase(pgdb *pgxpool.Pool, ethdb ethdb.Database, config *trie.Config) (*stateDatabase, error) {
|
||||
// NewStateDatabase returns a new Database implementation using the provided postgres connection pool
|
||||
func NewStateDatabase(pgdb *pgxpool.Pool) (*stateDatabase, error) {
|
||||
csc, _ := lru.New(codeSizeCacheSize)
|
||||
return &stateDatabase{
|
||||
pgdb: pgdb,
|
||||
trieDB: trie.NewDatabaseWithConfig(ethdb, config),
|
||||
codeSizeCache: csc,
|
||||
codeCache: fastcache.New(codeCacheSize),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ContractCode satisfies Database, it returns the contract code for a give codehash
|
||||
func (sd *stateDatabase) ContractCode(_, codeHash common.Hash) ([]byte, error) {
|
||||
if code := sd.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 {
|
||||
return code, nil
|
||||
@ -75,6 +71,7 @@ func (sd *stateDatabase) ContractCode(_, codeHash common.Hash) ([]byte, error) {
|
||||
return nil, errNotFound
|
||||
}
|
||||
|
||||
// ContractCodeSize satisfies Database, it returns the length of the code for a provided codehash
|
||||
func (sd *stateDatabase) ContractCodeSize(_, codeHash common.Hash) (int, error) {
|
||||
if cached, ok := sd.codeSizeCache.Get(codeHash); ok {
|
||||
return cached.(int), nil
|
||||
@ -83,10 +80,11 @@ func (sd *stateDatabase) ContractCodeSize(_, codeHash common.Hash) (int, error)
|
||||
return len(code), err
|
||||
}
|
||||
|
||||
func (sd *stateDatabase) StateAccount(address common.Address) (*types.StateAccount, error) {
|
||||
// StateAccount satisfies Database, it returns the types.StateAccount for a provided address and block hash
|
||||
func (sd *stateDatabase) StateAccount(addressHash, blockHash common.Hash) (*types.StateAccount, error) {
|
||||
res := StateAccountResult{}
|
||||
key := crypto.Keccak256Hash(address.Bytes())
|
||||
if err := sd.pgdb.QueryRow(context.Background(), GetStateAccount, key.Hex()).Scan(&res); err != nil {
|
||||
err := sd.pgdb.QueryRow(context.Background(), GetStateAccount, addressHash.Hex(), blockHash.Hex()).Scan(&res)
|
||||
if err != nil {
|
||||
return nil, errNotFound
|
||||
}
|
||||
if res.Removed {
|
||||
@ -103,9 +101,11 @@ func (sd *stateDatabase) StateAccount(address common.Address) (*types.StateAccou
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (sd *stateDatabase) StorageSlot(addressHash, slotHash common.Hash) ([]byte, error) {
|
||||
// StorageValue satisfies Database, it returns the storage value for the provided address, slot, and block hash
|
||||
func (sd *stateDatabase) StorageValue(addressHash, slotHash, blockHash common.Hash) ([]byte, error) {
|
||||
res := StorageSlotResult{}
|
||||
if err := sd.pgdb.QueryRow(context.Background(), GetStorageSlot, addressHash.Hex(), slotHash.Hex()).Scan(&res); err != nil {
|
||||
err := sd.pgdb.QueryRow(context.Background(), GetStorageSlot, addressHash.Hex(), slotHash.Hex(), blockHash.Hex()).Scan(&res)
|
||||
if err != nil {
|
||||
return nil, errNotFound
|
||||
}
|
||||
if res.Removed {
|
||||
|
3
sql.go
3
sql.go
@ -21,6 +21,9 @@ const (
|
||||
)
|
||||
WHERE state_leaf_key = $1
|
||||
AND storage_leaf_key = $2
|
||||
AND header_cids.block_number <= (SELECT block_number
|
||||
FROM eth.header_cids
|
||||
WHERE block_hash = $3)
|
||||
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
|
||||
ORDER BY header_cids.block_number DESC
|
||||
LIMIT 1`
|
||||
|
@ -54,10 +54,11 @@ func (s Storage) Copy() Storage {
|
||||
// First you need to obtain a state object.
|
||||
// Account values can be accessed and modified through the object.
|
||||
type stateObject struct {
|
||||
address common.Address
|
||||
addrHash common.Hash // hash of ethereum address of the account
|
||||
data types.StateAccount
|
||||
db *StateDB
|
||||
address common.Address
|
||||
addrHash common.Hash // hash of ethereum address of the account
|
||||
blockHash common.Hash // hash of the block this state object exists at or is being applied on top of
|
||||
data types.StateAccount
|
||||
db *StateDB
|
||||
|
||||
// DB error.
|
||||
// State objects are used by the consensus core and VM which are
|
||||
@ -88,7 +89,7 @@ func (s *stateObject) empty() bool {
|
||||
}
|
||||
|
||||
// newObject creates a state object.
|
||||
func newObject(db *StateDB, address common.Address, data types.StateAccount) *stateObject {
|
||||
func newObject(db *StateDB, address common.Address, data types.StateAccount, blockHash common.Hash) *stateObject {
|
||||
if data.Balance == nil {
|
||||
data.Balance = new(big.Int)
|
||||
}
|
||||
@ -102,6 +103,7 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st
|
||||
db: db,
|
||||
address: address,
|
||||
addrHash: crypto.Keccak256Hash(address[:]),
|
||||
blockHash: blockHash,
|
||||
data: data,
|
||||
originStorage: make(Storage),
|
||||
pendingStorage: make(Storage),
|
||||
@ -161,7 +163,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
|
||||
}
|
||||
// If no live objects are available, load from database
|
||||
start := time.Now()
|
||||
enc, err := db.StorageSlot(s.addrHash, key)
|
||||
enc, err := db.StorageValue(s.addrHash, key, s.blockHash)
|
||||
if metrics.EnabledExpensive {
|
||||
s.db.StorageReads += time.Since(start)
|
||||
}
|
||||
|
16
statedb.go
16
statedb.go
@ -50,9 +50,8 @@ type StateDB struct {
|
||||
db Database
|
||||
hasher crypto.KeccakState
|
||||
|
||||
// originalRoot is the pre-state root, before any changes were made.
|
||||
// It will be updated when the Commit is called.
|
||||
originalRoot common.Hash
|
||||
// originBlockHash is the blockhash for the state we are working on top of
|
||||
originBlockHash common.Hash
|
||||
|
||||
snaps *snapshot.Tree
|
||||
snapDestructs map[common.Hash]struct{}
|
||||
@ -110,10 +109,10 @@ type StateDB struct {
|
||||
}
|
||||
|
||||
// New creates a new state from a given trie.
|
||||
func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) {
|
||||
func New(blockHash common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) {
|
||||
sdb := &StateDB{
|
||||
db: db,
|
||||
originalRoot: root,
|
||||
originBlockHash: blockHash,
|
||||
snaps: snaps,
|
||||
stateObjects: make(map[common.Address]*stateObject),
|
||||
stateObjectsPending: make(map[common.Address]struct{}),
|
||||
@ -348,7 +347,8 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
|
||||
// TODO: REPLACE TRIE ACCESS HERE
|
||||
// can add a fallback option to use ipfsethdb to do the trie access if direct access fails
|
||||
start := time.Now()
|
||||
data, err := s.db.StateAccount(addr)
|
||||
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||
data, err := s.db.StateAccount(addrHash, s.originBlockHash)
|
||||
if metrics.EnabledExpensive {
|
||||
s.AccountReads += time.Since(start)
|
||||
}
|
||||
@ -360,7 +360,7 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
|
||||
return nil
|
||||
}
|
||||
// Insert into the live set
|
||||
obj := newObject(s, addr, *data)
|
||||
obj := newObject(s, addr, *data, s.originBlockHash)
|
||||
s.setStateObject(obj)
|
||||
return obj
|
||||
}
|
||||
@ -382,7 +382,7 @@ func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
|
||||
// the given address, it is overwritten and returned as the second return value.
|
||||
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
|
||||
prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that!
|
||||
newobj = newObject(s, addr, types.StateAccount{})
|
||||
newobj = newObject(s, addr, types.StateAccount{}, s.originBlockHash)
|
||||
if prev == nil {
|
||||
s.journal.append(createObjectChange{account: &addr})
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user