diff --git a/core/vm/contract.go b/core/vm/contract.go index bf71549c35..7b3983b8d9 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -48,6 +48,7 @@ type Contract struct { Code []byte CodeHash common.Hash + CodeAddr *common.Address // Address where the code was loaded from (for CODECOPY in optimized mode) Input []byte // is the execution frame represented by this object a contract deployment @@ -173,9 +174,10 @@ func (c *Contract) Value() *uint256.Int { // SetCallCode sets the code of the contract and address of the backing data // object -func (c *Contract) SetCallCode(hash common.Hash, code []byte) { +func (c *Contract) SetCallCode(codeAddr *common.Address, hash common.Hash, code []byte) { c.Code = code c.CodeHash = hash + c.CodeAddr = codeAddr } // SetOptimizedForTest returns a contract with optimized equals true for test purpose only diff --git a/core/vm/contract_pool.go b/core/vm/contract_pool.go index ab41938286..a2d18f0e09 100644 --- a/core/vm/contract_pool.go +++ b/core/vm/contract_pool.go @@ -24,6 +24,7 @@ func GetContract(caller common.Address, address common.Address, value *uint256.I contract.Gas = gas contract.Code = nil contract.CodeHash = common.Hash{} + contract.CodeAddr = nil contract.Input = nil contract.IsDeployment = false contract.IsSystemCall = false diff --git a/core/vm/evm.go b/core/vm/evm.go index 3d95861d6a..f8e07f10fd 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -268,6 +268,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g ret, err = nil, nil // gas is unchanged } else { if evm.Config.EnableOpcodeOptimizations { + addrCopy := addr // If the account has no code, we can abort here // The depth-check is already done, and precompiles handled above contract := GetContract(caller, addr, value, gas, evm.jumpDests) @@ -281,17 +282,18 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g evm.UseBaseInterpreter() } contract.IsSystemCall = isSystemCall(caller) - contract.SetCallCode(codeHash, code) + contract.SetCallCode(&addrCopy, codeHash, code) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } else { + addrCopy := addr // If the account has no code, we can abort here // The depth-check is already done, and precompiles handled above contract := GetContract(caller, addr, value, gas, evm.jumpDests) defer ReturnContract(contract) contract.IsSystemCall = isSystemCall(caller) - contract.SetCallCode(evm.resolveCodeHash(addr), code) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addr), code) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -349,6 +351,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { if evm.Config.EnableOpcodeOptimizations { + addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := GetContract(caller, caller, value, gas, evm.jumpDests) @@ -356,7 +359,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt code := evm.resolveCode(addr) codeHash := evm.resolveCodeHash(addr) contract.optimized, code = tryGetOptimizedCode(evm, codeHash, code) - contract.SetCallCode(codeHash, code) + contract.SetCallCode(&addrCopy, codeHash, code) if contract.optimized { evm.UseOptInterpreter() @@ -368,12 +371,13 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } else { + addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := GetContract(caller, caller, value, gas, evm.jumpDests) defer ReturnContract(contract) - contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addr), evm.resolveCode(addr)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -415,13 +419,14 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address, ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { if evm.Config.EnableOpcodeOptimizations { + addrCopy := addr // Initialise a new contract and make initialise the delegate values contract := GetContract(originCaller, caller, value, gas, evm.jumpDests) defer ReturnContract(contract) code := evm.resolveCode(addr) codeHash := evm.resolveCodeHash(addr) contract.optimized, code = tryGetOptimizedCode(evm, codeHash, code) - contract.SetCallCode(codeHash, code) + contract.SetCallCode(&addrCopy, codeHash, code) if contract.optimized { evm.UseOptInterpreter() contract.codeBitmapFunc = codeBitmapWhitSI @@ -431,11 +436,12 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address, ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } else { + addrCopy := addr // Initialise a new contract and make initialise the delegate values contract := GetContract(originCaller, caller, value, gas, evm.jumpDests) defer ReturnContract(contract) - contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addr), evm.resolveCode(addr)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -485,6 +491,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { if evm.Config.EnableOpcodeOptimizations { + addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := GetContract(caller, addr, new(uint256.Int), gas, evm.jumpDests) @@ -498,19 +505,20 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b } else { evm.UseBaseInterpreter() } - contract.SetCallCode(codeHash, code) + contract.SetCallCode(&addrCopy, codeHash, code) // 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) gas = contract.Gas } else { + addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. contract := GetContract(caller, addr, new(uint256.Int), gas, evm.jumpDests) defer ReturnContract(contract) - contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addr), evm.resolveCode(addr)) // 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. @@ -635,7 +643,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui // Explicitly set the code to a null hash to prevent caching of jump analysis // for the initialization code. - contract.SetCallCode(common.Hash{}, code) + contract.SetCallCode(&address, common.Hash{}, code) contract.IsDeployment = true ret, err = evm.initNewContract(contract, address) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index decb40ef20..adb5b1765a 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -342,7 +342,7 @@ func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { code := scope.Contract.Code if scope.Contract.optimized { - code = interpreter.evm.resolveCode(scope.Contract.address) + code = interpreter.evm.resolveCode(*scope.Contract.CodeAddr) } scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(code)))) return nil, nil @@ -359,7 +359,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ } code := scope.Contract.Code if scope.Contract.optimized { - code = interpreter.evm.resolveCode(scope.Contract.address) + code = interpreter.evm.resolveCode(*scope.Contract.CodeAddr) } codeCopy := getData(code, uint64CodeOffset, length.Uint64()) scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) diff --git a/core/vm/interpreter_si.go b/core/vm/interpreter_si.go index bc753e3a95..747bf02dc8 100644 --- a/core/vm/interpreter_si.go +++ b/core/vm/interpreter_si.go @@ -110,7 +110,7 @@ func (in *EVMInterpreter) executeSingleOpcode(pc *uint64, op OpCode, contract *C func (in *EVMInterpreter) tryFallbackForSuperInstruction(pc *uint64, seq []OpCode, contract *Contract, stack *Stack, mem *Memory, callCtx *ScopeContext) error { for _, sub := range seq { if err := in.executeSingleOpcode(pc, sub, contract, stack, mem, callCtx); err != nil { - log.Error("[FALLBACK-EXEC]", "op", sub.String(), "err", err, "gasLeft", contract.Gas) + log.Debug("[FALLBACK-EXEC]", "op", sub.String(), "err", err, "gasLeft", contract.Gas) return err // OutOfGas or other errors, will let upper level handle } }