瀏覽代碼

core, tests: implement Metropolis EIP 684

Péter Szilágyi 8 年之前
父節點
當前提交
08f27428b4
共有 5 個文件被更改,包括 18 次插入12 次删除
  1. 6 5
      core/vm/errors.go
  2. 11 3
      core/vm/evm.go
  3. 0 2
      tests/state_test.go
  4. 1 1
      tests/testdata
  5. 0 1
      tests/vm_test.go

+ 6 - 5
core/vm/errors.go

@@ -19,9 +19,10 @@ package vm
 import "errors"
 
 var (
-	ErrOutOfGas            = errors.New("out of gas")
-	ErrCodeStoreOutOfGas   = errors.New("contract creation code storage out of gas")
-	ErrDepth               = errors.New("max call depth exceeded")
-	ErrTraceLimitReached   = errors.New("the number of logs reached the specified limit")
-	ErrInsufficientBalance = errors.New("insufficient balance for transfer")
+	ErrOutOfGas                 = errors.New("out of gas")
+	ErrCodeStoreOutOfGas        = errors.New("contract creation code storage out of gas")
+	ErrDepth                    = errors.New("max call depth exceeded")
+	ErrTraceLimitReached        = errors.New("the number of logs reached the specified limit")
+	ErrInsufficientBalance      = errors.New("insufficient balance for transfer")
+	ErrContractAddressCollision = errors.New("contract address collision")
 )

+ 11 - 3
core/vm/evm.go

@@ -25,6 +25,10 @@ import (
 	"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 (
 	CanTransferFunc func(StateDB, common.Address, *big.Int) bool
 	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) {
 		return nil, common.Address{}, gas, ErrInsufficientBalance
 	}
-
-	// Create a new account on the state
+	// Ensure there's no existing contract already at the designated address
 	nonce := evm.StateDB.GetNonce(caller.Address())
 	evm.StateDB.SetNonce(caller.Address(), nonce+1)
 
-	snapshot := evm.StateDB.Snapshot()
 	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)
 	if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
 		evm.StateDB.SetNonce(contractAddr, 1)

+ 0 - 2
tests/state_test.go

@@ -37,10 +37,8 @@ func TestState(t *testing.T) {
 	// Expected failures:
 	st.fails(`^stCodeSizeLimit/codesizeOOGInvalidSize\.json/(Frontier|Homestead|EIP150)`,
 		"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/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/RevertPrefoundEmptyOOG\.json/Byzantium`, "bug in test")
 

+ 1 - 1
tests/testdata

@@ -1 +1 @@
-Subproject commit cd2c3f1b3acb98c0d1501b06a4a54629d8794d79
+Subproject commit 1d30b4795664f64b1b157971754e14a10cfd9115

+ 0 - 1
tests/vm_test.go

@@ -27,7 +27,6 @@ func TestVM(t *testing.T) {
 	vmt := new(testMatcher)
 	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.skipShortMode("^vmPerformanceTest.json")