cmd/evm/internal/t8ntool: use transaction iterator instead of list

This commit is contained in:
Martin Holst Swende 2023-10-21 22:36:10 +02:00
parent efcb866643
commit 463bd9f076
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
3 changed files with 56 additions and 17 deletions

View file

@ -116,8 +116,8 @@ type rejectedTx struct {
// Apply applies a set of transactions to a pre-state // Apply applies a set of transactions to a pre-state
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
txs types.Transactions, miningReward int64, txIt txIterator, miningReward int64,
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) { getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, []byte, error) {
// Capture errors for BLOCKHASH operation, if we haven't been supplied the // Capture errors for BLOCKHASH operation, if we haven't been supplied the
// required blockhashes // required blockhashes
var hashError error var hashError error
@ -190,7 +190,14 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb) core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
} }
var blobGasUsed uint64 var blobGasUsed uint64
for i, tx := range txs {
for i := 0; txIt.Next(); i++ {
tx, err := txIt.Tx()
if err != nil {
log.Warn("rejected tx", "index", i, "error", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
continue
}
if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil { if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil {
errMsg := "blob tx used but field env.ExcessBlobGas missing" errMsg := "blob tx used but field env.ExcessBlobGas missing"
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg) log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg)
@ -208,7 +215,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
} }
tracer, err := getTracerFn(txIndex, tx.Hash()) tracer, err := getTracerFn(txIndex, tx.Hash())
if err != nil { if err != nil {
return nil, nil, err return nil, nil, nil, err
} }
vmConfig.Tracer = tracer vmConfig.Tracer = tracer
statedb.SetTxContext(tx.Hash(), txIndex) statedb.SetTxContext(tx.Hash(), txIndex)
@ -231,7 +238,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
} }
includedTxs = append(includedTxs, tx) includedTxs = append(includedTxs, tx)
if hashError != nil { if hashError != nil {
return nil, nil, NewError(ErrorMissingBlockhash, hashError) return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError)
} }
gasUsed += msgResult.UsedGas gasUsed += msgResult.UsedGas
@ -306,7 +313,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
// Commit block // Commit block
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber)) root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
if err != nil { if err != nil {
return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err)) return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
} }
execRs := &ExecutionResult{ execRs := &ExecutionResult{
StateRoot: root, StateRoot: root,
@ -332,9 +339,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
// for accessing latest states. // for accessing latest states.
statedb, err = state.New(root, statedb.Database(), nil) statedb, err = state.New(root, statedb.Database(), nil)
if err != nil { if err != nil {
return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err)) return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
} }
return statedb, execRs, nil body, _ := rlp.EncodeToBytes(includedTxs)
return statedb, execRs, body, nil
} }
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB { func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {

View file

@ -34,7 +34,6 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests" "github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -144,7 +143,7 @@ func Transition(ctx *cli.Context) error {
// Check if anything needs to be read from stdin // Check if anything needs to be read from stdin
var ( var (
prestate Prestate prestate Prestate
txs types.Transactions // txs to apply txIt txIterator // txs to apply
allocStr = ctx.String(InputAllocFlag.Name) allocStr = ctx.String(InputAllocFlag.Name)
envStr = ctx.String(InputEnvFlag.Name) envStr = ctx.String(InputEnvFlag.Name)
@ -189,7 +188,7 @@ func Transition(ctx *cli.Context) error {
// Set the chain id // Set the chain id
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name)) chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
if txs, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil { if txIt, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil {
return err return err
} }
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil { if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
@ -205,11 +204,10 @@ func Transition(ctx *cli.Context) error {
return err return err
} }
// Run the test and aggregate the result // Run the test and aggregate the result
s, result, err := prestate.Apply(vmConfig, chainConfig, txs, ctx.Int64(RewardFlag.Name), getTracer) s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name), getTracer)
if err != nil { if err != nil {
return err return err
} }
body, _ := rlp.EncodeToBytes(txs)
// Dump the excution result // Dump the excution result
collector := make(Alloc) collector := make(Alloc)
s.DumpToCollector(collector, nil) s.DumpToCollector(collector, nil)

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"io"
) )
// txWithKey is a helper-struct, to allow us to use the types.Transaction along with // txWithKey is a helper-struct, to allow us to use the types.Transaction along with
@ -110,7 +111,7 @@ func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Tran
return signedTxs, nil return signedTxs, nil
} }
func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (types.Transactions, error) { func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (txIterator, error) {
var txsWithKeys []*txWithKey var txsWithKeys []*txWithKey
var signed types.Transactions var signed types.Transactions
if txStr != stdinSelector { if txStr != stdinSelector {
@ -127,7 +128,7 @@ func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *pa
if err := rlp.DecodeBytes(body, &signed); err != nil { if err := rlp.DecodeBytes(body, &signed); err != nil {
return nil, err return nil, err
} }
return signed, nil return newArrayIterator(signed), err
} }
if err := json.Unmarshal(data, &txsWithKeys); err != nil { if err := json.Unmarshal(data, &txsWithKeys); err != nil {
return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err)) return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
@ -140,12 +141,44 @@ func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *pa
if err := rlp.DecodeBytes(body, &signed); err != nil { if err := rlp.DecodeBytes(body, &signed); err != nil {
return nil, err return nil, err
} }
return signed, nil return newArrayIterator(signed), nil
} }
// JSON encoded transactions // JSON encoded transactions
txsWithKeys = inputData.Txs txsWithKeys = inputData.Txs
} }
// We may have to sign the transactions. // We may have to sign the transactions.
signer := types.LatestSignerForChainID(chainConfig.ChainID) signer := types.LatestSignerForChainID(chainConfig.ChainID)
return signUnsignedTransactions(txsWithKeys, signer) txs, err := signUnsignedTransactions(txsWithKeys, signer)
return newArrayIterator(txs), err
}
type txIterator interface {
// Next returns true until EOF
Next() bool
// Tx returns the next transaction, OR an error.
Tx() (*types.Transaction, error)
}
type arrayIterator struct {
idx int
txs types.Transactions
}
func newArrayIterator(transactions types.Transactions) *arrayIterator {
return &arrayIterator{0, transactions}
}
func (ait *arrayIterator) Next() bool {
if ait.idx < len(ait.txs) {
return true
}
return false
}
func (ait *arrayIterator) Tx() (*types.Transaction, error) {
if ait.idx < len(ait.txs) {
ait.idx++
return ait.txs[ait.idx-1], nil
}
return nil, io.EOF
} }