From 4e1deabe5904794a80b4bf7406c5048f2d8883af Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Wed, 13 Sep 2023 15:10:51 +0800 Subject: [PATCH] core/state: remove reset-account notion in statedb --- core/state/statedb.go | 30 ++++++++---------------------- core/state/statedb_test.go | 34 ---------------------------------- core/vm/evm.go | 4 +++- core/vm/interface.go | 2 ++ 4 files changed, 13 insertions(+), 57 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index bd578ba23d5..42682aa550e 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -618,16 +618,16 @@ func (s *StateDB) setStateObject(object *stateObject) { func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { stateObject := s.getStateObject(addr) if stateObject == nil { - stateObject, _ = s.createObject(addr) + stateObject = s.createObject(addr) } return stateObject } // createObject creates a new state object. If there is an existing account with // the given address, it is overwritten and returned as the second return value. -func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { - prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! - newobj = newObject(s, addr, nil) +func (s *StateDB) createObject(addr common.Address) *stateObject { + prev := s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! + newobj := newObject(s, addr, nil) if prev == nil { s.journal.append(createObjectChange{account: &addr}) } else { @@ -662,27 +662,13 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) newobj.created = true s.setStateObject(newobj) - if prev != nil && !prev.deleted { - return newobj, prev - } - return newobj, nil + return newobj } -// CreateAccount explicitly creates a state object. If a state object with the address -// already exists the balance is carried over to the new account. -// -// CreateAccount is called during the EVM CREATE operation. The situation might arise that -// a contract does the following: -// -// 1. sends funds to sha(account ++ (nonce + 1)) -// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) -// -// Carrying over the balance ensures that Ether doesn't disappear. +// CreateAccount creates a new account at the given address. This function +// assumes the address is unoccupied to avoid unintentional overwrites. func (s *StateDB) CreateAccount(addr common.Address) { - newObj, prev := s.createObject(addr) - if prev != nil { - newObj.setBalance(prev.data.Balance) - } + s.createObject(addr) } // Copy creates a deep, independent copy of the state. diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index ad829a0c8f0..ac22425d804 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -1104,40 +1104,6 @@ func TestStateDBTransientStorage(t *testing.T) { } } -func TestResetObject(t *testing.T) { - var ( - disk = rawdb.NewMemoryDatabase() - tdb = trie.NewDatabase(disk, nil) - db = NewDatabaseWithNodeDB(disk, tdb) - snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash) - state, _ = New(types.EmptyRootHash, db, snaps) - addr = common.HexToAddress("0x1") - slotA = common.HexToHash("0x1") - slotB = common.HexToHash("0x2") - ) - // Initialize account with balance and storage in first transaction. - state.SetBalance(addr, big.NewInt(1)) - state.SetState(addr, slotA, common.BytesToHash([]byte{0x1})) - state.IntermediateRoot(true) - - // Reset account and mutate balance and storages - state.CreateAccount(addr) - state.SetBalance(addr, big.NewInt(2)) - state.SetState(addr, slotB, common.BytesToHash([]byte{0x2})) - root, _ := state.Commit(0, true) - - // Ensure the original account is wiped properly - snap := snaps.Snapshot(root) - slot, _ := snap.Storage(crypto.Keccak256Hash(addr.Bytes()), crypto.Keccak256Hash(slotA.Bytes())) - if len(slot) != 0 { - t.Fatalf("Unexpected storage slot") - } - slot, _ = snap.Storage(crypto.Keccak256Hash(addr.Bytes()), crypto.Keccak256Hash(slotB.Bytes())) - if !bytes.Equal(slot, []byte{0x2}) { - t.Fatalf("Unexpected storage slot value %v", slot) - } -} - func TestDeleteStorage(t *testing.T) { var ( disk = rawdb.NewMemoryDatabase() diff --git a/core/vm/evm.go b/core/vm/evm.go index 40e2f3554f4..77bfab0abec 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -441,7 +441,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, } // Create a new account on the state snapshot := evm.StateDB.Snapshot() - evm.StateDB.CreateAccount(address) + if !evm.StateDB.Exist(address) { + evm.StateDB.CreateAccount(address) + } if evm.chainRules.IsEIP158 { evm.StateDB.SetNonce(address, 1) } diff --git a/core/vm/interface.go b/core/vm/interface.go index 26814d3d2f0..d539d2152f1 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -26,6 +26,8 @@ import ( // StateDB is an EVM database for full state querying. type StateDB interface { + // CreateAccount creates a new account at the given address. This function + // assumes the address is unoccupied to avoid unintentional overwrites. CreateAccount(common.Address) SubBalance(common.Address, *big.Int)