Skip to content

Commit

Permalink
all: remove noop vm config flags (ethereum#23111)
Browse files Browse the repository at this point in the history
  • Loading branch information
gzliudan committed Oct 17, 2024
1 parent f3f8f59 commit 67e4601
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 73 deletions.
46 changes: 8 additions & 38 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package vm

import (
"errors"
"math/big"
"sync/atomic"
"time"
Expand Down Expand Up @@ -61,29 +60,6 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
return p, ok
}

// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
if evm.ChainConfig().IsTIPXDCXCancellationFee(evm.Context.BlockNumber) {
for _, interpreter := range evm.interpreters {
if interpreter.CanRun(contract.Code) {
if evm.interpreter != interpreter {
// Ensure that the interpreter pointer is set back
// to its current value upon return.
defer func(i Interpreter) {
evm.interpreter = i
}(evm.interpreter)
evm.interpreter = interpreter
}
return interpreter.Run(contract, input, readOnly)
}
}
} else {
return evm.interpreter.Run(contract, input, false)
}

return nil, errors.New("no compatible interpreter")
}

// BlockContext provides the EVM with auxiliary information. Once provided
// it shouldn't be modified.
type BlockContext struct {
Expand Down Expand Up @@ -143,8 +119,7 @@ type EVM struct {
Config Config
// global (to this context) ethereum virtual machine
// used throughout the execution of the tx.
interpreters []Interpreter
interpreter Interpreter
interpreter *EVMInterpreter
// abort is used to abort the EVM calling operations
// NOTE: must be set atomically
abort int32
Expand All @@ -165,14 +140,9 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, tradingStat
Config: config,
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber),
interpreters: make([]Interpreter, 0, 1),
}

// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here
// as we always want to have the built-in EVM as the failover option.
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, config))
evm.interpreter = evm.interpreters[0]

evm.interpreter = NewEVMInterpreter(evm, config)
return evm
}

Expand All @@ -195,7 +165,7 @@ func (evm *EVM) Cancelled() bool {
}

// Interpreter returns the current interpreter
func (evm *EVM) Interpreter() Interpreter {
func (evm *EVM) Interpreter() *EVMInterpreter {
return evm.interpreter
}

Expand Down Expand Up @@ -264,7 +234,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// The depth-check is already done, and precompiles handled above
contract := NewContract(caller, AccountRef(addrCopy), value, gas)
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code)
ret, err = run(evm, contract, input, false)
ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas
}
}
Expand Down Expand Up @@ -321,7 +291,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
ret, err = run(evm, contract, input, false)
ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas
}
if err != nil {
Expand Down Expand Up @@ -361,7 +331,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// Initialise a new contract and make initialise the delegate values
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
ret, err = run(evm, contract, input, false)
ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas
}
if err != nil {
Expand Down Expand Up @@ -418,7 +388,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in Homestead this also counts for code storage gas errors.
readOnly := evm.ChainConfig().IsTIPXDCXCancellationFee(evm.Context.BlockNumber)
ret, err = run(evm, contract, input, readOnly)
ret, err = evm.interpreter.Run(contract, input, readOnly)
gas = contract.Gas
}
if err != nil {
Expand Down Expand Up @@ -489,7 +459,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}
start := time.Now()

ret, err := run(evm, contract, nil, false)
ret, err := evm.interpreter.Run(contract, nil, false)

// Check whether the max code size has been exceeded, assign err if the case.
if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
Expand Down
26 changes: 25 additions & 1 deletion core/vm/instructions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
evmInterpreter = env.interpreter.(*EVMInterpreter)
evmInterpreter = env.interpreter
)

for i, test := range tests {
Expand Down Expand Up @@ -228,6 +228,30 @@ func TestAddMod(t *testing.T) {
}
}

// getResult is a convenience function to generate the expected values
func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
var (
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
interpreter = env.interpreter
)
result := make([]TwoOperandTestcase, len(args))
for i, param := range args {
x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x))
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
stack.push(x)
stack.push(y)
_, err := opFn(&pc, interpreter, &ScopeContext{nil, stack, nil})
if err != nil {
log.Fatalln(err)
}
actual := stack.pop()
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
}
return result
}

// utility function to fill the json-file with testcases
// Enable this test to generate the 'testcases_xx.json' files
func TestWriteExpectedValues(t *testing.T) {
Expand Down
31 changes: 0 additions & 31 deletions core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,9 @@ type Config struct {

JumpTable *JumpTable // EVM instruction table, automatically populated if unset

EWASMInterpreter string // External EWASM interpreter options
EVMInterpreter string // External EVM interpreter options

ExtraEips []int // Additional EIPS that are to be enabled
}

// Interpreter is used to run Ethereum based contracts and will utilise the
// passed environment to query external sources for state information.
// The Interpreter will run the byte code VM based on the passed
// configuration.
type Interpreter interface {
// Run loops and evaluates the contract's code with the given input data and returns
// the return byte-slice and an error if one occurred.
Run(contract *Contract, input []byte, static bool) ([]byte, error)
// CanRun tells if the contract, passed as an argument, can be
// run by the current interpreter. This is meant so that the
// caller can do something like:
//
// ```golang
// for _, interpreter := range interpreters {
// if interpreter.CanRun(contract.code) {
// interpreter.Run(contract.code, input)
// }
// }
// ```
CanRun([]byte) bool
}

// ScopeContext contains the things that are per-call, such as stack and memory,
// but not transients like pc and gas
type ScopeContext struct {
Expand Down Expand Up @@ -274,9 +249,3 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (

return res, err
}

// CanRun tells if the contract, passed as an argument, can be
// run by the current interpreter.
func (in *EVMInterpreter) CanRun(code []byte) bool {
return true
}
10 changes: 7 additions & 3 deletions tests/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,21 @@ func TestState(t *testing.T) {
const traceErrorLimit = 400000

func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
err := test(vm.Config{})
// Use config from command line arguments.
config := vm.Config{}
err := test(config)
if err == nil {
return
}
t.Error(err)

// Test failed, re-run with tracing enabled.
if gasLimit > traceErrorLimit {
t.Log("gas limit too high for EVM trace")
return
}
tracer := vm.NewStructLogger(nil)
err2 := test(vm.Config{Debug: true, Tracer: tracer})
config.Debug, config.Tracer = true, tracer
err2 := test(config)
if !reflect.DeepEqual(err, err2) {
t.Errorf("different error for second run: %v", err2)
}
Expand Down

0 comments on commit 67e4601

Please sign in to comment.