core: Set L1CostFunc in NewEVMBlockContext (#71)

Avoids potential for bugs where L1CostFunc is not manually set after creating the block context.
This commit is contained in:
Adrian Sutton 2023-03-17 09:22:58 +10:00 committed by GitHub
parent e95b13f657
commit e3c5831e7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 24 additions and 38 deletions

View File

@ -716,8 +716,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
msg := callMsg{call}
txContext := core.NewEVMTxContext(msg)
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
evmContext.L1CostFunc = types.NewL1CostFunc(b.config, stateDB)
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil, b.config, stateDB)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})

View File

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
// ChainContext supports retrieving headers and consensus parameters from the
@ -36,7 +37,7 @@ type ChainContext interface {
}
// NewEVMBlockContext creates a new context for use in the EVM.
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext {
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address, config *params.ChainConfig, statedb types.StateGetter) vm.BlockContext {
var (
beneficiary common.Address
baseFee *big.Int
@ -66,6 +67,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
BaseFee: baseFee,
GasLimit: header.GasLimit,
Random: random,
L1CostFunc: types.NewL1CostFunc(config, statedb),
}
}

View File

@ -51,11 +51,10 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
var (
header = block.Header()
gaspool = new(GasPool).AddGas(block.GasLimit())
blockContext = NewEVMBlockContext(header, p.bc, nil)
blockContext = NewEVMBlockContext(header, p.bc, nil, p.config, statedb)
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
signer = types.MakeSigner(p.config, header.Number)
)
blockContext.L1CostFunc = types.NewL1CostFunc(p.config, statedb)
// Iterate over and process the individual transactions
byzantium := p.config.IsByzantium(block.Number())
for i, tx := range block.Transactions() {

View File

@ -70,8 +70,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb)
}
blockContext := NewEVMBlockContext(header, p.bc, nil)
blockContext.L1CostFunc = types.NewL1CostFunc(p.config, statedb)
blockContext := NewEVMBlockContext(header, p.bc, nil, p.config, statedb)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
@ -164,8 +163,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
return nil, err
}
// Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author)
blockContext.L1CostFunc = types.NewL1CostFunc(config, statedb)
blockContext := NewEVMBlockContext(header, bc, author, config, statedb)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
}

View File

@ -232,8 +232,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *sta
vmConfig = b.eth.blockchain.GetVMConfig()
}
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
context.L1CostFunc = types.NewL1CostFunc(b.eth.blockchain.Config(), state)
context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil, b.eth.blockchain.Config(), state)
return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error, nil
}

View File

@ -214,8 +214,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
// Assemble the transaction call message and return if the requested offset
msg, _ := tx.AsMessage(signer, block.BaseFee())
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
context.L1CostFunc = types.NewL1CostFunc(eth.blockchain.Config(), statedb)
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil, eth.blockchain.Config(), statedb)
if idx == txIndex {
return msg, context, statedb, release, nil
}

View File

@ -290,9 +290,8 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
for task := range taskCh {
var (
signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number())
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil, api.backend.ChainConfig(), task.statedb)
)
blockCtx.L1CostFunc = types.NewL1CostFunc(api.backend.ChainConfig(), task.statedb)
// Trace all the transactions contained within
for i, tx := range task.block.Transactions() {
msg, _ := tx.AsMessage(signer, task.block.BaseFee())
@ -576,10 +575,9 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
roots []common.Hash
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
chainConfig = api.backend.ChainConfig()
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil, chainConfig, statedb)
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
)
vmctx.L1CostFunc = types.NewL1CostFunc(chainConfig, statedb)
for i, tx := range block.Transactions() {
if err := ctx.Err(); err != nil {
return nil, err
@ -653,11 +651,10 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
txs = block.Transactions()
blockHash = block.Hash()
is158 = api.backend.ChainConfig().IsEIP158(block.Number())
blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil, api.backend.ChainConfig(), statedb)
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
results = make([]*txTraceResult, len(txs))
)
blockCtx.L1CostFunc = types.NewL1CostFunc(api.backend.ChainConfig(), statedb)
for i, tx := range txs {
// Generate the next state snapshot fast without tracing
msg, _ := tx.AsMessage(signer, block.BaseFee())
@ -701,8 +698,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
defer pend.Done()
// Fetch and execute the next transaction trace tasks
for task := range jobs {
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
blockCtx.L1CostFunc = types.NewL1CostFunc(api.backend.ChainConfig(), task.statedb)
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil, api.backend.ChainConfig(), task.statedb)
msg, _ := txs[task.index].AsMessage(signer, block.BaseFee())
txctx := &Context{
BlockHash: blockHash,
@ -721,8 +717,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
// Feed the transactions into the tracers and return
var failed error
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
blockCtx.L1CostFunc = types.NewL1CostFunc(api.backend.ChainConfig(), statedb)
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil, api.backend.ChainConfig(), statedb)
txloop:
for i, tx := range txs {
// Send the trace task over for execution
@ -800,7 +795,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
dumps []string
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
chainConfig = api.backend.ChainConfig()
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil, chainConfig, statedb)
canon = true
)
// Check if there are any overrides: the caller may wish to enable a future
@ -812,7 +807,6 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
// Note: This copies the config, to not screw up the main config
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
}
vmctx.L1CostFunc = types.NewL1CostFunc(chainConfig, statedb)
for i, tx := range block.Transactions() {
// Prepare the transaction for un-traced execution
var (
@ -972,7 +966,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
}
defer release()
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil, api.backend.ChainConfig(), statedb)
// Apply the customization rules if required.
if config != nil {
if err := config.StateOverrides.Apply(statedb); err != nil {
@ -980,7 +974,6 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
}
config.BlockOverrides.Apply(&vmctx)
}
vmctx.L1CostFunc = types.NewL1CostFunc(api.backend.ChainConfig(), statedb)
// Execute the trace
msg, err := args.ToMessage(api.backend.RPCGasCap(), block.BaseFee())
if err != nil {

View File

@ -255,11 +255,10 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
for idx, tx := range block.Transactions() {
msg, _ := tx.AsMessage(signer, block.BaseFee())
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
context := core.NewEVMBlockContext(block.Header(), b.chain, nil, b.chainConfig, statedb)
if idx == txIndex {
return msg, context, statedb, release, nil
}
context.L1CostFunc = types.NewL1CostFunc(b.chainConfig, statedb)
vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{})
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)

View File

@ -189,8 +189,7 @@ func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *sta
vmConfig = new(vm.Config)
}
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(header, b.eth.blockchain, nil)
context.L1CostFunc = types.NewL1CostFunc(b.eth.chainConfig, state)
context := core.NewEVMBlockContext(header, b.eth.blockchain, nil, b.eth.chainConfig, state)
return vm.NewEVM(context, txContext, state, b.eth.chainConfig, *vmConfig), state.Error, nil
}

View File

@ -138,7 +138,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)}
context := core.NewEVMBlockContext(header, bc, nil)
context := core.NewEVMBlockContext(header, bc, nil, config, statedb)
txContext := core.NewEVMTxContext(msg)
vmenv := vm.NewEVM(context, txContext, statedb, config, vm.Config{NoBaseFee: true})
@ -152,7 +152,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
state := light.NewState(ctx, header, lc.Odr())
state.SetBalance(bankAddr, math.MaxBig256)
msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)}
context := core.NewEVMBlockContext(header, lc, nil)
context := core.NewEVMBlockContext(header, lc, nil, config, state)
txContext := core.NewEVMTxContext(msg)
vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{NoBaseFee: true})
gp := new(core.GasPool).AddGas(math.MaxUint64)

View File

@ -62,12 +62,11 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.
// Assemble the transaction call message and return if the requested offset
msg, _ := tx.AsMessage(signer, block.BaseFee())
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), leth.blockchain, nil)
context := core.NewEVMBlockContext(block.Header(), leth.blockchain, nil, leth.blockchain.Config(), statedb)
statedb.SetTxContext(tx.Hash(), idx)
if idx == txIndex {
return msg, context, statedb, release, nil
}
context.L1CostFunc = types.NewL1CostFunc(leth.blockchain.Config(), statedb)
// Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{})
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {

View File

@ -207,7 +207,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
st.SetBalance(testBankAddress, math.MaxBig256)
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)}
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(header, chain, nil)
context := core.NewEVMBlockContext(header, chain, nil, config, st)
vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{NoBaseFee: true})
gp := new(core.GasPool).AddGas(math.MaxUint64)
result, _ := core.ApplyMessage(vmenv, msg, gp)

View File

@ -222,7 +222,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
// Prepare the EVM.
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase, config, statedb)
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)

View File

@ -245,7 +245,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
// Prepare the EVM.
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase, config, statedb)
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
context.Random = nil