mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
core/vm: fold EVMInterpreter into EVM
the separation serves no purpose atm and the circular dependency that EVM and EVMInterpreter had was begging for them to be merged
This commit is contained in:
parent
e9dca3b181
commit
f4b838b761
8 changed files with 316 additions and 335 deletions
|
|
@ -89,8 +89,8 @@ func enable1884(jt *JumpTable) {
|
|||
}
|
||||
}
|
||||
|
||||
func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
func opSelfBalance(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
balance := evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
scope.Stack.push(balance)
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -108,8 +108,8 @@ func enable1344(jt *JumpTable) {
|
|||
}
|
||||
|
||||
// opChainID implements CHAINID opcode
|
||||
func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
chainId, _ := uint256.FromBig(interpreter.evm.chainConfig.ChainID)
|
||||
func opChainID(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
chainId, _ := uint256.FromBig(evm.chainConfig.ChainID)
|
||||
scope.Stack.push(chainId)
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -199,28 +199,28 @@ func enable1153(jt *JumpTable) {
|
|||
}
|
||||
|
||||
// opTload implements TLOAD opcode
|
||||
func opTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opTload(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
loc := scope.Stack.peek()
|
||||
hash := common.Hash(loc.Bytes32())
|
||||
val := interpreter.evm.StateDB.GetTransientState(scope.Contract.Address(), hash)
|
||||
val := evm.StateDB.GetTransientState(scope.Contract.Address(), hash)
|
||||
loc.SetBytes(val.Bytes())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// opTstore implements TSTORE opcode
|
||||
func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
func opTstore(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
loc := scope.Stack.pop()
|
||||
val := scope.Stack.pop()
|
||||
interpreter.evm.StateDB.SetTransientState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
|
||||
evm.StateDB.SetTransientState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// opBaseFee implements BASEFEE opcode
|
||||
func opBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
baseFee, _ := uint256.FromBig(interpreter.evm.Context.BaseFee)
|
||||
func opBaseFee(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
baseFee, _ := uint256.FromBig(evm.Context.BaseFee)
|
||||
scope.Stack.push(baseFee)
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -237,7 +237,7 @@ func enable3855(jt *JumpTable) {
|
|||
}
|
||||
|
||||
// opPush0 implements the PUSH0 opcode
|
||||
func opPush0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opPush0(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int))
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -263,7 +263,7 @@ func enable5656(jt *JumpTable) {
|
|||
}
|
||||
|
||||
// opMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656)
|
||||
func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMcopy(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
dst = scope.Stack.pop()
|
||||
src = scope.Stack.pop()
|
||||
|
|
@ -276,10 +276,10 @@ func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
|||
}
|
||||
|
||||
// opBlobHash implements the BLOBHASH opcode
|
||||
func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opBlobHash(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
index := scope.Stack.peek()
|
||||
if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) {
|
||||
blobHash := interpreter.evm.TxContext.BlobHashes[index.Uint64()]
|
||||
if index.LtUint64(uint64(len(evm.TxContext.BlobHashes))) {
|
||||
blobHash := evm.TxContext.BlobHashes[index.Uint64()]
|
||||
index.SetBytes32(blobHash[:])
|
||||
} else {
|
||||
index.Clear()
|
||||
|
|
@ -288,14 +288,14 @@ func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
}
|
||||
|
||||
// opBlobBaseFee implements BLOBBASEFEE opcode
|
||||
func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee)
|
||||
func opBlobBaseFee(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
blobBaseFee, _ := uint256.FromBig(evm.Context.BlobBaseFee)
|
||||
scope.Stack.push(blobBaseFee)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// opCLZ implements the CLZ opcode (count leading zero bytes)
|
||||
func opCLZ(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCLZ(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x := scope.Stack.peek()
|
||||
x.SetUint64(256 - uint64(x.BitLen()))
|
||||
return nil, nil
|
||||
|
|
@ -342,7 +342,7 @@ func enable6780(jt *JumpTable) {
|
|||
}
|
||||
}
|
||||
|
||||
func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opExtCodeCopyEIP4762(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
stack = scope.Stack
|
||||
a = stack.pop()
|
||||
|
|
@ -355,10 +355,10 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
|
|||
uint64CodeOffset = math.MaxUint64
|
||||
}
|
||||
addr := common.Address(a.Bytes20())
|
||||
code := interpreter.evm.StateDB.GetCode(addr)
|
||||
code := evm.StateDB.GetCode(addr)
|
||||
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64())
|
||||
consumed, wanted := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(consumed, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
@ -370,7 +370,7 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
|
|||
// opPush1EIP4762 handles the special case of PUSH1 opcode for EIP-4762, which
|
||||
// need not worry about the adjusted bound logic when adding the PUSHDATA to
|
||||
// the list of access events.
|
||||
func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opPush1EIP4762(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
codeLen = uint64(len(scope.Contract.Code))
|
||||
integer = new(uint256.Int)
|
||||
|
|
@ -383,8 +383,8 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
// touch next chunk if PUSH1 is at the boundary. if so, *pc has
|
||||
// advanced past this boundary.
|
||||
contractAddr := scope.Contract.Address()
|
||||
consumed, wanted := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, *pc+1, uint64(1), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(wanted, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(contractAddr, *pc+1, uint64(1), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(wanted, evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
@ -396,7 +396,7 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
}
|
||||
|
||||
func makePushEIP4762(size uint64, pushByteSize int) executionFunc {
|
||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
return func(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
codeLen = len(scope.Contract.Code)
|
||||
start = min(codeLen, int(*pc+1))
|
||||
|
|
@ -411,8 +411,8 @@ func makePushEIP4762(size uint64, pushByteSize int) executionFunc {
|
|||
|
||||
if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall {
|
||||
contractAddr := scope.Contract.Address()
|
||||
consumed, wanted := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(consumed, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
|
@ -95,6 +96,9 @@ type EVM struct {
|
|||
// StateDB gives access to the underlying state
|
||||
StateDB StateDB
|
||||
|
||||
// table holds the opcode specific handlers
|
||||
table *JumpTable
|
||||
|
||||
// depth is the current call stack
|
||||
depth int
|
||||
|
||||
|
|
@ -107,10 +111,6 @@ type EVM struct {
|
|||
// virtual machine configuration options used to initialise the evm
|
||||
Config Config
|
||||
|
||||
// global (to this context) ethereum virtual machine used throughout
|
||||
// the execution of the tx
|
||||
interpreter *EVMInterpreter
|
||||
|
||||
// abort is used to abort the EVM calling operations
|
||||
abort atomic.Bool
|
||||
|
||||
|
|
@ -124,6 +124,12 @@ type EVM struct {
|
|||
|
||||
// jumpDests stores results of JUMPDEST analysis.
|
||||
jumpDests JumpDestCache
|
||||
|
||||
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
|
||||
hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes
|
||||
|
||||
readOnly bool // Whether to throw on stateful modifications
|
||||
returnData []byte // Last CALL's return data for subsequent reuse
|
||||
}
|
||||
|
||||
// NewEVM constructs an EVM instance with the supplied block context, state
|
||||
|
|
@ -138,9 +144,57 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
|
|||
chainConfig: chainConfig,
|
||||
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
|
||||
jumpDests: newMapJumpDests(),
|
||||
hasher: crypto.NewKeccakState(),
|
||||
}
|
||||
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
||||
evm.interpreter = NewEVMInterpreter(evm)
|
||||
|
||||
switch {
|
||||
case evm.chainRules.IsOsaka:
|
||||
evm.table = &osakaInstructionSet
|
||||
case evm.chainRules.IsVerkle:
|
||||
// TODO replace with proper instruction set when fork is specified
|
||||
evm.table = &verkleInstructionSet
|
||||
case evm.chainRules.IsPrague:
|
||||
evm.table = &pragueInstructionSet
|
||||
case evm.chainRules.IsCancun:
|
||||
evm.table = &cancunInstructionSet
|
||||
case evm.chainRules.IsShanghai:
|
||||
evm.table = &shanghaiInstructionSet
|
||||
case evm.chainRules.IsMerge:
|
||||
evm.table = &mergeInstructionSet
|
||||
case evm.chainRules.IsLondon:
|
||||
evm.table = &londonInstructionSet
|
||||
case evm.chainRules.IsBerlin:
|
||||
evm.table = &berlinInstructionSet
|
||||
case evm.chainRules.IsIstanbul:
|
||||
evm.table = &istanbulInstructionSet
|
||||
case evm.chainRules.IsConstantinople:
|
||||
evm.table = &constantinopleInstructionSet
|
||||
case evm.chainRules.IsByzantium:
|
||||
evm.table = &byzantiumInstructionSet
|
||||
case evm.chainRules.IsEIP158:
|
||||
evm.table = &spuriousDragonInstructionSet
|
||||
case evm.chainRules.IsEIP150:
|
||||
evm.table = &tangerineWhistleInstructionSet
|
||||
case evm.chainRules.IsHomestead:
|
||||
evm.table = &homesteadInstructionSet
|
||||
default:
|
||||
evm.table = &frontierInstructionSet
|
||||
}
|
||||
var extraEips []int
|
||||
if len(evm.Config.ExtraEips) > 0 {
|
||||
// Deep-copy jumptable to prevent modification of opcodes in other tables
|
||||
evm.table = copyJumpTable(evm.table)
|
||||
}
|
||||
for _, eip := range evm.Config.ExtraEips {
|
||||
if err := EnableEIP(eip, evm.table); err != nil {
|
||||
// Disable it, so caller can check if it's activated or not
|
||||
log.Error("EIP activation failed", "eip", eip, "error", err)
|
||||
} else {
|
||||
extraEips = append(extraEips, eip)
|
||||
}
|
||||
}
|
||||
evm.Config.ExtraEips = extraEips
|
||||
return evm
|
||||
}
|
||||
|
||||
|
|
@ -176,11 +230,6 @@ func (evm *EVM) Cancelled() bool {
|
|||
return evm.abort.Load()
|
||||
}
|
||||
|
||||
// Interpreter returns the current interpreter
|
||||
func (evm *EVM) Interpreter() *EVMInterpreter {
|
||||
return evm.interpreter
|
||||
}
|
||||
|
||||
func isSystemCall(caller common.Address) bool {
|
||||
return caller == params.SystemAddress
|
||||
}
|
||||
|
|
@ -245,7 +294,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
contract := NewContract(caller, addr, value, gas, evm.jumpDests)
|
||||
contract.IsSystemCall = isSystemCall(caller)
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), code)
|
||||
ret, err = evm.interpreter.Run(contract, input, false)
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
}
|
||||
|
|
@ -304,7 +353,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
// The contract is a scoped environment for this execution context only.
|
||||
contract := NewContract(caller, caller, value, gas, evm.jumpDests)
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
|
||||
ret, err = evm.interpreter.Run(contract, input, false)
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
if err != nil {
|
||||
|
|
@ -348,7 +397,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
// Note: The value refers to the original value from the parent call.
|
||||
contract := NewContract(originCaller, caller, value, gas, evm.jumpDests)
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
|
||||
ret, err = evm.interpreter.Run(contract, input, false)
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
if err != nil {
|
||||
|
|
@ -403,7 +452,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
// 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 = evm.Run(contract, input, true)
|
||||
gas = contract.Gas
|
||||
}
|
||||
if err != nil {
|
||||
|
|
@ -524,7 +573,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
// initNewContract runs a new contract's creation code, performs checks on the
|
||||
// resulting code that is to be deployed, and consumes necessary gas.
|
||||
func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]byte, error) {
|
||||
ret, err := evm.interpreter.Run(contract, nil, false)
|
||||
ret, err := evm.Run(contract, nil, false)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
|
@ -567,7 +616,7 @@ func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
// 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 common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||
inithash := crypto.HashData(evm.interpreter.hasher, code)
|
||||
inithash := crypto.HashData(evm.hasher, code)
|
||||
contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash[:])
|
||||
return evm.create(caller, code, gas, endowment, contractAddr, CREATE2)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,67 +26,67 @@ import (
|
|||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opAdd(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Add(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSub(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Sub(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMul(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Mul(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opDiv(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Div(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSdiv(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.SDiv(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMod(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Mod(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSmod(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.SMod(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opExp(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
base, exponent := scope.Stack.pop(), scope.Stack.peek()
|
||||
exponent.Exp(&base, exponent)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSignExtend(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
back, num := scope.Stack.pop(), scope.Stack.peek()
|
||||
num.ExtendSign(num, &back)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opNot(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x := scope.Stack.peek()
|
||||
x.Not(x)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opLt(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
if x.Lt(y) {
|
||||
y.SetOne()
|
||||
|
|
@ -96,7 +96,7 @@ func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opGt(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
if x.Gt(y) {
|
||||
y.SetOne()
|
||||
|
|
@ -106,7 +106,7 @@ func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSlt(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
if x.Slt(y) {
|
||||
y.SetOne()
|
||||
|
|
@ -116,7 +116,7 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSgt(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
if x.Sgt(y) {
|
||||
y.SetOne()
|
||||
|
|
@ -126,7 +126,7 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opEq(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
if x.Eq(y) {
|
||||
y.SetOne()
|
||||
|
|
@ -136,7 +136,7 @@ func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opIszero(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x := scope.Stack.peek()
|
||||
if x.IsZero() {
|
||||
x.SetOne()
|
||||
|
|
@ -146,37 +146,37 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opAnd(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.And(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opOr(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Or(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opXor(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Xor(&x, y)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opByte(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
th, val := scope.Stack.pop(), scope.Stack.peek()
|
||||
val.Byte(&th)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opAddmod(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek()
|
||||
z.AddMod(&x, &y, z)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMulmod(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek()
|
||||
z.MulMod(&x, &y, z)
|
||||
return nil, nil
|
||||
|
|
@ -185,7 +185,7 @@ func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
|||
// opSHL implements Shift Left
|
||||
// The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2,
|
||||
// and pushes on the stack arg2 shifted to the left by arg1 number of bits.
|
||||
func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSHL(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
|
||||
shift, value := scope.Stack.pop(), scope.Stack.peek()
|
||||
if shift.LtUint64(256) {
|
||||
|
|
@ -199,7 +199,7 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
|||
// opSHR implements Logical Shift Right
|
||||
// The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2,
|
||||
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
|
||||
func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSHR(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
|
||||
shift, value := scope.Stack.pop(), scope.Stack.peek()
|
||||
if shift.LtUint64(256) {
|
||||
|
|
@ -213,7 +213,7 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
|||
// opSAR implements Arithmetic Shift Right
|
||||
// The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2,
|
||||
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
|
||||
func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSAR(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
shift, value := scope.Stack.pop(), scope.Stack.peek()
|
||||
if shift.GtUint64(256) {
|
||||
if value.Sign() >= 0 {
|
||||
|
|
@ -229,50 +229,49 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opKeccak256(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
offset, size := scope.Stack.pop(), scope.Stack.peek()
|
||||
data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64())
|
||||
|
||||
interpreter.hasher.Reset()
|
||||
interpreter.hasher.Write(data)
|
||||
interpreter.hasher.Read(interpreter.hasherBuf[:])
|
||||
evm.hasher.Reset()
|
||||
evm.hasher.Write(data)
|
||||
evm.hasher.Read(evm.hasherBuf[:])
|
||||
|
||||
evm := interpreter.evm
|
||||
if evm.Config.EnablePreimageRecording {
|
||||
evm.StateDB.AddPreimage(interpreter.hasherBuf, data)
|
||||
evm.StateDB.AddPreimage(evm.hasherBuf, data)
|
||||
}
|
||||
size.SetBytes(interpreter.hasherBuf[:])
|
||||
size.SetBytes(evm.hasherBuf[:])
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opAddress(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes()))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opBalance(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
slot := scope.Stack.peek()
|
||||
address := common.Address(slot.Bytes20())
|
||||
slot.Set(interpreter.evm.StateDB.GetBalance(address))
|
||||
slot.Set(evm.StateDB.GetBalance(address))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes()))
|
||||
func opOrigin(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetBytes(evm.Origin.Bytes()))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCaller(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes()))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCallValue(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(scope.Contract.value)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCallDataLoad(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
x := scope.Stack.peek()
|
||||
if offset, overflow := x.Uint64WithOverflow(); !overflow {
|
||||
data := getData(scope.Contract.Input, offset, 32)
|
||||
|
|
@ -283,12 +282,12 @@ func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCallDataSize(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Input))))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCallDataCopy(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
memOffset = scope.Stack.pop()
|
||||
dataOffset = scope.Stack.pop()
|
||||
|
|
@ -306,12 +305,12 @@ func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData))))
|
||||
func opReturnDataSize(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(evm.returnData))))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opReturnDataCopy(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
memOffset = scope.Stack.pop()
|
||||
dataOffset = scope.Stack.pop()
|
||||
|
|
@ -326,25 +325,25 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
|||
var end = dataOffset
|
||||
end.Add(&dataOffset, &length)
|
||||
end64, overflow := end.Uint64WithOverflow()
|
||||
if overflow || uint64(len(interpreter.returnData)) < end64 {
|
||||
if overflow || uint64(len(evm.returnData)) < end64 {
|
||||
return nil, ErrReturnDataOutOfBounds
|
||||
}
|
||||
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[offset64:end64])
|
||||
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), evm.returnData[offset64:end64])
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opExtCodeSize(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
slot := scope.Stack.peek()
|
||||
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20())))
|
||||
slot.SetUint64(uint64(evm.StateDB.GetCodeSize(slot.Bytes20())))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCodeSize(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Code))))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCodeCopy(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
memOffset = scope.Stack.pop()
|
||||
codeOffset = scope.Stack.pop()
|
||||
|
|
@ -360,7 +359,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opExtCodeCopy(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
stack = scope.Stack
|
||||
a = stack.pop()
|
||||
|
|
@ -373,7 +372,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
uint64CodeOffset = math.MaxUint64
|
||||
}
|
||||
addr := common.Address(a.Bytes20())
|
||||
code := interpreter.evm.StateDB.GetCode(addr)
|
||||
code := evm.StateDB.GetCode(addr)
|
||||
codeCopy := getData(code, uint64CodeOffset, length.Uint64())
|
||||
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
|
||||
|
||||
|
|
@ -406,24 +405,24 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
//
|
||||
// 6. Caller tries to get the code hash for an account which is marked as deleted, this
|
||||
// account should be regarded as a non-existent account and zero should be returned.
|
||||
func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opExtCodeHash(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
slot := scope.Stack.peek()
|
||||
address := common.Address(slot.Bytes20())
|
||||
if interpreter.evm.StateDB.Empty(address) {
|
||||
if evm.StateDB.Empty(address) {
|
||||
slot.Clear()
|
||||
} else {
|
||||
slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes())
|
||||
slot.SetBytes(evm.StateDB.GetCodeHash(address).Bytes())
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
v, _ := uint256.FromBig(interpreter.evm.GasPrice)
|
||||
func opGasprice(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
v, _ := uint256.FromBig(evm.GasPrice)
|
||||
scope.Stack.push(v)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opBlockhash(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
num := scope.Stack.peek()
|
||||
num64, overflow := num.Uint64WithOverflow()
|
||||
if overflow {
|
||||
|
|
@ -432,18 +431,18 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
|
|||
}
|
||||
|
||||
var upper, lower uint64
|
||||
upper = interpreter.evm.Context.BlockNumber.Uint64()
|
||||
upper = evm.Context.BlockNumber.Uint64()
|
||||
if upper < 257 {
|
||||
lower = 0
|
||||
} else {
|
||||
lower = upper - 256
|
||||
}
|
||||
if num64 >= lower && num64 < upper {
|
||||
res := interpreter.evm.Context.GetHash(num64)
|
||||
if witness := interpreter.evm.StateDB.Witness(); witness != nil {
|
||||
res := evm.Context.GetHash(num64)
|
||||
if witness := evm.StateDB.Witness(); witness != nil {
|
||||
witness.AddBlockHash(num64)
|
||||
}
|
||||
if tracer := interpreter.evm.Config.Tracer; tracer != nil && tracer.OnBlockHashRead != nil {
|
||||
if tracer := evm.Config.Tracer; tracer != nil && tracer.OnBlockHashRead != nil {
|
||||
tracer.OnBlockHashRead(num64, res)
|
||||
}
|
||||
num.SetBytes(res[:])
|
||||
|
|
@ -453,83 +452,83 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
|
||||
func opCoinbase(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetBytes(evm.Context.Coinbase.Bytes()))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.Time))
|
||||
func opTimestamp(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(evm.Context.Time))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opNumber(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber)
|
||||
func opNumber(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
v, _ := uint256.FromBig(evm.Context.BlockNumber)
|
||||
scope.Stack.push(v)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty)
|
||||
func opDifficulty(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
v, _ := uint256.FromBig(evm.Context.Difficulty)
|
||||
scope.Stack.push(v)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes())
|
||||
func opRandom(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
v := new(uint256.Int).SetBytes(evm.Context.Random.Bytes())
|
||||
scope.Stack.push(v)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
|
||||
func opGasLimit(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(evm.Context.GasLimit))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opPop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opPop(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.pop()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMload(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
v := scope.Stack.peek()
|
||||
offset := v.Uint64()
|
||||
v.SetBytes(scope.Memory.GetPtr(offset, 32))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMstore(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
mStart, val := scope.Stack.pop(), scope.Stack.pop()
|
||||
scope.Memory.Set32(mStart.Uint64(), &val)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMstore8(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
off, val := scope.Stack.pop(), scope.Stack.pop()
|
||||
scope.Memory.store[off.Uint64()] = byte(val.Uint64())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSload(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
loc := scope.Stack.peek()
|
||||
hash := common.Hash(loc.Bytes32())
|
||||
val := interpreter.evm.StateDB.GetState(scope.Contract.Address(), hash)
|
||||
val := evm.StateDB.GetState(scope.Contract.Address(), hash)
|
||||
loc.SetBytes(val.Bytes())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
func opSstore(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
loc := scope.Stack.pop()
|
||||
val := scope.Stack.pop()
|
||||
interpreter.evm.StateDB.SetState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
|
||||
evm.StateDB.SetState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opJump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.evm.abort.Load() {
|
||||
func opJump(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.abort.Load() {
|
||||
return nil, errStopToken
|
||||
}
|
||||
pos := scope.Stack.pop()
|
||||
|
|
@ -540,8 +539,8 @@ func opJump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opJumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.evm.abort.Load() {
|
||||
func opJumpi(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.abort.Load() {
|
||||
return nil, errStopToken
|
||||
}
|
||||
pos, cond := scope.Stack.pop(), scope.Stack.pop()
|
||||
|
|
@ -554,107 +553,107 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opJumpdest(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opJumpdest(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opPc(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opPc(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(*pc))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMsize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opMsize(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(uint64(scope.Memory.Len())))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opGas(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opGas(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(new(uint256.Int).SetUint64(scope.Contract.Gas))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap1(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap1()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap2()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap3(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap3()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap4(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap4()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap5(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap5(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap5()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap6(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap6(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap6()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap7(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap7(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap7()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap8(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap8()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap9(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap9(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap9()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap10(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap10(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap10()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap11(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap11(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap11()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap12(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap12(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap12()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap13(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap13(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap13()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap14(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap14(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap14()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap15(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap15(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap15()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSwap16(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opSwap16(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.swap16()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
var (
|
||||
|
|
@ -663,21 +662,21 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
|||
input = scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
|
||||
gas = scope.Contract.Gas
|
||||
)
|
||||
if interpreter.evm.chainRules.IsEIP150 {
|
||||
if evm.chainRules.IsEIP150 {
|
||||
gas -= gas / 64
|
||||
}
|
||||
|
||||
// reuse size int for stackvalue
|
||||
stackvalue := size
|
||||
|
||||
scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation)
|
||||
scope.Contract.UseGas(gas, evm.Config.Tracer, tracing.GasChangeCallContractCreation)
|
||||
|
||||
res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract.Address(), input, gas, &value)
|
||||
res, addr, returnGas, suberr := evm.Create(scope.Contract.Address(), input, gas, &value)
|
||||
// Push item on the stack based on the returned error. If the ruleset is
|
||||
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
||||
// rule) and treat as an error, if the ruleset is frontier we must
|
||||
// ignore this error and pretend the operation was successful.
|
||||
if interpreter.evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas {
|
||||
if evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas {
|
||||
stackvalue.Clear()
|
||||
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
|
||||
stackvalue.Clear()
|
||||
|
|
@ -686,18 +685,18 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
|||
}
|
||||
scope.Stack.push(&stackvalue)
|
||||
|
||||
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
if suberr == ErrExecutionReverted {
|
||||
interpreter.returnData = res // set REVERT data to return data buffer
|
||||
evm.returnData = res // set REVERT data to return data buffer
|
||||
return res, nil
|
||||
}
|
||||
interpreter.returnData = nil // clear dirty return data buffer
|
||||
evm.returnData = nil // clear dirty return data buffer
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
var (
|
||||
|
|
@ -710,10 +709,10 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
|||
|
||||
// Apply EIP150
|
||||
gas -= gas / 64
|
||||
scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation2)
|
||||
scope.Contract.UseGas(gas, evm.Config.Tracer, tracing.GasChangeCallContractCreation2)
|
||||
// reuse size int for stackvalue
|
||||
stackvalue := size
|
||||
res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract.Address(), input, gas,
|
||||
res, addr, returnGas, suberr := evm.Create2(scope.Contract.Address(), input, gas,
|
||||
&endowment, &salt)
|
||||
// Push item on the stack based on the returned error.
|
||||
if suberr != nil {
|
||||
|
|
@ -722,35 +721,35 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
|||
stackvalue.SetBytes(addr.Bytes())
|
||||
}
|
||||
scope.Stack.push(&stackvalue)
|
||||
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
if suberr == ErrExecutionReverted {
|
||||
interpreter.returnData = res // set REVERT data to return data buffer
|
||||
evm.returnData = res // set REVERT data to return data buffer
|
||||
return res, nil
|
||||
}
|
||||
interpreter.returnData = nil // clear dirty return data buffer
|
||||
evm.returnData = nil // clear dirty return data buffer
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
stack := scope.Stack
|
||||
// Pop gas. The actual gas in interpreter.evm.callGasTemp.
|
||||
// Pop gas. The actual gas in evm.callGasTemp.
|
||||
// We can use this as a temporary value
|
||||
temp := stack.pop()
|
||||
gas := interpreter.evm.callGasTemp
|
||||
gas := evm.callGasTemp
|
||||
// Pop other call parameters.
|
||||
addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
||||
toAddr := common.Address(addr.Bytes20())
|
||||
// Get the arguments from the memory.
|
||||
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
|
||||
|
||||
if interpreter.readOnly && !value.IsZero() {
|
||||
if evm.readOnly && !value.IsZero() {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
if !value.IsZero() {
|
||||
gas += params.CallStipend
|
||||
}
|
||||
ret, returnGas, err := interpreter.evm.Call(scope.Contract.Address(), toAddr, args, gas, &value)
|
||||
ret, returnGas, err := evm.Call(scope.Contract.Address(), toAddr, args, gas, &value)
|
||||
|
||||
if err != nil {
|
||||
temp.Clear()
|
||||
|
|
@ -762,18 +761,18 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
interpreter.returnData = ret
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
|
||||
func opCallCode(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
// Pop gas. The actual gas is in evm.callGasTemp.
|
||||
stack := scope.Stack
|
||||
// We use it as a temporary value
|
||||
temp := stack.pop()
|
||||
gas := interpreter.evm.callGasTemp
|
||||
gas := evm.callGasTemp
|
||||
// Pop other call parameters.
|
||||
addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
||||
toAddr := common.Address(addr.Bytes20())
|
||||
|
|
@ -784,7 +783,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
gas += params.CallStipend
|
||||
}
|
||||
|
||||
ret, returnGas, err := interpreter.evm.CallCode(scope.Contract.Address(), toAddr, args, gas, &value)
|
||||
ret, returnGas, err := evm.CallCode(scope.Contract.Address(), toAddr, args, gas, &value)
|
||||
if err != nil {
|
||||
temp.Clear()
|
||||
} else {
|
||||
|
|
@ -795,25 +794,25 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
interpreter.returnData = ret
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opDelegateCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
stack := scope.Stack
|
||||
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
|
||||
// Pop gas. The actual gas is in evm.callGasTemp.
|
||||
// We use it as a temporary value
|
||||
temp := stack.pop()
|
||||
gas := interpreter.evm.callGasTemp
|
||||
gas := evm.callGasTemp
|
||||
// Pop other call parameters.
|
||||
addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
||||
toAddr := common.Address(addr.Bytes20())
|
||||
// Get arguments from the memory.
|
||||
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
|
||||
|
||||
ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract.Caller(), scope.Contract.Address(), toAddr, args, gas, scope.Contract.value)
|
||||
ret, returnGas, err := evm.DelegateCall(scope.Contract.Caller(), scope.Contract.Address(), toAddr, args, gas, scope.Contract.value)
|
||||
if err != nil {
|
||||
temp.Clear()
|
||||
} else {
|
||||
|
|
@ -824,25 +823,25 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
interpreter.returnData = ret
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
|
||||
func opStaticCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
// Pop gas. The actual gas is in evm.callGasTemp.
|
||||
stack := scope.Stack
|
||||
// We use it as a temporary value
|
||||
temp := stack.pop()
|
||||
gas := interpreter.evm.callGasTemp
|
||||
gas := evm.callGasTemp
|
||||
// Pop other call parameters.
|
||||
addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
||||
toAddr := common.Address(addr.Bytes20())
|
||||
// Get arguments from the memory.
|
||||
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
|
||||
|
||||
ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract.Address(), toAddr, args, gas)
|
||||
ret, returnGas, err := evm.StaticCall(scope.Contract.Address(), toAddr, args, gas)
|
||||
if err != nil {
|
||||
temp.Clear()
|
||||
} else {
|
||||
|
|
@ -853,69 +852,69 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
interpreter.returnData = ret
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func opReturn(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opReturn(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
offset, size := scope.Stack.pop(), scope.Stack.pop()
|
||||
ret := scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
|
||||
|
||||
return ret, errStopToken
|
||||
}
|
||||
|
||||
func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opRevert(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
offset, size := scope.Stack.pop(), scope.Stack.pop()
|
||||
ret := scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
|
||||
|
||||
interpreter.returnData = ret
|
||||
evm.returnData = ret
|
||||
return ret, ErrExecutionReverted
|
||||
}
|
||||
|
||||
func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opUndefined(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.Code[*pc])}
|
||||
}
|
||||
|
||||
func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opStop(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
return nil, errStopToken
|
||||
}
|
||||
|
||||
func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
beneficiary := scope.Stack.pop()
|
||||
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
interpreter.evm.StateDB.SelfDestruct(scope.Contract.Address())
|
||||
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
|
||||
balance := evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
evm.StateDB.SelfDestruct(scope.Contract.Address())
|
||||
if tracer := evm.Config.Tracer; tracer != nil {
|
||||
if tracer.OnEnter != nil {
|
||||
tracer.OnEnter(interpreter.evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
}
|
||||
if tracer.OnExit != nil {
|
||||
tracer.OnExit(interpreter.evm.depth, []byte{}, 0, nil, false)
|
||||
tracer.OnExit(evm.depth, []byte{}, 0, nil, false)
|
||||
}
|
||||
}
|
||||
return nil, errStopToken
|
||||
}
|
||||
|
||||
func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
beneficiary := scope.Stack.pop()
|
||||
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)
|
||||
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
interpreter.evm.StateDB.SelfDestruct6780(scope.Contract.Address())
|
||||
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
|
||||
balance := evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)
|
||||
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
evm.StateDB.SelfDestruct6780(scope.Contract.Address())
|
||||
if tracer := evm.Config.Tracer; tracer != nil {
|
||||
if tracer.OnEnter != nil {
|
||||
tracer.OnEnter(interpreter.evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
}
|
||||
if tracer.OnExit != nil {
|
||||
tracer.OnExit(interpreter.evm.depth, []byte{}, 0, nil, false)
|
||||
tracer.OnExit(evm.depth, []byte{}, 0, nil, false)
|
||||
}
|
||||
}
|
||||
return nil, errStopToken
|
||||
|
|
@ -925,8 +924,8 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
|
|||
|
||||
// make log instruction function
|
||||
func makeLog(size int) executionFunc {
|
||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return func(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
topics := make([]common.Hash, size)
|
||||
|
|
@ -938,13 +937,13 @@ func makeLog(size int) executionFunc {
|
|||
}
|
||||
|
||||
d := scope.Memory.GetCopy(mStart.Uint64(), mSize.Uint64())
|
||||
interpreter.evm.StateDB.AddLog(&types.Log{
|
||||
evm.StateDB.AddLog(&types.Log{
|
||||
Address: scope.Contract.Address(),
|
||||
Topics: topics,
|
||||
Data: d,
|
||||
// This is a non-consensus field, but assigned here because
|
||||
// core/state doesn't know the current block number.
|
||||
BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(),
|
||||
BlockNumber: evm.Context.BlockNumber.Uint64(),
|
||||
})
|
||||
|
||||
return nil, nil
|
||||
|
|
@ -952,7 +951,7 @@ func makeLog(size int) executionFunc {
|
|||
}
|
||||
|
||||
// opPush1 is a specialized version of pushN
|
||||
func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opPush1(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
codeLen = uint64(len(scope.Contract.Code))
|
||||
integer = new(uint256.Int)
|
||||
|
|
@ -967,7 +966,7 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
|||
}
|
||||
|
||||
// opPush2 is a specialized version of pushN
|
||||
func opPush2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
func opPush2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
codeLen = uint64(len(scope.Contract.Code))
|
||||
integer = new(uint256.Int)
|
||||
|
|
@ -985,7 +984,7 @@ func opPush2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
|||
|
||||
// make push instruction function
|
||||
func makePush(size uint64, pushByteSize int) executionFunc {
|
||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
return func(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
codeLen = len(scope.Contract.Code)
|
||||
start = min(codeLen, int(*pc+1))
|
||||
|
|
@ -1005,7 +1004,7 @@ func makePush(size uint64, pushByteSize int) executionFunc {
|
|||
|
||||
// make dup instruction function
|
||||
func makeDup(size int64) executionFunc {
|
||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
return func(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.dup(int(size))
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
|
|||
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
|
||||
stack.push(x)
|
||||
stack.push(y)
|
||||
opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||
opFn(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
if len(stack.data) != 1 {
|
||||
t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
|
||||
}
|
||||
|
|
@ -221,7 +221,7 @@ func TestAddMod(t *testing.T) {
|
|||
stack.push(z)
|
||||
stack.push(y)
|
||||
stack.push(x)
|
||||
opAddmod(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||
opAddmod(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
actual := stack.pop()
|
||||
if actual.Cmp(expected) != 0 {
|
||||
t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
|
||||
|
|
@ -247,7 +247,7 @@ func TestWriteExpectedValues(t *testing.T) {
|
|||
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
|
||||
stack.push(x)
|
||||
stack.push(y)
|
||||
opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||
opFn(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
actual := stack.pop()
|
||||
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
|
||||
}
|
||||
|
|
@ -296,7 +296,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
|||
for _, arg := range intArgs {
|
||||
stack.push(arg)
|
||||
}
|
||||
op(&pc, evm.interpreter, scope)
|
||||
op(&pc, evm, scope)
|
||||
stack.pop()
|
||||
}
|
||||
bench.StopTimer()
|
||||
|
|
@ -528,13 +528,13 @@ func TestOpMstore(t *testing.T) {
|
|||
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
||||
stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
|
||||
stack.push(new(uint256.Int))
|
||||
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
|
||||
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
|
||||
}
|
||||
stack.push(new(uint256.Int).SetUint64(0x1))
|
||||
stack.push(new(uint256.Int))
|
||||
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
||||
t.Fatalf("Mstore failed to overwrite previous value")
|
||||
}
|
||||
|
|
@ -555,7 +555,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
|||
for i := 0; i < bench.N; i++ {
|
||||
stack.push(value)
|
||||
stack.push(memStart)
|
||||
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -581,14 +581,14 @@ func TestOpTstore(t *testing.T) {
|
|||
stack.push(new(uint256.Int).SetBytes(value))
|
||||
// push the location to the stack
|
||||
stack.push(new(uint256.Int))
|
||||
opTstore(&pc, evm.interpreter, &scopeContext)
|
||||
opTstore(&pc, evm, &scopeContext)
|
||||
// there should be no elements on the stack after TSTORE
|
||||
if stack.len() != 0 {
|
||||
t.Fatal("stack wrong size")
|
||||
}
|
||||
// push the location to the stack
|
||||
stack.push(new(uint256.Int))
|
||||
opTload(&pc, evm.interpreter, &scopeContext)
|
||||
opTload(&pc, evm, &scopeContext)
|
||||
// there should be one element on the stack after TLOAD
|
||||
if stack.len() != 1 {
|
||||
t.Fatal("stack wrong size")
|
||||
|
|
@ -613,7 +613,7 @@ func BenchmarkOpKeccak256(bench *testing.B) {
|
|||
for i := 0; i < bench.N; i++ {
|
||||
stack.push(uint256.NewInt(32))
|
||||
stack.push(start)
|
||||
opKeccak256(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opKeccak256(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -707,7 +707,7 @@ func TestRandom(t *testing.T) {
|
|||
stack = newstack()
|
||||
pc = uint64(0)
|
||||
)
|
||||
opRandom(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||
opRandom(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
if len(stack.data) != 1 {
|
||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
||||
}
|
||||
|
|
@ -749,7 +749,7 @@ func TestBlobHash(t *testing.T) {
|
|||
)
|
||||
evm.SetTxContext(TxContext{BlobHashes: tt.hashes})
|
||||
stack.push(uint256.NewInt(tt.idx))
|
||||
opBlobHash(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||
opBlobHash(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
if len(stack.data) != 1 {
|
||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
||||
}
|
||||
|
|
@ -889,7 +889,7 @@ func TestOpMCopy(t *testing.T) {
|
|||
mem.Resize(memorySize)
|
||||
}
|
||||
// Do the copy
|
||||
opMcopy(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opMcopy(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
|
||||
if have := mem.store; !bytes.Equal(want, have) {
|
||||
t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
|
||||
|
|
@ -1001,7 +1001,7 @@ func TestOpCLZ(t *testing.T) {
|
|||
}
|
||||
|
||||
stack.push(val)
|
||||
opCLZ(&pc, evm.interpreter, &ScopeContext{Stack: stack})
|
||||
opCLZ(&pc, evm, &ScopeContext{Stack: stack})
|
||||
|
||||
if gotLen := stack.len(); gotLen != 1 {
|
||||
t.Fatalf("stack length = %d; want 1", gotLen)
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -89,93 +87,27 @@ func (ctx *ScopeContext) ContractCode() []byte {
|
|||
return ctx.Contract.Code
|
||||
}
|
||||
|
||||
// EVMInterpreter represents an EVM interpreter
|
||||
type EVMInterpreter struct {
|
||||
evm *EVM
|
||||
table *JumpTable
|
||||
|
||||
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
|
||||
hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes
|
||||
|
||||
readOnly bool // Whether to throw on stateful modifications
|
||||
returnData []byte // Last CALL's return data for subsequent reuse
|
||||
}
|
||||
|
||||
// NewEVMInterpreter returns a new instance of the Interpreter.
|
||||
func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||
// If jump table was not initialised we set the default one.
|
||||
var table *JumpTable
|
||||
switch {
|
||||
case evm.chainRules.IsOsaka:
|
||||
table = &osakaInstructionSet
|
||||
case evm.chainRules.IsVerkle:
|
||||
// TODO replace with proper instruction set when fork is specified
|
||||
table = &verkleInstructionSet
|
||||
case evm.chainRules.IsPrague:
|
||||
table = &pragueInstructionSet
|
||||
case evm.chainRules.IsCancun:
|
||||
table = &cancunInstructionSet
|
||||
case evm.chainRules.IsShanghai:
|
||||
table = &shanghaiInstructionSet
|
||||
case evm.chainRules.IsMerge:
|
||||
table = &mergeInstructionSet
|
||||
case evm.chainRules.IsLondon:
|
||||
table = &londonInstructionSet
|
||||
case evm.chainRules.IsBerlin:
|
||||
table = &berlinInstructionSet
|
||||
case evm.chainRules.IsIstanbul:
|
||||
table = &istanbulInstructionSet
|
||||
case evm.chainRules.IsConstantinople:
|
||||
table = &constantinopleInstructionSet
|
||||
case evm.chainRules.IsByzantium:
|
||||
table = &byzantiumInstructionSet
|
||||
case evm.chainRules.IsEIP158:
|
||||
table = &spuriousDragonInstructionSet
|
||||
case evm.chainRules.IsEIP150:
|
||||
table = &tangerineWhistleInstructionSet
|
||||
case evm.chainRules.IsHomestead:
|
||||
table = &homesteadInstructionSet
|
||||
default:
|
||||
table = &frontierInstructionSet
|
||||
}
|
||||
var extraEips []int
|
||||
if len(evm.Config.ExtraEips) > 0 {
|
||||
// Deep-copy jumptable to prevent modification of opcodes in other tables
|
||||
table = copyJumpTable(table)
|
||||
}
|
||||
for _, eip := range evm.Config.ExtraEips {
|
||||
if err := EnableEIP(eip, table); err != nil {
|
||||
// Disable it, so caller can check if it's activated or not
|
||||
log.Error("EIP activation failed", "eip", eip, "error", err)
|
||||
} else {
|
||||
extraEips = append(extraEips, eip)
|
||||
}
|
||||
}
|
||||
evm.Config.ExtraEips = extraEips
|
||||
return &EVMInterpreter{evm: evm, table: table, hasher: crypto.NewKeccakState()}
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// It's important to note that any errors returned by the interpreter should be
|
||||
// considered a revert-and-consume-all-gas operation except for
|
||||
// ErrExecutionReverted which means revert-and-keep-gas-left.
|
||||
func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
|
||||
func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
|
||||
// Increment the call depth which is restricted to 1024
|
||||
in.evm.depth++
|
||||
defer func() { in.evm.depth-- }()
|
||||
evm.depth++
|
||||
defer func() { evm.depth-- }()
|
||||
|
||||
// Make sure the readOnly is only set if we aren't in readOnly yet.
|
||||
// This also makes sure that the readOnly flag isn't removed for child calls.
|
||||
if readOnly && !in.readOnly {
|
||||
in.readOnly = true
|
||||
defer func() { in.readOnly = false }()
|
||||
if readOnly && !evm.readOnly {
|
||||
evm.readOnly = true
|
||||
defer func() { evm.readOnly = false }()
|
||||
}
|
||||
|
||||
// Reset the previous call's return data. It's unimportant to preserve the old buffer
|
||||
// as every returning call will return new data anyway.
|
||||
in.returnData = nil
|
||||
evm.returnData = nil
|
||||
|
||||
// Don't bother with the execution if there's no code.
|
||||
if len(contract.Code) == 0 {
|
||||
|
|
@ -184,7 +116,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
|
||||
var (
|
||||
op OpCode // current opcode
|
||||
jumpTable *JumpTable = in.table
|
||||
jumpTable *JumpTable = evm.table
|
||||
mem = NewMemory() // bound memory
|
||||
stack = newstack() // local stack
|
||||
callContext = &ScopeContext{
|
||||
|
|
@ -198,11 +130,12 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
pc = uint64(0) // program counter
|
||||
cost uint64
|
||||
// copies used by tracer
|
||||
pcCopy uint64 // needed for the deferred EVMLogger
|
||||
gasCopy uint64 // for EVMLogger to log gas remaining before execution
|
||||
logged bool // deferred EVMLogger should ignore already logged steps
|
||||
res []byte // result of the opcode execution function
|
||||
debug = in.evm.Config.Tracer != nil
|
||||
pcCopy uint64 // needed for the deferred EVMLogger
|
||||
gasCopy uint64 // for EVMLogger to log gas remaining before execution
|
||||
logged bool // deferred EVMLogger should ignore already logged steps
|
||||
res []byte // result of the opcode execution function
|
||||
debug = evm.Config.Tracer != nil
|
||||
isEIP4762 = evm.chainRules.IsEIP4762
|
||||
)
|
||||
// Don't move this deferred function, it's placed before the OnOpcode-deferred method,
|
||||
// so that it gets executed _after_: the OnOpcode needs the stacks before
|
||||
|
|
@ -218,11 +151,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
if err == nil {
|
||||
return
|
||||
}
|
||||
if !logged && in.evm.Config.Tracer.OnOpcode != nil {
|
||||
in.evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, in.returnData, in.evm.depth, VMErrorFromErr(err))
|
||||
if !logged && evm.Config.Tracer.OnOpcode != nil {
|
||||
evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
if logged && in.evm.Config.Tracer.OnFault != nil {
|
||||
in.evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, in.evm.depth, VMErrorFromErr(err))
|
||||
if logged && evm.Config.Tracer.OnFault != nil {
|
||||
evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
@ -237,12 +170,12 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
logged, pcCopy, gasCopy = false, pc, contract.Gas
|
||||
}
|
||||
|
||||
if in.evm.chainRules.IsEIP4762 && !contract.IsDeployment && !contract.IsSystemCall {
|
||||
if isEIP4762 && !contract.IsDeployment && !contract.IsSystemCall {
|
||||
// if the PC ends up in a new "chunk" of verkleized code, charge the
|
||||
// associated costs.
|
||||
contractAddr := contract.Address()
|
||||
consumed, wanted := in.evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, pc, 1, uint64(len(contract.Code)), false, contract.Gas)
|
||||
contract.UseGas(consumed, in.evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk)
|
||||
consumed, wanted := evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, pc, 1, uint64(len(contract.Code)), false, contract.Gas)
|
||||
contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
@ -287,7 +220,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
// Consume the gas and return an error if not enough gas is available.
|
||||
// cost is explicitly set so that the capture state defer method can get the proper cost
|
||||
var dynamicCost uint64
|
||||
dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize)
|
||||
dynamicCost, err = operation.dynamicGas(evm, contract, stack, mem, memorySize)
|
||||
cost += dynamicCost // for tracing
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
|
|
@ -302,11 +235,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
|
||||
// Do tracing before potential memory expansion
|
||||
if debug {
|
||||
if in.evm.Config.Tracer.OnGasChange != nil {
|
||||
in.evm.Config.Tracer.OnGasChange(gasCopy, gasCopy-cost, tracing.GasChangeCallOpCode)
|
||||
if evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gasCopy, gasCopy-cost, tracing.GasChangeCallOpCode)
|
||||
}
|
||||
if in.evm.Config.Tracer.OnOpcode != nil {
|
||||
in.evm.Config.Tracer.OnOpcode(pc, byte(op), gasCopy, cost, callContext, in.returnData, in.evm.depth, VMErrorFromErr(err))
|
||||
if evm.Config.Tracer.OnOpcode != nil {
|
||||
evm.Config.Tracer.OnOpcode(pc, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
logged = true
|
||||
}
|
||||
}
|
||||
|
|
@ -315,7 +248,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
}
|
||||
|
||||
// execute the operation
|
||||
res, err = operation.execute(&pc, in, callContext)
|
||||
res, err = operation.execute(&pc, evm, callContext)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
)
|
||||
|
||||
type (
|
||||
executionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error)
|
||||
executionFunc func(pc *uint64, evm *EVM, callContext *ScopeContext) ([]byte, error)
|
||||
gasFunc func(*EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
|
||||
// memorySizeFunc returns the required size, and whether the operation overflowed a uint64
|
||||
memorySizeFunc func(*Stack) (size uint64, overflow bool)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
|
|||
|
||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit, GasPrice: vmctx.txCtx.GasPrice}), contract.Caller())
|
||||
tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
|
||||
ret, err := evm.Interpreter().Run(contract, []byte{}, false)
|
||||
ret, err := evm.Run(contract, []byte{}, false)
|
||||
tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
|
||||
// Rest gas assumes no refund
|
||||
tracer.OnTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func TestStoreCapture(t *testing.T) {
|
|||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
||||
var index common.Hash
|
||||
logger.OnTxStart(evm.GetVMContext(), nil, common.Address{})
|
||||
_, err := evm.Interpreter().Run(contract, []byte{}, false)
|
||||
_, err := evm.Run(contract, []byte{}, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue