Skip to content

Commit

Permalink
core/vm: evm options to ignore max-bytecode-size and caller overriding
Browse files Browse the repository at this point in the history
Signed-off-by: protolambda <[email protected]>
  • Loading branch information
protolambda authored and karlb committed Sep 10, 2024
1 parent 0ae3784 commit f755ee6
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 6 deletions.
19 changes: 16 additions & 3 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,19 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
return evm.interpreter
}

func (evm *EVM) maybeOverrideCaller(caller ContractRef) ContractRef {
if evm.Config.CallerOverride != nil {
return evm.Config.CallerOverride(caller)
}
return caller
}

// Call executes the contract associated with the addr with the given input as
// parameters. It also handles any necessary value transfer required and takes
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
caller = evm.maybeOverrideCaller(caller)
// Capture the tracer start/end events in debug mode
if evm.Config.Tracer != nil {
evm.captureBegin(evm.depth, CALL, caller.Address(), addr, input, gas, value.ToBig())
Expand Down Expand Up @@ -298,6 +306,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// CallCode differs from Call in the sense that it executes the given address'
// code with the caller as context.
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
caller = evm.maybeOverrideCaller(caller)
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil {
evm.captureBegin(evm.depth, CALLCODE, caller.Address(), addr, input, gas, value.ToBig())
Expand Down Expand Up @@ -352,13 +361,14 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// DelegateCall differs from CallCode in the sense that it executes the given address'
// code with the caller as context and the caller is set to the caller of the caller.
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
caller = evm.maybeOverrideCaller(caller)
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil {
// NOTE: caller must, at all times be a contract. It should never happen
// that caller is something other than a Contract.
parent := caller.(*Contract)
parent := caller.(interface{ Value() *uint256.Int })
// DELEGATECALL inherits value from parent call
evm.captureBegin(evm.depth, DELEGATECALL, caller.Address(), addr, input, gas, parent.value.ToBig())
evm.captureBegin(evm.depth, DELEGATECALL, caller.Address(), addr, input, gas, parent.Value().ToBig())
defer func(startGas uint64) {
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas)
Expand Down Expand Up @@ -400,6 +410,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// Opcodes that attempt to perform such modifications will result in exceptions
// instead of performing the modifications.
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
caller = evm.maybeOverrideCaller(caller)
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil {
evm.captureBegin(evm.depth, STATICCALL, caller.Address(), addr, input, gas, nil)
Expand Down Expand Up @@ -547,7 +558,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}

// Check whether the max code size has been exceeded, assign err if the case.
if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize && !evm.Config.NoMaxCodeSize {
err = ErrMaxCodeSizeExceeded
}

Expand Down Expand Up @@ -597,6 +608,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,

// Create creates a new contract using code as deployment code.
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
caller = evm.maybeOverrideCaller(caller)
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE)
}
Expand All @@ -606,6 +618,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint2
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
caller = evm.maybeOverrideCaller(caller)
codeAndHash := &codeAndHash{code: code}
contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
Expand Down
4 changes: 2 additions & 2 deletions core/vm/gas_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
if overflow {
return 0, ErrGasUintOverflow
}
if size > params.MaxInitCodeSize {
if size > params.MaxInitCodeSize && !evm.Config.NoMaxCodeSize {
return 0, fmt.Errorf("%w: size %d", ErrMaxInitCodeSizeExceeded, size)
}
// Since size <= params.MaxInitCodeSize, these multiplication cannot overflow
Expand All @@ -333,7 +333,7 @@ func gasCreate2Eip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
if overflow {
return 0, ErrGasUintOverflow
}
if size > params.MaxInitCodeSize {
if size > params.MaxInitCodeSize && !evm.Config.NoMaxCodeSize {
return 0, fmt.Errorf("%w: size %d", ErrMaxInitCodeSizeExceeded, size)
}
// Since size <= params.MaxInitCodeSize, these multiplication cannot overflow
Expand Down
4 changes: 3 additions & 1 deletion core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ type Config struct {
ExtraEips []int // Additional EIPS that are to be enabled
EnableWitnessCollection bool // true if witness collection is enabled

PrecompileOverrides PrecompileOverrides // Precompiles can be swapped / changed / wrapped as needed
PrecompileOverrides PrecompileOverrides // Precompiles can be swapped / changed / wrapped as needed
NoMaxCodeSize bool // Ignore Max code size and max init code size limits
CallerOverride func(v ContractRef) ContractRef // Swap the caller as needed, for VM prank functionality.
}

// ScopeContext contains the things that are per-call, such as stack and memory,
Expand Down

0 comments on commit f755ee6

Please sign in to comment.