core, tests: implement Metropolis EIP 684
This commit is contained in:
parent
27a5622e99
commit
08f27428b4
@ -24,4 +24,5 @@ var (
|
|||||||
ErrDepth = errors.New("max call depth exceeded")
|
ErrDepth = errors.New("max call depth exceeded")
|
||||||
ErrTraceLimitReached = errors.New("the number of logs reached the specified limit")
|
ErrTraceLimitReached = errors.New("the number of logs reached the specified limit")
|
||||||
ErrInsufficientBalance = errors.New("insufficient balance for transfer")
|
ErrInsufficientBalance = errors.New("insufficient balance for transfer")
|
||||||
|
ErrContractAddressCollision = errors.New("contract address collision")
|
||||||
)
|
)
|
||||||
|
@ -25,6 +25,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// emptyCodeHash is used by create to ensure deployment is disallowed to already
|
||||||
|
// deployed contract addresses (relevant after the account abstraction).
|
||||||
|
var emptyCodeHash = crypto.Keccak256Hash(nil)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
CanTransferFunc func(StateDB, common.Address, *big.Int) bool
|
CanTransferFunc func(StateDB, common.Address, *big.Int) bool
|
||||||
TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
|
TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
|
||||||
@ -307,13 +311,17 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
|
|||||||
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
|
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||||
return nil, common.Address{}, gas, ErrInsufficientBalance
|
return nil, common.Address{}, gas, ErrInsufficientBalance
|
||||||
}
|
}
|
||||||
|
// Ensure there's no existing contract already at the designated address
|
||||||
// Create a new account on the state
|
|
||||||
nonce := evm.StateDB.GetNonce(caller.Address())
|
nonce := evm.StateDB.GetNonce(caller.Address())
|
||||||
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
||||||
|
|
||||||
snapshot := evm.StateDB.Snapshot()
|
|
||||||
contractAddr = crypto.CreateAddress(caller.Address(), nonce)
|
contractAddr = crypto.CreateAddress(caller.Address(), nonce)
|
||||||
|
contractHash := evm.StateDB.GetCodeHash(contractAddr)
|
||||||
|
if evm.StateDB.GetNonce(contractAddr) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
|
||||||
|
return nil, common.Address{}, 0, ErrContractAddressCollision
|
||||||
|
}
|
||||||
|
// Create a new account on the state
|
||||||
|
snapshot := evm.StateDB.Snapshot()
|
||||||
evm.StateDB.CreateAccount(contractAddr)
|
evm.StateDB.CreateAccount(contractAddr)
|
||||||
if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
|
if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
|
||||||
evm.StateDB.SetNonce(contractAddr, 1)
|
evm.StateDB.SetNonce(contractAddr, 1)
|
||||||
|
@ -37,10 +37,8 @@ func TestState(t *testing.T) {
|
|||||||
// Expected failures:
|
// Expected failures:
|
||||||
st.fails(`^stCodeSizeLimit/codesizeOOGInvalidSize\.json/(Frontier|Homestead|EIP150)`,
|
st.fails(`^stCodeSizeLimit/codesizeOOGInvalidSize\.json/(Frontier|Homestead|EIP150)`,
|
||||||
"code size limit implementation is not conditional on fork")
|
"code size limit implementation is not conditional on fork")
|
||||||
st.fails(`^stRevertTest/RevertDepthCreateAddressCollision\.json/EIP15[08]/[67]`, "bug in test")
|
|
||||||
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/EIP158`, "bug in test")
|
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/EIP158`, "bug in test")
|
||||||
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/EIP158`, "bug in test")
|
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/EIP158`, "bug in test")
|
||||||
st.fails(`^stRevertTest/RevertDepthCreateAddressCollision\.json/Byzantium/[67]`, "bug in test")
|
|
||||||
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test")
|
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test")
|
||||||
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/Byzantium`, "bug in test")
|
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/Byzantium`, "bug in test")
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit cd2c3f1b3acb98c0d1501b06a4a54629d8794d79
|
Subproject commit 1d30b4795664f64b1b157971754e14a10cfd9115
|
@ -27,7 +27,6 @@ func TestVM(t *testing.T) {
|
|||||||
vmt := new(testMatcher)
|
vmt := new(testMatcher)
|
||||||
vmt.fails("^vmSystemOperationsTest.json/createNameRegistrator$", "fails without parallel execution")
|
vmt.fails("^vmSystemOperationsTest.json/createNameRegistrator$", "fails without parallel execution")
|
||||||
|
|
||||||
vmt.skipLoad(`^vmPerformanceTest.json`) // log format broken
|
|
||||||
vmt.skipLoad(`^vmInputLimits(Light)?.json`) // log format broken
|
vmt.skipLoad(`^vmInputLimits(Light)?.json`) // log format broken
|
||||||
|
|
||||||
vmt.skipShortMode("^vmPerformanceTest.json")
|
vmt.skipShortMode("^vmPerformanceTest.json")
|
||||||
|
Loading…
Reference in New Issue
Block a user