Patch for concurrent iterator & others (onto v1.11.6) #386

Closed
roysc wants to merge 1565 commits from v1.11.6-statediff-v5 into master
4 changed files with 69 additions and 69 deletions
Showing only changes of commit 877d2174fb - Show all commits

View File

@ -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

View File

@ -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
} }

View File

@ -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)

View File

@ -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