Patch for concurrent iterator & others (onto v1.11.6) #386
@ -133,7 +133,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
|
|||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
|
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
|
||||||
}
|
}
|
||||||
evm.interpreter = NewEVMInterpreter(evm, config)
|
evm.interpreter = NewEVMInterpreter(evm)
|
||||||
return evm
|
return evm
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +160,14 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
|
|||||||
return evm.interpreter
|
return evm.interpreter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBlockContext updates the block context of the EVM.
|
||||||
|
func (evm *EVM) SetBlockContext(blockCtx BlockContext) {
|
||||||
|
evm.Context = blockCtx
|
||||||
|
num := blockCtx.BlockNumber
|
||||||
|
timestamp := blockCtx.Time
|
||||||
|
evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
// Call executes the contract associated with the addr with the given input as
|
// Call executes the contract associated with the addr with the given input as
|
||||||
// parameters. It also handles any necessary value transfer required and takes
|
// 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
|
// the necessary steps to create accounts and reverses the state in case of an
|
||||||
|
@ -824,9 +824,9 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||||||
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
||||||
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
|
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
|
||||||
interpreter.evm.StateDB.Suicide(scope.Contract.Address())
|
interpreter.evm.StateDB.Suicide(scope.Contract.Address())
|
||||||
if interpreter.cfg.Debug {
|
if interpreter.evm.Config.Debug {
|
||||||
interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
|
interpreter.evm.Config.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
|
||||||
interpreter.cfg.Tracer.CaptureExit([]byte{}, 0, nil)
|
interpreter.evm.Config.Tracer.CaptureExit([]byte{}, 0, nil)
|
||||||
}
|
}
|
||||||
return nil, errStopToken
|
return nil, errStopToken
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ func TestAddMod(t *testing.T) {
|
|||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.Config)
|
evmInterpreter = NewEVMInterpreter(env)
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
)
|
)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@ -293,7 +293,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
|||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
scope = &ScopeContext{nil, stack, nil}
|
scope = &ScopeContext{nil, stack, nil}
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.Config)
|
evmInterpreter = NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
env.interpreter = evmInterpreter
|
||||||
@ -534,7 +534,7 @@ func TestOpMstore(t *testing.T) {
|
|||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.Config)
|
evmInterpreter = NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
env.interpreter = evmInterpreter
|
||||||
@ -560,7 +560,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
|||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.Config)
|
evmInterpreter = NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
env.interpreter = evmInterpreter
|
||||||
@ -583,7 +583,7 @@ func TestOpTstore(t *testing.T) {
|
|||||||
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.Config)
|
evmInterpreter = NewEVMInterpreter(env)
|
||||||
caller = common.Address{}
|
caller = common.Address{}
|
||||||
to = common.Address{1}
|
to = common.Address{1}
|
||||||
contractRef = contractRef{caller}
|
contractRef = contractRef{caller}
|
||||||
@ -625,7 +625,7 @@ func BenchmarkOpKeccak256(bench *testing.B) {
|
|||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.Config)
|
evmInterpreter = NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
env.interpreter = evmInterpreter
|
env.interpreter = evmInterpreter
|
||||||
mem.Resize(32)
|
mem.Resize(32)
|
||||||
|
@ -29,9 +29,6 @@ type Config struct {
|
|||||||
Tracer EVMLogger // Opcode logger
|
Tracer EVMLogger // Opcode logger
|
||||||
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
||||||
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
||||||
|
|
||||||
JumpTable *JumpTable // EVM instruction table, automatically populated if unset
|
|
||||||
|
|
||||||
ExtraEips []int // Additional EIPS that are to be enabled
|
ExtraEips []int // Additional EIPS that are to be enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +43,7 @@ type ScopeContext struct {
|
|||||||
// EVMInterpreter represents an EVM interpreter
|
// EVMInterpreter represents an EVM interpreter
|
||||||
type EVMInterpreter struct {
|
type EVMInterpreter struct {
|
||||||
evm *EVM
|
evm *EVM
|
||||||
cfg Config
|
table *JumpTable
|
||||||
|
|
||||||
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
|
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
|
||||||
hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes
|
hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes
|
||||||
@ -56,53 +53,48 @@ type EVMInterpreter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewEVMInterpreter returns a new instance of the Interpreter.
|
// NewEVMInterpreter returns a new instance of the Interpreter.
|
||||||
func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
|
func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||||
// If jump table was not initialised we set the default one.
|
// If jump table was not initialised we set the default one.
|
||||||
if cfg.JumpTable == nil {
|
var table *JumpTable
|
||||||
switch {
|
switch {
|
||||||
case evm.chainRules.IsShanghai:
|
case evm.chainRules.IsShanghai:
|
||||||
cfg.JumpTable = &shanghaiInstructionSet
|
table = &shanghaiInstructionSet
|
||||||
case evm.chainRules.IsMerge:
|
case evm.chainRules.IsMerge:
|
||||||
cfg.JumpTable = &mergeInstructionSet
|
table = &mergeInstructionSet
|
||||||
case evm.chainRules.IsLondon:
|
case evm.chainRules.IsLondon:
|
||||||
cfg.JumpTable = &londonInstructionSet
|
table = &londonInstructionSet
|
||||||
case evm.chainRules.IsBerlin:
|
case evm.chainRules.IsBerlin:
|
||||||
cfg.JumpTable = &berlinInstructionSet
|
table = &berlinInstructionSet
|
||||||
case evm.chainRules.IsIstanbul:
|
case evm.chainRules.IsIstanbul:
|
||||||
cfg.JumpTable = &istanbulInstructionSet
|
table = &istanbulInstructionSet
|
||||||
case evm.chainRules.IsConstantinople:
|
case evm.chainRules.IsConstantinople:
|
||||||
cfg.JumpTable = &constantinopleInstructionSet
|
table = &constantinopleInstructionSet
|
||||||
case evm.chainRules.IsByzantium:
|
case evm.chainRules.IsByzantium:
|
||||||
cfg.JumpTable = &byzantiumInstructionSet
|
table = &byzantiumInstructionSet
|
||||||
case evm.chainRules.IsEIP158:
|
case evm.chainRules.IsEIP158:
|
||||||
cfg.JumpTable = &spuriousDragonInstructionSet
|
table = &spuriousDragonInstructionSet
|
||||||
case evm.chainRules.IsEIP150:
|
case evm.chainRules.IsEIP150:
|
||||||
cfg.JumpTable = &tangerineWhistleInstructionSet
|
table = &tangerineWhistleInstructionSet
|
||||||
case evm.chainRules.IsHomestead:
|
case evm.chainRules.IsHomestead:
|
||||||
cfg.JumpTable = &homesteadInstructionSet
|
table = &homesteadInstructionSet
|
||||||
default:
|
default:
|
||||||
cfg.JumpTable = &frontierInstructionSet
|
table = &frontierInstructionSet
|
||||||
}
|
}
|
||||||
var extraEips []int
|
var extraEips []int
|
||||||
if len(cfg.ExtraEips) > 0 {
|
if len(evm.Config.ExtraEips) > 0 {
|
||||||
// Deep-copy jumptable to prevent modification of opcodes in other tables
|
// Deep-copy jumptable to prevent modification of opcodes in other tables
|
||||||
cfg.JumpTable = copyJumpTable(cfg.JumpTable)
|
table = copyJumpTable(table)
|
||||||
}
|
}
|
||||||
for _, eip := range cfg.ExtraEips {
|
for _, eip := range evm.Config.ExtraEips {
|
||||||
if err := EnableEIP(eip, cfg.JumpTable); err != nil {
|
if err := EnableEIP(eip, table); err != nil {
|
||||||
// Disable it, so caller can check if it's activated or not
|
// Disable it, so caller can check if it's activated or not
|
||||||
log.Error("EIP activation failed", "eip", eip, "error", err)
|
log.Error("EIP activation failed", "eip", eip, "error", err)
|
||||||
} else {
|
} else {
|
||||||
extraEips = append(extraEips, eip)
|
extraEips = append(extraEips, eip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.ExtraEips = extraEips
|
evm.Config.ExtraEips = extraEips
|
||||||
}
|
return &EVMInterpreter{evm: evm, table: table}
|
||||||
|
|
||||||
return &EVMInterpreter{
|
|
||||||
evm: evm,
|
|
||||||
cfg: cfg,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run loops and evaluates the contract's code with the given input data and returns
|
// Run loops and evaluates the contract's code with the given input data and returns
|
||||||
@ -160,13 +152,13 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||||||
}()
|
}()
|
||||||
contract.Input = input
|
contract.Input = input
|
||||||
|
|
||||||
if in.cfg.Debug {
|
if in.evm.Config.Debug {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !logged {
|
if !logged {
|
||||||
in.cfg.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
in.evm.Config.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
||||||
} else {
|
} else {
|
||||||
in.cfg.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err)
|
in.evm.Config.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -176,14 +168,14 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||||||
// the execution of one of the operations or until the done flag is set by the
|
// the execution of one of the operations or until the done flag is set by the
|
||||||
// parent context.
|
// parent context.
|
||||||
for {
|
for {
|
||||||
if in.cfg.Debug {
|
if in.evm.Config.Debug {
|
||||||
// Capture pre-execution values for tracing.
|
// Capture pre-execution values for tracing.
|
||||||
logged, pcCopy, gasCopy = false, pc, contract.Gas
|
logged, pcCopy, gasCopy = false, pc, contract.Gas
|
||||||
}
|
}
|
||||||
// Get the operation from the jump table and validate the stack to ensure there are
|
// Get the operation from the jump table and validate the stack to ensure there are
|
||||||
// enough stack items available to perform the operation.
|
// enough stack items available to perform the operation.
|
||||||
op = contract.GetOp(pc)
|
op = contract.GetOp(pc)
|
||||||
operation := in.cfg.JumpTable[op]
|
operation := in.table[op]
|
||||||
cost = operation.constantGas // For tracing
|
cost = operation.constantGas // For tracing
|
||||||
// Validate stack
|
// Validate stack
|
||||||
if sLen := stack.len(); sLen < operation.minStack {
|
if sLen := stack.len(); sLen < operation.minStack {
|
||||||
@ -221,15 +213,15 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||||||
return nil, ErrOutOfGas
|
return nil, ErrOutOfGas
|
||||||
}
|
}
|
||||||
// Do tracing before memory expansion
|
// Do tracing before memory expansion
|
||||||
if in.cfg.Debug {
|
if in.evm.Config.Debug {
|
||||||
in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
in.evm.Config.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
||||||
logged = true
|
logged = true
|
||||||
}
|
}
|
||||||
if memorySize > 0 {
|
if memorySize > 0 {
|
||||||
mem.Resize(memorySize)
|
mem.Resize(memorySize)
|
||||||
}
|
}
|
||||||
} else if in.cfg.Debug {
|
} else if in.evm.Config.Debug {
|
||||||
in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
in.evm.Config.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
||||||
logged = true
|
logged = true
|
||||||
}
|
}
|
||||||
// execute the operation
|
// execute the operation
|
||||||
|
Loading…
Reference in New Issue
Block a user