diff options
Diffstat (limited to 'core/vm/evm.go')
-rw-r--r-- | core/vm/evm.go | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/core/vm/evm.go b/core/vm/evm.go index fc040c621..968d2219e 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -212,12 +212,12 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas evm.StateDB.CreateAccount(addr) } evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) - // 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 := NewContract(caller, to, value, gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) + // Even if the account has no code, we need to continue because it might be a precompile start := time.Now() // Capture the tracer start/end events in debug mode @@ -352,8 +352,20 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte return ret, contract.Gas, err } +type codeAndHash struct { + code []byte + hash common.Hash +} + +func (c *codeAndHash) Hash() common.Hash { + if c.hash == (common.Hash{}) { + c.hash = crypto.Keccak256Hash(c.code) + } + return c.hash +} + // create creates a new contract using code as deployment code. -func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { +func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { // Depth check execution. Fail if we're trying to execute above the // limit. if evm.depth > int(params.CallCreateDepth) { @@ -382,14 +394,14 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.I // EVM. The contract is a scoped environment for this execution context // only. contract := NewContract(caller, AccountRef(address), value, gas) - contract.SetCallCode(&address, crypto.Keccak256Hash(code), code) + contract.SetCodeOptionalHash(&address, codeAndHash) if evm.vmConfig.NoRecursion && evm.depth > 0 { return nil, address, gas, nil } if evm.vmConfig.Debug && evm.depth == 0 { - evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, code, gas, value) + evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) } start := time.Now() @@ -433,7 +445,7 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.I // Create creates a new contract using code as deployment code. func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) - return evm.create(caller, code, gas, value, contractAddr) + return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr) } // Create2 creates a new contract using code as deployment code. @@ -441,8 +453,9 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(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 ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), code) - return evm.create(caller, code, gas, endowment, contractAddr) + codeAndHash := &codeAndHash{code: code} + contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes()) + return evm.create(caller, codeAndHash, gas, endowment, contractAddr) } // ChainConfig returns the environment's chain configuration |