diff --git a/core/vm/contract.go b/core/vm/contract.go index 2e02ce32b8..a97ee697b7 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -162,10 +162,3 @@ func (c *Contract) SetCallCode(hash common.Hash, code []byte) { c.Code = code c.CodeHash = hash } - -// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash. -// In case hash is not provided, the jumpdest analysis will not be saved to the parent context -func (c *Contract) SetCodeOptionalHash(codeAndHash *codeAndHash) { - c.Code = codeAndHash.code - c.CodeHash = codeAndHash.hash -} diff --git a/core/vm/evm.go b/core/vm/evm.go index 5415591024..effb181839 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -404,22 +404,10 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b return ret, 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 common.Address, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) { +func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) { if evm.Config.Tracer != nil { - evm.captureBegin(evm.depth, typ, caller, address, codeAndHash.code, gas, value.ToBig()) + evm.captureBegin(evm.depth, typ, caller, address, code, gas, value.ToBig()) defer func(startGas uint64) { evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) }(gas) @@ -502,10 +490,13 @@ func (evm *EVM) create(caller common.Address, codeAndHash *codeAndHash, gas uint // 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, address, value, gas, evm.jumpDests) - contract.SetCodeOptionalHash(codeAndHash) + + // Explicitly set the code to a null hash to prevent caching of jump analysis + // for the initialization code. + contract.SetCallCode(common.Hash{}, code) contract.IsDeployment = true - ret, err = evm.initNewContract(contract, address, value) + ret, err = evm.initNewContract(contract, address) if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { evm.StateDB.RevertToSnapshot(snapshot) if err != ErrExecutionReverted { @@ -517,7 +508,7 @@ func (evm *EVM) create(caller common.Address, codeAndHash *codeAndHash, gas uint // 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, value *uint256.Int) ([]byte, error) { +func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]byte, error) { ret, err := evm.interpreter.Run(contract, nil, false) if err != nil { return ret, err @@ -551,7 +542,7 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address, valu // Create creates a new contract using code as deployment code. func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { contractAddr = crypto.CreateAddress(caller, evm.StateDB.GetNonce(caller)) - return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) + return evm.create(caller, code, gas, value, contractAddr, CREATE) } // Create2 creates a new contract using code as deployment code. @@ -559,9 +550,8 @@ 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) { - codeAndHash := &codeAndHash{code: code} - contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), codeAndHash.Hash().Bytes()) - return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) + contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), crypto.Keccak256(code)) + return evm.create(caller, code, gas, endowment, contractAddr, CREATE2) } // resolveCode returns the code associated with the provided account. After