Merge pull request #42 from sei-protocol/tony/precompile-dyn-load

make precompile loading dynamic
This commit is contained in:
codchen 2025-03-03 15:54:48 +08:00 committed by GitHub
commit a9c1e92907
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 71 additions and 57 deletions

View file

@ -702,7 +702,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
txContext := core.NewEVMTxContext(msg) txContext := core.NewEVMTxContext(msg)
evmContext := core.NewEVMBlockContext(header, b.blockchain, nil) evmContext := core.NewEVMBlockContext(header, b.blockchain, nil)
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}) vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}, nil)
gasPool := new(core.GasPool).AddGas(math.MaxUint64) gasPool := new(core.GasPool).AddGas(math.MaxUint64)
return core.ApplyMessage(vmEnv, msg, gasPool) return core.ApplyMessage(vmEnv, msg, gasPool)

View file

@ -190,7 +190,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil { if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig) evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig, nil)
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb) core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
} }
var blobGasUsed uint64 var blobGasUsed uint64
@ -238,7 +238,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
snapshot = statedb.Snapshot() snapshot = statedb.Snapshot()
prevGas = gaspool.Gas() prevGas = gaspool.Gas()
) )
evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig, nil)
if tracer != nil && tracer.OnTxStart != nil { if tracer != nil && tracer.OnTxStart != nil {
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)

View file

@ -98,7 +98,7 @@ func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
b.header.ParentBeaconRoot = &root b.header.ParentBeaconRoot = &root
var ( var (
blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase) blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{}) vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{}, nil)
) )
ProcessBeaconBlockRoot(root, vmenv, b.statedb) ProcessBeaconBlockRoot(root, vmenv, b.statedb)
} }

View file

@ -52,7 +52,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
header = block.Header() header = block.Header()
gaspool = new(GasPool).AddGas(block.GasLimit()) gaspool = new(GasPool).AddGas(block.GasLimit())
blockContext = NewEVMBlockContext(header, p.bc, nil) blockContext = NewEVMBlockContext(header, p.bc, nil)
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg, nil)
signer = types.MakeSigner(p.config, header.Number, header.Time) signer = types.MakeSigner(p.config, header.Number, header.Time)
) )
// Iterate over and process the individual transactions // Iterate over and process the individual transactions

View file

@ -73,7 +73,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb vm.StateDB, cfg vm.
} }
var ( var (
context = NewEVMBlockContext(header, p.bc, nil) context = NewEVMBlockContext(header, p.bc, nil)
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg) vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg, nil)
signer = types.MakeSigner(p.config, header.Number, header.Time) signer = types.MakeSigner(p.config, header.Number, header.Time)
) )
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
@ -178,7 +178,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
// Create a new context to be used in the EVM environment // Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author) blockContext := NewEVMBlockContext(header, bc, author)
txContext := NewEVMTxContext(msg) txContext := NewEVMTxContext(msg)
vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg) vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg, nil)
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
} }

View file

@ -37,7 +37,7 @@ func FuzzPrecompiledContracts(f *testing.F) {
return return
} }
inWant := string(input) inWant := string(input)
vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, input, gas, nil, nil, false) vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, input, gas, nil, nil, false, false)
if inHave := string(input); inWant != inHave { if inHave := string(input); inWant != inHave {
t.Errorf("Precompiled %v modified input data", a) t.Errorf("Precompiled %v modified input data", a)
} }

View file

@ -99,7 +99,7 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
in := common.Hex2Bytes(test.Input) in := common.Hex2Bytes(test.Input)
gas := p.RequiredGas(in) gas := p.RequiredGas(in)
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) { t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
if res, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false); err != nil { if res, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false, false); err != nil {
t.Error(err) t.Error(err)
} else if common.Bytes2Hex(res) != test.Expected { } else if common.Bytes2Hex(res) != test.Expected {
t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res)) t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
@ -121,7 +121,7 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
gas := p.RequiredGas(in) - 1 gas := p.RequiredGas(in) - 1
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) { t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
_, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false) _, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false, false)
if err.Error() != "out of gas" { if err.Error() != "out of gas" {
t.Errorf("Expected error [out of gas], got [%v]", err) t.Errorf("Expected error [out of gas], got [%v]", err)
} }
@ -138,7 +138,7 @@ func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing
in := common.Hex2Bytes(test.Input) in := common.Hex2Bytes(test.Input)
gas := p.RequiredGas(in) gas := p.RequiredGas(in)
t.Run(test.Name, func(t *testing.T) { t.Run(test.Name, func(t *testing.T) {
_, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false) _, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false, false)
if err.Error() != test.ExpectedError { if err.Error() != test.ExpectedError {
t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err) t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
} }
@ -170,7 +170,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
bench.ResetTimer() bench.ResetTimer()
for i := 0; i < bench.N; i++ { for i := 0; i < bench.N; i++ {
copy(data, in) copy(data, in)
res, _, err = vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, data, reqGas, nil, nil, false) res, _, err = vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, data, reqGas, nil, nil, false, false)
} }
bench.StopTimer() bench.StopTimer()
elapsed := uint64(time.Since(start)) elapsed := uint64(time.Since(start))

View file

@ -40,6 +40,12 @@ type (
) )
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
if evm.dynamicPrecompiles != nil {
p, ok := evm.dynamicPrecompiles[addr]
if ok {
return p, true
}
}
var precompiles map[common.Address]PrecompiledContract var precompiles map[common.Address]PrecompiledContract
switch { switch {
case evm.chainRules.IsCancun: case evm.chainRules.IsCancun:
@ -123,11 +129,13 @@ type EVM struct {
// available gas is calculated in gasCall* according to the 63/64 rule and later // available gas is calculated in gasCall* according to the 63/64 rule and later
// applied in opCall*. // applied in opCall*.
callGasTemp uint64 callGasTemp uint64
dynamicPrecompiles map[common.Address]PrecompiledContract
} }
// NewEVM returns a new EVM. The returned EVM is not thread safe and should // NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*. // only ever be used *once*.
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM { func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, dynamicPrecompiles map[common.Address]PrecompiledContract) *EVM {
// If basefee tracking is disabled (eth_call, eth_estimateGas, etc), and no // If basefee tracking is disabled (eth_call, eth_estimateGas, etc), and no
// gas prices were specified, lower the basefee to 0 to avoid breaking EVM // gas prices were specified, lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap) // invariants (basefee < feecap)
@ -146,6 +154,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
Config: config, Config: config,
chainConfig: chainConfig, chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
dynamicPrecompiles: dynamicPrecompiles,
} }
evm.interpreter = NewEVMInterpreter(evm) evm.interpreter = NewEVMInterpreter(evm)
return evm return evm

View file

@ -95,7 +95,7 @@ func TestEIP2200(t *testing.T) {
CanTransfer: func(vm.StateDB, common.Address, *big.Int) bool { return true }, CanTransfer: func(vm.StateDB, common.Address, *big.Int) bool { return true },
Transfer: func(vm.StateDB, common.Address, common.Address, *big.Int) {}, Transfer: func(vm.StateDB, common.Address, common.Address, *big.Int) {},
} }
vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, vm.Config{ExtraEips: []int{2200}}) vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, vm.Config{ExtraEips: []int{2200}}, nil)
_, gas, err := vmenv.Call(vm.AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int)) _, gas, err := vmenv.Call(vm.AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
if err != tt.failure { if err != tt.failure {
@ -151,7 +151,7 @@ func TestCreateGas(t *testing.T) {
config.ExtraEips = []int{3860} config.ExtraEips = []int{3860}
} }
vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, config) vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, config, nil)
var startGas = uint64(testGas) var startGas = uint64(testGas)
ret, gas, err := vmenv.Call(vm.AccountRef(common.Address{}), address, nil, startGas, new(big.Int)) ret, gas, err := vmenv.Call(vm.AccountRef(common.Address{}), address, nil, startGas, new(big.Int))
if err != nil { if err != nil {

View file

@ -106,7 +106,7 @@ func init() {
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn vm.ExecutionFunc, name string) { func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn vm.ExecutionFunc, name string) {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
pc = uint64(0) pc = uint64(0)
evmInterpreter = env.GetInterpreter() evmInterpreter = env.GetInterpreter()
@ -205,7 +205,7 @@ func TestSAR(t *testing.T) {
func TestAddMod(t *testing.T) { func TestAddMod(t *testing.T) {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
evmInterpreter = vm.NewEVMInterpreter(env) evmInterpreter = vm.NewEVMInterpreter(env)
pc = uint64(0) pc = uint64(0)
@ -249,7 +249,7 @@ func TestWriteExpectedValues(t *testing.T) {
// getResult is a convenience function to generate the expected values // getResult is a convenience function to generate the expected values
getResult := func(args []*twoOperandParams, opFn vm.ExecutionFunc) []TwoOperandTestcase { getResult := func(args []*twoOperandParams, opFn vm.ExecutionFunc) []TwoOperandTestcase {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
pc = uint64(0) pc = uint64(0)
interpreter = env.Interpreter() interpreter = env.Interpreter()
@ -294,7 +294,7 @@ func TestJsonTestcases(t *testing.T) {
func opBenchmark(bench *testing.B, op vm.ExecutionFunc, args ...string) { func opBenchmark(bench *testing.B, op vm.ExecutionFunc, args ...string) {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
scope = &vm.ScopeContext{nil, stack, nil} scope = &vm.ScopeContext{nil, stack, nil}
evmInterpreter = vm.NewEVMInterpreter(env) evmInterpreter = vm.NewEVMInterpreter(env)
@ -535,7 +535,7 @@ func BenchmarkOpIsZero(b *testing.B) {
func TestOpMstore(t *testing.T) { func TestOpMstore(t *testing.T) {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
mem = vm.NewMemory() mem = vm.NewMemory()
evmInterpreter = vm.NewEVMInterpreter(env) evmInterpreter = vm.NewEVMInterpreter(env)
@ -561,7 +561,7 @@ func TestOpMstore(t *testing.T) {
func BenchmarkOpMstore(bench *testing.B) { func BenchmarkOpMstore(bench *testing.B) {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
mem = vm.NewMemory() mem = vm.NewMemory()
evmInterpreter = vm.NewEVMInterpreter(env) evmInterpreter = vm.NewEVMInterpreter(env)
@ -584,7 +584,7 @@ func BenchmarkOpMstore(bench *testing.B) {
func TestOpTstore(t *testing.T) { func TestOpTstore(t *testing.T) {
var ( var (
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, statedb, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, statedb, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
mem = vm.NewMemory() mem = vm.NewMemory()
evmInterpreter = vm.NewEVMInterpreter(env) evmInterpreter = vm.NewEVMInterpreter(env)
@ -626,7 +626,7 @@ func TestOpTstore(t *testing.T) {
func BenchmarkOpKeccak256(bench *testing.B) { func BenchmarkOpKeccak256(bench *testing.B) {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
mem = vm.NewMemory() mem = vm.NewMemory()
evmInterpreter = vm.NewEVMInterpreter(env) evmInterpreter = vm.NewEVMInterpreter(env)
@ -730,7 +730,7 @@ func TestRandom(t *testing.T) {
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})}, {name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
} { } {
var ( var (
env = vm.NewEVM(vm.BlockContext{Random: &tt.random}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{Random: &tt.random}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
pc = uint64(0) pc = uint64(0)
evmInterpreter = env.Interpreter() evmInterpreter = env.Interpreter()
@ -771,7 +771,7 @@ func TestBlobHash(t *testing.T) {
{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil}, {name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
} { } {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
pc = uint64(0) pc = uint64(0)
evmInterpreter = env.Interpreter() evmInterpreter = env.Interpreter()
@ -874,7 +874,7 @@ func TestOpMCopy(t *testing.T) {
}, },
} { } {
var ( var (
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}, nil)
stack = vm.Newstack() stack = vm.Newstack()
pc = uint64(0) pc = uint64(0)
evmInterpreter = env.Interpreter() evmInterpreter = env.Interpreter()

View file

@ -49,7 +49,7 @@ func TestLoopInterrupt(t *testing.T) {
statedb.SetCode(address, common.Hex2Bytes(tt)) statedb.SetCode(address, common.Hex2Bytes(tt))
statedb.Finalise(true) statedb.Finalise(true)
evm := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, vm.Config{}) evm := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, vm.Config{}, nil)
errChannel := make(chan error) errChannel := make(chan error)
timeout := make(chan bool) timeout := make(chan bool)

View file

@ -42,5 +42,5 @@ func NewEnv(cfg *Config) *vm.EVM {
Random: cfg.Random, Random: cfg.Random,
} }
return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig) return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig, nil)
} }

View file

@ -259,7 +259,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state vm.
} else { } else {
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil) context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
} }
return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig) return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig, b.GetCustomPrecompiles())
} }
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
@ -414,3 +414,5 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, tracers.StateReleaseFunc, error) { func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, tracers.StateReleaseFunc, error) {
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
} }
func (b *EthAPIBackend) GetCustomPrecompiles() map[common.Address]vm.PrecompiledContract { return nil }

View file

@ -217,7 +217,7 @@ func run(ctx context.Context, call *core.Message, opts *Options) (*core.Executio
evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil) evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil)
dirtyState = opts.State.Copy() dirtyState = opts.State.Copy()
evm = vm.NewEVM(evmContext, msgContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true}) evm = vm.NewEVM(evmContext, msgContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true}, nil)
) )
dirtyState.SetEVM(evm) dirtyState.SetEVM(evm)

View file

@ -246,7 +246,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
return tx, context, statedb, release, nil return tx, context, statedb, release, nil
} }
// Not yet the searched for transaction, execute on top of the current state // Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}, nil)
statedb.SetTxContext(tx.Hash(), idx) statedb.SetTxContext(tx.Hash(), idx)
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { 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) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)

View file

@ -89,6 +89,7 @@ type Backend interface {
ChainDb() ethdb.Database ChainDb() ethdb.Database
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, StateReleaseFunc, error) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, StateReleaseFunc, error)
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, StateReleaseFunc, error) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, StateReleaseFunc, error)
GetCustomPrecompiles() map[common.Address]vm.PrecompiledContract
} }
// API is the collection of tracing APIs exposed over the private debugging endpoint. // API is the collection of tracing APIs exposed over the private debugging endpoint.
@ -533,7 +534,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
var ( var (
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
txContext = core.NewEVMTxContext(msg) txContext = core.NewEVMTxContext(msg)
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{}) vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{}, api.backend.GetCustomPrecompiles())
) )
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
@ -683,7 +684,7 @@ txloop:
// Generate the next state snapshot fast without tracing // Generate the next state snapshot fast without tracing
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}, api.backend.GetCustomPrecompiles())
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
failed = err failed = err
break txloop break txloop
@ -789,7 +790,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
} }
} }
// Execute the transaction and flush any traces to disk // Execute the transaction and flush any traces to disk
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf, api.backend.GetCustomPrecompiles())
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
vmConf.Tracer.OnTxStart(vmenv.GetVMContext(), tx, msg.From) vmConf.Tracer.OnTxStart(vmenv.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)) vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
@ -987,7 +988,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
return nil, err return nil, err
} }
} }
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: big.NewInt(0)}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true}) vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: big.NewInt(0)}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true}, api.backend.GetCustomPrecompiles())
statedb.SetLogger(tracer.Hooks) statedb.SetLogger(tracer.Hooks)
// Define a meaningful timeout of a single transaction trace // Define a meaningful timeout of a single transaction trace

View file

@ -175,7 +175,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
if idx == txIndex { if idx == txIndex {
return tx, context, statedb, release, nil return tx, context, statedb, release, nil
} }
vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}) vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}, nil)
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { 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) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
} }
@ -184,6 +184,8 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
} }
func (b *testBackend) GetCustomPrecompiles() map[common.Address]vm.PrecompiledContract { return nil }
func TestTraceCall(t *testing.T) { func TestTraceCall(t *testing.T) {
t.Parallel() t.Parallel()

View file

@ -149,7 +149,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) t.Fatalf("failed to prepare transaction for tracing: %v", err)
} }
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}, nil)
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {
@ -251,7 +251,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
if err != nil { if err != nil {
b.Fatalf("failed to create call tracer: %v", err) b.Fatalf("failed to create call tracer: %v", err)
} }
evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}, nil)
snap := statedb.Snapshot() snap := statedb.Snapshot()
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()), false) st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()), false)
if _, err = st.TransitionDb(); err != nil { if _, err = st.TransitionDb(); err != nil {
@ -393,7 +393,7 @@ func TestInternals(t *testing.T) {
Origin: origin, Origin: origin,
GasPrice: tx.GasPrice(), GasPrice: tx.GasPrice(),
} }
evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer.Hooks}) evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer.Hooks}, nil)
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0)) msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
if err != nil { if err != nil {
t.Fatalf("test %v: failed to create message: %v", tc.name, err) t.Fatalf("test %v: failed to create message: %v", tc.name, err)

View file

@ -107,7 +107,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
if err != nil { if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err) return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
} }
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}, nil)
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {

View file

@ -123,7 +123,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) t.Fatalf("failed to prepare transaction for tracing: %v", err)
} }
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}, nil)
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {

View file

@ -63,7 +63,7 @@ func testCtx() *vmContext {
func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) { func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
var ( var (
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.Hooks}) env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.Hooks}, nil)
gasLimit uint64 = 31000 gasLimit uint64 = 31000
startGas uint64 = 10000 startGas uint64 = 10000
value = big.NewInt(0) value = big.NewInt(0)
@ -184,7 +184,7 @@ func TestHaltBetweenSteps(t *testing.T) {
scope := &vm.ScopeContext{ scope := &vm.ScopeContext{
Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0), Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
} }
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks}) env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks}, nil)
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{}) tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0)) tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0))
tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil) tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
@ -206,7 +206,7 @@ func TestNoStepExec(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks}) env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks}, nil)
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{}) tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0)) tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0))
tracer.OnExit(0, nil, 0, nil, false) tracer.OnExit(0, nil, 0, nil, false)

View file

@ -55,7 +55,7 @@ func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) {}
func TestStoreCapture(t *testing.T) { func TestStoreCapture(t *testing.T) {
var ( var (
logger = NewStructLogger(nil) logger = NewStructLogger(nil)
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()}) env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()}, nil)
contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000) contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000)
) )
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)} contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}

View file

@ -89,7 +89,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
//EnableMemory: false, //EnableMemory: false,
//EnableReturnData: false, //EnableReturnData: false,
}) })
evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer.Hooks()}) evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer.Hooks()}, nil)
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil { if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err) b.Fatalf("failed to prepare transaction for tracing: %v", err)

View file

@ -544,7 +544,7 @@ func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state vm.Sta
if blockContext != nil { if blockContext != nil {
context = *blockContext context = *blockContext
} }
return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig) return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig, nil)
} }
func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
panic("implement me") panic("implement me")

View file

@ -975,7 +975,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
} }
if header.ParentBeaconRoot != nil { if header.ParentBeaconRoot != nil {
context := core.NewEVMBlockContext(header, w.chain, nil) context := core.NewEVMBlockContext(header, w.chain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{}) vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{}, nil)
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state) core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state)
} }
return env, nil return env, nil

View file

@ -82,7 +82,7 @@ func fuzz(id byte, data []byte) int {
} }
cpy := make([]byte, len(data)) cpy := make([]byte, len(data))
copy(cpy, data) copy(cpy, data)
_, err := precompile.Run(nil, common.Address{}, common.Address{}, cpy, nil, false) _, err := precompile.Run(nil, common.Address{}, common.Address{}, cpy, nil, false, false)
if !bytes.Equal(cpy, data) { if !bytes.Equal(cpy, data) {
panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy)) panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy))
} }

View file

@ -267,7 +267,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase) context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context.GetHash = vmTestBlockHash context.GetHash = vmTestBlockHash
context.BaseFee = baseFee context.BaseFee = baseFee
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig) evm := vm.NewEVM(context, txContext, statedb, config, vmconfig, nil)
// Create "contract" for sender to cache code analysis. // Create "contract" for sender to cache code analysis.
sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From), sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From),

View file

@ -284,7 +284,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
context.Random = &rnd context.Random = &rnd
context.Difficulty = big.NewInt(0) context.Difficulty = big.NewInt(0)
} }
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig) evm := vm.NewEVM(context, txContext, statedb, config, vmconfig, nil)
// Execute the message. // Execute the message.
snapshot := statedb.Snapshot() snapshot := statedb.Snapshot()