Skip to content

Commit

Permalink
Add error returns to inttrablock state (#12926)
Browse files Browse the repository at this point in the history
This PR adds error returns to intrablock state calls so that errors are
consistently returned to the caller code.

Previously several of these where just swallowed by the implementation.

This is necessary for parallel execution processing which needs to be
able to distinguish between retryable errors due to parallel data access
from system and other fails which need to stop processing.

Without this the code goes into a continuous retry of fail loop.
  • Loading branch information
mh0lt authored Dec 1, 2024
1 parent baf0a60 commit a962e99
Show file tree
Hide file tree
Showing 48 changed files with 1,603 additions and 678 deletions.
25 changes: 17 additions & 8 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract libcommon.Addres
}
defer tx.Rollback()
stateDB := b.stateByBlockNumber(tx, blockNumber)
return stateDB.GetCode(contract), nil
return stateDB.GetCode(contract)
}

// BalanceAt returns the wei balance of a certain account in the blockchain.
Expand All @@ -220,7 +220,7 @@ func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract libcommon.Add
}
defer tx.Rollback()
stateDB := b.stateByBlockNumber(tx, blockNumber)
return stateDB.GetBalance(contract), nil
return stateDB.GetBalance(contract)
}

// NonceAt returns the nonce of a certain account in the blockchain.
Expand All @@ -234,7 +234,7 @@ func (b *SimulatedBackend) NonceAt(ctx context.Context, contract libcommon.Addre
defer tx.Rollback()

stateDB := b.stateByBlockNumber(tx, blockNumber)
return stateDB.GetNonce(contract), nil
return stateDB.GetNonce(contract)
}

// StorageAt returns the value of key in the storage of an account in the blockchain.
Expand Down Expand Up @@ -518,7 +518,7 @@ func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract libcommon
b.mu.Lock()
defer b.mu.Unlock()

return b.pendingState.GetCode(contract), nil
return b.pendingState.GetCode(contract)
}

func newRevertError(result *evmtypes.ExecutionResult) *revertError {
Expand Down Expand Up @@ -600,7 +600,7 @@ func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account libcommon
b.mu.Lock()
defer b.mu.Unlock()

return b.pendingState.GetNonce(account), nil
return b.pendingState.GetNonce(account)
}

// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
Expand Down Expand Up @@ -628,7 +628,10 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
}
// Recap the highest gas allowance with account's balance.
if call.GasPrice != nil && !call.GasPrice.IsZero() {
balance := b.pendingState.GetBalance(call.From) // from can't be nil
balance, err := b.pendingState.GetBalance(call.From) // from can't be nil
if err != nil {
return 0, err
}
available := balance.ToBig()
if call.Value != nil {
if call.Value.ToBig().Cmp(available) >= 0 {
Expand Down Expand Up @@ -724,7 +727,10 @@ func (b *SimulatedBackend) callContract(_ context.Context, call ethereum.CallMsg
call.Value = new(uint256.Int)
}
// Set infinite balance to the fake caller account.
from := statedb.GetOrNewStateObject(call.From)
from, err := statedb.GetOrNewStateObject(call.From)
if err != nil {
return nil, err
}
from.SetBalance(uint256.NewInt(0).SetAllOne(), tracing.BalanceChangeUnspecified)
// Execute the call.
msg := callMsg{call}
Expand Down Expand Up @@ -752,7 +758,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, txn types.Transa
if senderErr != nil {
return fmt.Errorf("invalid transaction: %w", senderErr)
}
nonce := b.pendingState.GetNonce(sender)
nonce, err := b.pendingState.GetNonce(sender)
if err != nil {
return err
}
if txn.GetNonce() != nonce {
return fmt.Errorf("invalid transaction nonce: got %d, want %d", txn.GetNonce(), nonce)
}
Expand Down
5 changes: 4 additions & 1 deletion accounts/abi/bind/backends/simulated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ func TestNewSimulatedBackend(t *testing.T) {
}

statedb := sim.stateByBlockNumber(tx, new(big.Int).SetUint64(num+1))
bal := statedb.GetBalance(testAddr)
bal, err := statedb.GetBalance(testAddr)
if err != nil {
t.Fatal(err)
}
if !bal.Eq(expectedBal) {
t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
}
Expand Down
1 change: 1 addition & 0 deletions cl/beacon/handler/subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func (a *ApiHandler) PostEthV1ValidatorSyncCommitteeSubscriptions(w http.Respons
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
//cn()
}

// subscribe to subnets
Expand Down
1 change: 0 additions & 1 deletion cl/phase1/forkchoice/on_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ func (f *ForkChoiceStore) OnAttestation(
return err
}
}

var attestationIndicies []uint64
var err error
target := data.Target
Expand Down
1 change: 0 additions & 1 deletion cl/phase1/forkchoice/on_attester_slashing.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ func (f *ForkChoiceStore) onProcessAttesterSlashing(attesterSlashing *cltypes.At
if !cltypes.IsSlashableAttestationData(attestation1.Data, attestation2.Data) {
return errors.New("attestation data is not slashable")
}

attestation1PublicKeys, err := getIndexedAttestationPublicKeys(s, attestation1)
if err != nil {
return err
Expand Down
1 change: 0 additions & 1 deletion cl/phase1/network/services/block_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ func (b *blockService) ProcessMessage(ctx context.Context, _ *uint64, msg *cltyp
if msg.Block.Body.BlobKzgCommitments.Len() > int(b.beaconCfg.MaxBlobsPerBlock) {
return ErrInvalidCommitmentsCount
}

b.publishBlockGossipEvent(msg)
// the rest of the validation is done in the forkchoice store
if err := b.processAndStoreBlock(ctx, msg); err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/state/exec3/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func (rw *Worker) ResetTx(chainTx kv.Tx) {

func (rw *Worker) Run() error {
for txTask, ok := rw.in.Next(rw.ctx); ok; txTask, ok = rw.in.Next(rw.ctx) {
//fmt.Println("RTX", txTask.BlockNum, txTask.TxIndex, txTask.TxNum, txTask.Final)
rw.RunTxTask(txTask, rw.isMining)
if err := rw.resultCh.Add(rw.ctx, txTask); err != nil {
return err
Expand Down
9 changes: 6 additions & 3 deletions consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,12 @@ type PoW interface {
}

// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func Transfer(db evmtypes.IntraBlockState, sender, recipient libcommon.Address, amount *uint256.Int, bailout bool) {
func Transfer(db evmtypes.IntraBlockState, sender, recipient libcommon.Address, amount *uint256.Int, bailout bool) error {
if !bailout {
db.SubBalance(sender, amount, tracing.BalanceChangeTransfer)
err := db.SubBalance(sender, amount, tracing.BalanceChangeTransfer)
if err != nil {
return err
}
}
db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer)
return db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer)
}
15 changes: 12 additions & 3 deletions consensus/misc/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,24 @@ func VerifyDAOHeaderExtraData(config *chain.Config, header *types.Header) error
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
// rules, transferring all balances of a set of DAO accounts to a single refund
// contract.
func ApplyDAOHardFork(statedb *state.IntraBlockState) {
func ApplyDAOHardFork(statedb *state.IntraBlockState) error {
// Retrieve the contract to refund balances into
if !statedb.Exist(params.DAORefundContract) {
exist, err := statedb.Exist(params.DAORefundContract)
if err != nil {
return err
}
if !exist {
statedb.CreateAccount(params.DAORefundContract, false)
}

// Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList() {
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract)
balance, err := statedb.GetBalance(addr)
if err != nil {
return err
}
statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract)
statedb.SetBalance(addr, new(uint256.Int), tracing.BalanceDecreaseDaoAccount)
}
return nil
}
18 changes: 11 additions & 7 deletions consensus/misc/eip2935.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,25 @@ import (
"github.com/erigontech/erigon/params"
)

func StoreBlockHashesEip2935(header *types.Header, state *state.IntraBlockState, config *chain.Config, headerReader consensus.ChainHeaderReader) {
if state.GetCodeSize(params.HistoryStorageAddress) == 0 {
func StoreBlockHashesEip2935(header *types.Header, state *state.IntraBlockState, config *chain.Config, headerReader consensus.ChainHeaderReader) error {
codeSize, err := state.GetCodeSize(params.HistoryStorageAddress)
if err != nil {
return err
}
if codeSize == 0 {
log.Debug("[EIP-2935] No code deployed to HistoryStorageAddress before call to store EIP-2935 history")
return
return nil
}
headerNum := header.Number.Uint64()
if headerNum == 0 { // Activation of fork at Genesis
return
return nil
}
storeHash(headerNum-1, header.ParentHash, state)
return storeHash(headerNum-1, header.ParentHash, state)
}

func storeHash(num uint64, hash libcommon.Hash, state *state.IntraBlockState) {
func storeHash(num uint64, hash libcommon.Hash, state *state.IntraBlockState) error {
slotNum := num % params.BlockHashHistoryServeWindow
storageSlot := libcommon.BytesToHash(uint256.NewInt(slotNum).Bytes())
parentHashInt := uint256.NewInt(0).SetBytes32(hash.Bytes())
state.SetState(params.HistoryStorageAddress, &storageSlot, *parentHashInt)
return state.SetState(params.HistoryStorageAddress, &storageSlot, *parentHashInt)
}
12 changes: 10 additions & 2 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,18 @@ func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) {
// TxNonce returns the next valid transaction nonce for the
// account at addr. It panics if the account does not exist.
func (b *BlockGen) TxNonce(addr libcommon.Address) uint64 {
if !b.ibs.Exist(addr) {
exist, err := b.ibs.Exist(addr)
if err != nil {
panic(fmt.Sprintf("can't get account: %s", err))
}
if !exist {
panic("account does not exist")
}
return b.ibs.GetNonce(addr)
nonce, err := b.ibs.GetNonce(addr)
if err != nil {
panic(fmt.Sprintf("can't get account: %s", err))
}
return nonce
}

// AddUncle adds an uncle header to the generated block.
Expand Down
8 changes: 6 additions & 2 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ func GetHashFn(ref *types.Header, getHeader func(hash libcommon.Hash, number uin

// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
func CanTransfer(db evmtypes.IntraBlockState, addr libcommon.Address, amount *uint256.Int) bool {
return !db.GetBalance(addr).Lt(amount)
func CanTransfer(db evmtypes.IntraBlockState, addr libcommon.Address, amount *uint256.Int) (bool, error) {
balance, err := db.GetBalance(addr)
if err != nil {
return false, err
}
return !balance.Lt(amount), nil
}
6 changes: 4 additions & 2 deletions core/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,11 @@ func TestAllocConstructor(t *testing.T) {
reader, err := rpchelper.CreateHistoryStateReader(tx, rawdbv3.TxNums, 1, 0, genSpec.Config.ChainName)
require.NoError(err)
state := state.New(reader)
balance := state.GetBalance(address)
balance, err := state.GetBalance(address)
assert.NoError(err)
assert.Equal(funds, balance.ToBig())
code := state.GetCode(address)
code, err := state.GetCode(address)
assert.NoError(err)
assert.Equal(common.FromHex("5f355f55"), code)

key0 := libcommon.HexToHash("0000000000000000000000000000000000000000000000000000000000000000")
Expand Down
Loading

0 comments on commit a962e99

Please sign in to comment.