mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
fix: bal prefetcher empty account bug caused by merging 7702 code
This commit is contained in:
parent
86a72911a7
commit
af087d0581
6 changed files with 43 additions and 101 deletions
|
|
@ -47,7 +47,6 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn
|
||||||
mgasps = float64(st.usedGas) * 1000 / float64(elapsed)
|
mgasps = float64(st.usedGas) * 1000 / float64(elapsed)
|
||||||
)
|
)
|
||||||
// Update the Mgas per second gauge
|
// Update the Mgas per second gauge
|
||||||
chainMgaspsGauge.Update(int64(mgasps))
|
|
||||||
mgaspsHist.Update(int64(mgasps))
|
mgaspsHist.Update(int64(mgasps))
|
||||||
|
|
||||||
// If we're at the last block of the batch or report period reached, log
|
// If we're at the last block of the batch or report period reached, log
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ func (s *SequentialPrestateProvider) PrestateAtIndex(i int) (*state.StateDB, err
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
|
|
||||||
_, err = ApplyTransactionWithEVM(msg, s.gp, statedb, blockNumber, blockHash, tx, s.usedGas, s.evm)
|
_, err = ApplyTransactionWithEVM(msg, s.gp, statedb, blockNumber, blockHash, s.block.Time(), tx, s.usedGas, s.evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ func (p *ParallelStateProcessor) executeParallel(block *types.Block, statedb *st
|
||||||
}
|
}
|
||||||
// todo: handle gp race
|
// todo: handle gp race
|
||||||
gpcp := *gp
|
gpcp := *gp
|
||||||
receipt, entries, err := ApplyTransactionWithParallelEVM(msg, &gpcp, cleanStatedb, blockNumber, blockHash, tx, usedGas, evm)
|
receipt, entries, err := ApplyTransactionWithParallelEVM(msg, &gpcp, cleanStatedb, blockNumber, blockHash, block.Time(), tx, usedGas, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -234,8 +234,7 @@ func (p *ParallelStateProcessor) executeParallel(block *types.Block, statedb *st
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read requests if Prague is enabled.
|
// Read requests if Prague is enabled.
|
||||||
// commented out EIP-7002, EIP-7251 and p.chain.engine.Finalize for now, since statedb might cause concurrent map writes (journal.go:211) when postState = statedb.Copy()
|
|
||||||
// evm := vm.NewEVM(context, statedb, p.config, cfg)
|
|
||||||
var requests [][]byte
|
var requests [][]byte
|
||||||
if p.config.IsPrague(block.Number(), block.Time()) {
|
if p.config.IsPrague(block.Number(), block.Time()) {
|
||||||
requests = [][]byte{}
|
requests = [][]byte{}
|
||||||
|
|
@ -243,18 +242,25 @@ func (p *ParallelStateProcessor) executeParallel(block *types.Block, statedb *st
|
||||||
if err := ParseDepositLogs(&requests, allLogs, p.config); err != nil {
|
if err := ParseDepositLogs(&requests, allLogs, p.config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Commented out EIP-7002, EIP-7251 and p.chain.engine.Finalize for now, since statedb might cause concurrent map writes (journal.go:211) when postState = statedb.Copy()
|
||||||
|
if preStateType == SeqPreState {
|
||||||
|
evm := vm.NewEVM(context, statedb, p.config, cfg)
|
||||||
// // EIP-7002
|
// // EIP-7002
|
||||||
// if err := ProcessWithdrawalQueue(&requests, evm); err != nil {
|
if err := ProcessWithdrawalQueue(&requests, evm); err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
// // EIP-7251
|
// // EIP-7251
|
||||||
// if err := ProcessConsolidationQueue(&requests, evm); err != nil {
|
if err := ProcessConsolidationQueue(&requests, evm); err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||||
// p.chain.engine.Finalize(p.chain, header, statedb, block.Body())
|
if preStateType == SeqPreState {
|
||||||
|
p.chain.engine.Finalize(p.chain, header, statedb, block.Body())
|
||||||
|
}
|
||||||
|
|
||||||
return &ProcessResult{
|
return &ProcessResult{
|
||||||
Receipts: receipts,
|
Receipts: receipts,
|
||||||
|
|
@ -264,7 +270,7 @@ func (p *ParallelStateProcessor) executeParallel(block *types.Block, statedb *st
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyTransactionWithParallelEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, entries []state.JournalEntry, err error) {
|
func ApplyTransactionWithParallelEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, blockTime uint64, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, entries []state.JournalEntry, err error) {
|
||||||
if hooks := evm.Config.Tracer; hooks != nil {
|
if hooks := evm.Config.Tracer; hooks != nil {
|
||||||
if hooks.OnTxStart != nil {
|
if hooks.OnTxStart != nil {
|
||||||
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
|
|
@ -295,5 +301,5 @@ func ApplyTransactionWithParallelEVM(msg *Message, gp *GasPool, statedb *state.S
|
||||||
statedb.AccessEvents().Merge(evm.AccessEvents)
|
statedb.AccessEvents().Merge(evm.AccessEvents)
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), entries, nil
|
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, blockTime, tx, *usedGas, root), entries, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,6 @@ type StateReader interface {
|
||||||
// - Returns an error only if an unexpected issue occurs
|
// - Returns an error only if an unexpected issue occurs
|
||||||
// - The returned storage slot is safe to modify after the call
|
// - The returned storage slot is safe to modify after the call
|
||||||
Storage(addr common.Address, slot common.Hash) (common.Hash, error)
|
Storage(addr common.Address, slot common.Hash) (common.Hash, error)
|
||||||
|
|
||||||
AccountBAL(addr common.Address) (*types.StateAccount, error)
|
|
||||||
StorageBAL(addr common.Address, slot common.Hash) (common.Hash, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reader defines the interface for accessing accounts, storage slots and contract
|
// Reader defines the interface for accessing accounts, storage slots and contract
|
||||||
|
|
@ -191,10 +188,6 @@ func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
return acct, nil
|
return acct, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *flatReader) AccountBAL(addr common.Address) (*types.StateAccount, error) {
|
|
||||||
return r.Account(addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage implements StateReader, retrieving the storage slot specified by the
|
// Storage implements StateReader, retrieving the storage slot specified by the
|
||||||
// address and slot key.
|
// address and slot key.
|
||||||
//
|
//
|
||||||
|
|
@ -223,10 +216,6 @@ func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash,
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *flatReader) StorageBAL(addr common.Address, key common.Hash) (common.Hash, error) {
|
|
||||||
return r.Storage(addr, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// trieReader implements the StateReader interface, providing functions to access
|
// trieReader implements the StateReader interface, providing functions to access
|
||||||
// state from the referenced trie.
|
// state from the referenced trie.
|
||||||
//
|
//
|
||||||
|
|
@ -293,14 +282,6 @@ func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
return r.account(addr)
|
return r.account(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *trieReader) AccountBAL(addr common.Address) (*types.StateAccount, error) {
|
|
||||||
account, err := r.mainTrie.GetAccount(addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return account, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage implements StateReader, retrieving the storage slot specified by the
|
// Storage implements StateReader, retrieving the storage slot specified by the
|
||||||
// address and slot key.
|
// address and slot key.
|
||||||
//
|
//
|
||||||
|
|
@ -347,10 +328,6 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash,
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *trieReader) StorageBAL(addr common.Address, key common.Hash) (common.Hash, error) {
|
|
||||||
return r.Storage(addr, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// multiStateReader is the aggregation of a list of StateReader interface,
|
// multiStateReader is the aggregation of a list of StateReader interface,
|
||||||
// providing state access by leveraging all readers. The checking priority
|
// providing state access by leveraging all readers. The checking priority
|
||||||
// is determined by the position in the reader list.
|
// is determined by the position in the reader list.
|
||||||
|
|
@ -391,24 +368,6 @@ func (r *multiStateReader) Account(addr common.Address) (*types.StateAccount, er
|
||||||
return nil, errors.Join(errs...)
|
return nil, errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *multiStateReader) AccountBAL(addr common.Address) (*types.StateAccount, error) {
|
|
||||||
var errs []error
|
|
||||||
for _, reader := range r.readers {
|
|
||||||
switch reader.(type) {
|
|
||||||
case *flatReader:
|
|
||||||
{
|
|
||||||
acct, err := reader.AccountBAL(addr)
|
|
||||||
if err == nil {
|
|
||||||
return acct, nil
|
|
||||||
}
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errs = append(errs, errors.New("no flatReader"))
|
|
||||||
return nil, errors.Join(errs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage implementing StateReader interface, retrieving the storage slot
|
// Storage implementing StateReader interface, retrieving the storage slot
|
||||||
// associated with a particular account address and slot key.
|
// associated with a particular account address and slot key.
|
||||||
//
|
//
|
||||||
|
|
@ -427,24 +386,6 @@ func (r *multiStateReader) Storage(addr common.Address, slot common.Hash) (commo
|
||||||
return common.Hash{}, errors.Join(errs...)
|
return common.Hash{}, errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *multiStateReader) StorageBAL(addr common.Address, slot common.Hash) (common.Hash, error) {
|
|
||||||
var errs []error
|
|
||||||
for _, reader := range r.readers {
|
|
||||||
switch reader.(type) {
|
|
||||||
case *flatReader:
|
|
||||||
{
|
|
||||||
slot, err := reader.Storage(addr, slot)
|
|
||||||
if err == nil {
|
|
||||||
return slot, nil
|
|
||||||
}
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errs = append(errs, errors.New("no flatReader"))
|
|
||||||
return common.Hash{}, errors.Join(errs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// reader is the wrapper of ContractCodeReader and StateReader interface.
|
// reader is the wrapper of ContractCodeReader and StateReader interface.
|
||||||
type reader struct {
|
type reader struct {
|
||||||
ContractCodeReader
|
ContractCodeReader
|
||||||
|
|
@ -690,6 +631,9 @@ func (r *readerWithBAL) Account(addr common.Address) (*types.StateAccount, error
|
||||||
acct, err := r.Reader.Account(addr)
|
acct, err := r.Reader.Account(addr)
|
||||||
if acct == nil || err != nil {
|
if acct == nil || err != nil {
|
||||||
// acct is nil, just return the postAcct
|
// acct is nil, just return the postAcct
|
||||||
|
if acctVal.Nonce == 0 && acctVal.Balance == nil && len(acctVal.Code) == 0 {
|
||||||
|
return nil, fmt.Errorf("account not exist")
|
||||||
|
}
|
||||||
return &types.StateAccount{
|
return &types.StateAccount{
|
||||||
Nonce: acctVal.Nonce,
|
Nonce: acctVal.Nonce,
|
||||||
Balance: acctVal.Balance,
|
Balance: acctVal.Balance,
|
||||||
|
|
|
||||||
|
|
@ -249,8 +249,13 @@ func New(root common.Hash, db Database) (*StateDB, error) {
|
||||||
// NewWithReader creates a new state for the specified state root. Unlike New,
|
// NewWithReader creates a new state for the specified state root. Unlike New,
|
||||||
// this function accepts an additional Reader which is bound to the given root.
|
// this function accepts an additional Reader which is bound to the given root.
|
||||||
func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, error) {
|
func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, error) {
|
||||||
|
tr, err := db.OpenTrie(root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
sdb := &StateDB{
|
sdb := &StateDB{
|
||||||
db: db,
|
db: db,
|
||||||
|
trie: tr,
|
||||||
originalRoot: root,
|
originalRoot: root,
|
||||||
reader: reader,
|
reader: reader,
|
||||||
stateObjects: make(map[common.Address]*stateObject),
|
stateObjects: make(map[common.Address]*stateObject),
|
||||||
|
|
@ -373,18 +378,17 @@ func (s *StateDB) prefetchBalPreblockKeys() {
|
||||||
lenMaxSlots += len(acl.StorageKeys)
|
lenMaxSlots += len(acl.StorageKeys)
|
||||||
|
|
||||||
workers.Go(func() error {
|
workers.Go(func() error {
|
||||||
acctBal, err := s.reader.AccountBAL(addr)
|
acctBal, err := s.reader.Account(addr)
|
||||||
var obj *stateObject
|
var obj *stateObject
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("fail to fetch account from BALs:", addr)
|
log.Error("fail to fetch account from BALs:", addr)
|
||||||
acct, err := s.reader.Account(addr)
|
|
||||||
if err != nil {
|
|
||||||
panic("fail to fetch account from BALs")
|
panic("fail to fetch account from BALs")
|
||||||
}
|
|
||||||
obj = newObject(s, addr, acct)
|
|
||||||
} else {
|
} else {
|
||||||
|
// If obj is nil, we shouldn't newObject, it will cause invalid gas used error. Because 7702 will use Exist(addr) to decide where an account exists, which should be false if account is nil, but if we newObject it'll be true.
|
||||||
|
if acctBal != nil {
|
||||||
obj = newObject(s, addr, acctBal)
|
obj = newObject(s, addr, acctBal)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
accounts <- obj
|
accounts <- obj
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
@ -393,9 +397,11 @@ func (s *StateDB) prefetchBalPreblockKeys() {
|
||||||
|
|
||||||
for range len(preBal) {
|
for range len(preBal) {
|
||||||
obj := <-accounts
|
obj := <-accounts
|
||||||
// must set it first to avoid accounts read later in storageBAL fetching
|
// must set it first to avoid accounts read later in storage fetching
|
||||||
|
if obj != nil {
|
||||||
s.setStateObject(obj)
|
s.setStateObject(obj)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
close(accounts)
|
close(accounts)
|
||||||
|
|
||||||
|
|
@ -407,7 +413,7 @@ func (s *StateDB) prefetchBalPreblockKeys() {
|
||||||
|
|
||||||
obj := s.stateObjects[addr]
|
obj := s.stateObjects[addr]
|
||||||
|
|
||||||
if obj.origin == nil {
|
if obj == nil || obj.origin == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,17 +421,12 @@ func (s *StateDB) prefetchBalPreblockKeys() {
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
workers.Go(func() error {
|
workers.Go(func() error {
|
||||||
val, err := s.reader.StorageBAL(addr, key)
|
val, err := s.reader.Storage(addr, key)
|
||||||
kv := &StorageKV{&addr, &key, &val}
|
kv := &StorageKV{&addr, &key, &val}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("fail to fetch storage from BALs:", addr, key)
|
log.Error("fail to fetch storage from BALs:", addr, key)
|
||||||
// It's not safe to concurrent read from trie with StorageBAL, so we use the locked version Storage as fallback
|
|
||||||
val, err := s.reader.Storage(addr, key)
|
|
||||||
if err != nil {
|
|
||||||
panic("fail to fetch storage from BALs")
|
panic("fail to fetch storage from BALs")
|
||||||
}
|
}
|
||||||
kv.val = &val
|
|
||||||
}
|
|
||||||
storages <- kv
|
storages <- kv
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// All states must has been cachae to statedb.
|
// All states must has been cached to statedb.
|
||||||
func (s *StateDB) Account(addr common.Address) (*types.StateAccount, error) {
|
func (s *StateDB) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
// s.getStateObject() shouldn't be used, cause when acct is nil, it'll load account from DB and result concurrent map writes for accts
|
// s.getStateObject() shouldn't be used, cause when acct is nil, it'll load account from DB and result concurrent map writes for accts
|
||||||
obj := s.stateObjects[addr]
|
obj := s.stateObjects[addr]
|
||||||
|
|
@ -34,11 +34,3 @@ func (s *StateDB) Storage(addr common.Address, slot common.Hash) (common.Hash, e
|
||||||
}
|
}
|
||||||
return common.Hash{}, nil
|
return common.Hash{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) AccountBAL(addr common.Address) (*types.StateAccount, error) {
|
|
||||||
panic("AccountBAL not implemented for statedb")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateDB) StorageBAL(addr common.Address, slot common.Hash) (common.Hash, error) {
|
|
||||||
panic("StorageBAL not implemented for statedb")
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue