Skip to content

Commit

Permalink
Merge pull request #366 from ethereum-optimism/evm-options
Browse files Browse the repository at this point in the history
core/vm: evm options to ignore max-bytecode-size and support caller overriding
  • Loading branch information
protolambda authored Aug 22, 2024
2 parents 5c2e758 + 7a8962c commit 6c8de76
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 8 deletions.
19 changes: 16 additions & 3 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,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 @@ -283,6 +291,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 @@ -337,13 +346,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 @@ -385,6 +395,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 @@ -532,7 +543,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 @@ -582,6 +593,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 @@ -591,6 +603,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
12 changes: 10 additions & 2 deletions fork.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,21 @@ def:
- "core/types/tx_dynamic_fee.go"
- "core/types/tx_legacy.go"
- "core/types/tx_blob.go"
- title: "EVM enhancements"
description: |
Apply L1 cost computation, and add EVM configuration for tooling and more:
- Disable bytecode size-limits (for large test/script contracts).
- Prank (solidity test terminology) the EVM-call message-sender.
- Override precompiles, to insert tooling precompiles and optimize precompile proving.
globs:
- "core/vm/evm.go"
- "core/vm/interpreter.go"
- "core/vm/gas_table.go"
- title: "L1 cost computation"
description: |
Transactions must pay an additional L1 cost based on the amount of rollup-data-gas they consume,
estimated based on gas-price-oracle information and encoded tx size."
globs:
- "core/vm/evm.go"
- "core/evm.go"
- "core/types/rollup_cost.go"
- "core/state_processor.go"
Expand Down Expand Up @@ -117,7 +126,6 @@ def:
description: ""
globs:
- "core/vm/contracts.go"
- "core/vm/interpreter.go"
- "crypto/secp256r1/publickey.go"
- "crypto/secp256r1/verifier.go"
- title: "Chain Configuration"
Expand Down

0 comments on commit 6c8de76

Please sign in to comment.