Skip to content

Commit

Permalink
core/state: remove account reset operation v2 (ethereum#29520)
Browse files Browse the repository at this point in the history
* core/state, tests: remove account reset operation

* core/state, core/vm: implement createcontract journal event

* core/state: make createcontract not emit dirtied account, unskip tests

* core/state: add createcontract to journal fuzzing

* core/state: fix journal

* core/state: address comments

* core/state: remove useless code

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
  • Loading branch information
holiman and rjl493456442 committed Apr 24, 2024
1 parent 938734b commit 0d4c388
Show file tree
Hide file tree
Showing 9 changed files with 428 additions and 360 deletions.
151 changes: 123 additions & 28 deletions core/state/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package state

import (
"maps"

"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
)
Expand All @@ -29,6 +31,9 @@ type journalEntry interface {

// dirtied returns the Ethereum address modified by this journal entry.
dirtied() *common.Address

// copy returns a deep-copied journal entry.
copy() journalEntry
}

// journal contains the list of state modifications applied since the last state
Expand Down Expand Up @@ -83,22 +88,31 @@ func (j *journal) length() int {
return len(j.entries)
}

// copy returns a deep-copied journal.
func (j *journal) copy() *journal {
entries := make([]journalEntry, 0, j.length())
for i := 0; i < j.length(); i++ {
entries = append(entries, j.entries[i].copy())
}
return &journal{
entries: entries,
dirties: maps.Clone(j.dirties),
}
}

type (
// Changes to the account trie.
createObjectChange struct {
account *common.Address
}
resetObjectChange struct {
account *common.Address
prev *stateObject
prevdestruct bool
prevAccount []byte
prevStorage map[common.Hash][]byte

prevAccountOriginExist bool
prevAccountOrigin []byte
prevStorageOrigin map[common.Hash][]byte
// createContractChange represents an account becoming a contract-account.
// This event happens prior to executing initcode. The journal-event simply
// manages the created-flag, in order to allow same-tx destruction.
createContractChange struct {
account common.Address
}

selfDestructChange struct {
account *common.Address
prev bool // whether account had already self-destructed
Expand Down Expand Up @@ -136,6 +150,7 @@ type (
touchChange struct {
account *common.Address
}

// Changes to the access list
accessListAddAccountChange struct {
address *common.Address
Expand All @@ -145,6 +160,7 @@ type (
slot *common.Hash
}

// Changes to transient storage
transientStorageChange struct {
account *common.Address
key, prevalue common.Hash
Expand All @@ -153,34 +169,30 @@ type (

func (ch createObjectChange) revert(s *StateDB) {
delete(s.stateObjects, *ch.account)
delete(s.stateObjectsDirty, *ch.account)
}

func (ch createObjectChange) dirtied() *common.Address {
return ch.account
}

func (ch resetObjectChange) revert(s *StateDB) {
s.setStateObject(ch.prev)
if !ch.prevdestruct {
delete(s.stateObjectsDestruct, ch.prev.address)
}
if ch.prevAccount != nil {
s.accounts[ch.prev.addrHash] = ch.prevAccount
}
if ch.prevStorage != nil {
s.storages[ch.prev.addrHash] = ch.prevStorage
}
if ch.prevAccountOriginExist {
s.accountsOrigin[ch.prev.address] = ch.prevAccountOrigin
}
if ch.prevStorageOrigin != nil {
s.storagesOrigin[ch.prev.address] = ch.prevStorageOrigin
func (ch createObjectChange) copy() journalEntry {
return createObjectChange{
account: ch.account,
}
}

func (ch resetObjectChange) dirtied() *common.Address {
return ch.account
func (ch createContractChange) revert(s *StateDB) {
s.getStateObject(ch.account).newContract = false
}

func (ch createContractChange) dirtied() *common.Address {
return nil
}

func (ch createContractChange) copy() journalEntry {
return createContractChange{
account: ch.account,
}
}

func (ch selfDestructChange) revert(s *StateDB) {
Expand All @@ -195,6 +207,14 @@ func (ch selfDestructChange) dirtied() *common.Address {
return ch.account
}

func (ch selfDestructChange) copy() journalEntry {
return selfDestructChange{
account: ch.account,
prev: ch.prev,
prevbalance: new(uint256.Int).Set(ch.prevbalance),
}
}

var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")

func (ch touchChange) revert(s *StateDB) {
Expand All @@ -204,6 +224,12 @@ func (ch touchChange) dirtied() *common.Address {
return ch.account
}

func (ch touchChange) copy() journalEntry {
return touchChange{
account: ch.account,
}
}

func (ch balanceChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setBalance(ch.prev)
}
Expand All @@ -212,6 +238,13 @@ func (ch balanceChange) dirtied() *common.Address {
return ch.account
}

func (ch balanceChange) copy() journalEntry {
return balanceChange{
account: ch.account,
prev: new(uint256.Int).Set(ch.prev),
}
}

func (ch nonceChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setNonce(ch.prev)
}
Expand All @@ -220,6 +253,13 @@ func (ch nonceChange) dirtied() *common.Address {
return ch.account
}

func (ch nonceChange) copy() journalEntry {
return nonceChange{
account: ch.account,
prev: ch.prev,
}
}

func (ch codeChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
}
Expand All @@ -228,6 +268,14 @@ func (ch codeChange) dirtied() *common.Address {
return ch.account
}

func (ch codeChange) copy() journalEntry {
return codeChange{
account: ch.account,
prevhash: common.CopyBytes(ch.prevhash),
prevcode: common.CopyBytes(ch.prevcode),
}
}

func (ch storageChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
}
Expand All @@ -236,6 +284,14 @@ func (ch storageChange) dirtied() *common.Address {
return ch.account
}

func (ch storageChange) copy() journalEntry {
return storageChange{
account: ch.account,
key: ch.key,
prevalue: ch.prevalue,
}
}

func (ch transientStorageChange) revert(s *StateDB) {
s.setTransientState(*ch.account, ch.key, ch.prevalue)
}
Expand All @@ -244,6 +300,14 @@ func (ch transientStorageChange) dirtied() *common.Address {
return nil
}

func (ch transientStorageChange) copy() journalEntry {
return transientStorageChange{
account: ch.account,
key: ch.key,
prevalue: ch.prevalue,
}
}

func (ch refundChange) revert(s *StateDB) {
s.refund = ch.prev
}
Expand All @@ -252,6 +316,12 @@ func (ch refundChange) dirtied() *common.Address {
return nil
}

func (ch refundChange) copy() journalEntry {
return refundChange{
prev: ch.prev,
}
}

func (ch addLogChange) revert(s *StateDB) {
logs := s.logs[ch.txhash]
if len(logs) == 1 {
Expand All @@ -266,6 +336,12 @@ func (ch addLogChange) dirtied() *common.Address {
return nil
}

func (ch addLogChange) copy() journalEntry {
return addLogChange{
txhash: ch.txhash,
}
}

func (ch addPreimageChange) revert(s *StateDB) {
delete(s.preimages, ch.hash)
}
Expand All @@ -274,6 +350,12 @@ func (ch addPreimageChange) dirtied() *common.Address {
return nil
}

func (ch addPreimageChange) copy() journalEntry {
return addPreimageChange{
hash: ch.hash,
}
}

func (ch accessListAddAccountChange) revert(s *StateDB) {
/*
One important invariant here, is that whenever a (addr, slot) is added, if the
Expand All @@ -291,10 +373,23 @@ func (ch accessListAddAccountChange) dirtied() *common.Address {
return nil
}

func (ch accessListAddAccountChange) copy() journalEntry {
return accessListAddAccountChange{
address: ch.address,
}
}

func (ch accessListAddSlotChange) revert(s *StateDB) {
s.accessList.DeleteSlot(*ch.address, *ch.slot)
}

func (ch accessListAddSlotChange) dirtied() *common.Address {
return nil
}

func (ch accessListAddSlotChange) copy() journalEntry {
return accessListAddSlotChange{
address: ch.address,
slot: ch.slot,
}
}
Loading

0 comments on commit 0d4c388

Please sign in to comment.