From ca8184c15152e567cd572dd08729e06702ba9483 Mon Sep 17 00:00:00 2001 From: artheraone <126314488+artheraone@users.noreply.github.com> Date: Fri, 10 Mar 2023 12:47:35 +0200 Subject: [PATCH] Run EWASM contracts --- core/vm/evm.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 148f5fc2c..6e2042bd4 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -17,6 +17,7 @@ package vm import ( + "errors" "github.com/ethereum/evmc/v10/bindings/go/evmc" "math/big" "sync/atomic" @@ -67,6 +68,24 @@ func (evm *EVM) statePrecompile(addr common.Address) (PrecompiledStateContract, 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) { + 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) + } + } + return nil, errors.New("no compatible interpreter") +} + // BlockContext provides the EVM with auxiliary information. Once provided // it shouldn't be modified. type BlockContext struct { @@ -251,7 +270,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 = evm.interpreter.Run(contract, input, false) + ret, err = run(evm, contract, input, false) gas = contract.Gas } } @@ -311,7 +330,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 = evm.interpreter.Run(contract, input, false) + ret, err = run(evm, contract, input, false) gas = contract.Gas } if err != nil { @@ -354,7 +373,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 = evm.interpreter.Run(contract, input, false) + ret, err = run(evm, contract, input, false) gas = contract.Gas } if err != nil { @@ -413,7 +432,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte // When an error was returned by the EVM or when setting the creation code // 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. - ret, err = evm.interpreter.Run(contract, input, true) + ret, err = run(evm, contract, input, true) gas = contract.Gas } if err != nil { @@ -486,7 +505,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, start := time.Now() - ret, err := evm.interpreter.Run(contract, nil, false) + ret, err := run(evm, 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 {