From 8d5ceb6cad2b379eac4b5e2489d6628c2358d4ce Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 26 Jan 2024 14:46:47 +0100 Subject: [PATCH] core/state: refactor journalling by implementing journal API --- core/state/journal.go | 85 ++++++++++++++++++++++++++++++++++++++ core/state/state_object.go | 38 ++++------------- core/state/statedb.go | 33 ++++++--------- 3 files changed, 105 insertions(+), 51 deletions(-) diff --git a/core/state/journal.go b/core/state/journal.go index ad4a654fc6..94f7e0ad39 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -100,6 +100,91 @@ func (j *journal) copy() *journal { } } +func (j *journal) JournalAccessListAddAccount(addr common.Address) { + j.append(accessListAddAccountChange{&addr}) +} + +func (j *journal) JournalAccessListAddSlot(addr common.Address, slot common.Hash) { + j.append(accessListAddSlotChange{ + address: &addr, + slot: &slot, + }) +} + +func (j *journal) JournalLog(txHash common.Hash) { + j.append(addLogChange{txhash: txHash}) +} + +func (j *journal) JournalAddPreimage(hash common.Hash) { + j.append(addPreimageChange{hash: hash}) +} + +func (j *journal) JournalCreate(addr common.Address) { + j.append(createObjectChange{account: &addr}) +} + +func (j *journal) JournalDestruct(addr common.Address, previouslyDestructed bool, prevBalance *uint256.Int) { + j.append(selfDestructChange{ + account: &addr, + prev: previouslyDestructed, + prevbalance: prevBalance.Clone(), + }) +} + +func (j *journal) JournalSetState(addr common.Address, key, prev, origin common.Hash) { + j.append(storageChange{ + account: &addr, + key: key, + prevvalue: prev, + origvalue: origin, + }) +} + +func (j *journal) JournalSetTransientState(addr common.Address, key, prev common.Hash) { + j.append(transientStorageChange{ + account: &addr, + key: key, + prevalue: prev, + }) +} + +func (j *journal) JournalRefundChange(previous uint64) { + j.append(refundChange{prev: previous}) +} + +func (j *journal) JournalBalanceChange(addr common.Address, previous *uint256.Int) { + j.append(balanceChange{ + account: &addr, + prev: previous.Clone(), + }) +} + +func (j *journal) JournalSetCode(address common.Address, prevcode, prevHash []byte) { + j.append(codeChange{ + account: &address, + prevhash: prevHash, + prevcode: prevcode, + }) +} + +func (j *journal) JournalNonceChange(address common.Address, prev uint64) { + j.append(nonceChange{ + account: &address, + prev: prev, + }) +} + +func (j *journal) JournalTouch(address common.Address) { + j.append(touchChange{ + account: &address, + }) + if address == ripemd { + // Explicitly put it in the dirty-cache, which is otherwise generated from + // flattened journals. + j.dirty(address) + } +} + type ( // Changes to the account trie. createObjectChange struct { diff --git a/core/state/state_object.go b/core/state/state_object.go index 880b715b4b..44a628acfc 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -114,14 +114,7 @@ func (s *stateObject) markSelfdestructed() { } func (s *stateObject) touch() { - s.db.journal.append(touchChange{ - account: &s.address, - }) - if s.address == ripemd { - // Explicitly put it in the dirty-cache, which is otherwise generated from - // flattened journals. - s.db.journal.dirty(s.address) - } + s.db.journal.JournalTouch(s.address) } // getTrie returns the associated storage trie. The trie will be opened if it's @@ -251,16 +244,11 @@ func (s *stateObject) SetState(key, value common.Hash) { return } // New value is different, update and journal the change - s.db.journal.append(storageChange{ - account: &s.address, - key: key, - prevvalue: prev, - origvalue: origin, - }) + s.db.journal.JournalSetState(s.address, key, prev, origin) + s.setState(key, value, origin) if s.db.logger != nil && s.db.logger.OnStorageChange != nil { s.db.logger.OnStorageChange(s.address, key, prev, value) } - s.setState(key, value, origin) } // setState updates a value in account dirty storage. The dirtiness will be @@ -510,10 +498,7 @@ func (s *stateObject) SubBalance(amount *uint256.Int, reason tracing.BalanceChan } func (s *stateObject) SetBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { - s.db.journal.append(balanceChange{ - account: &s.address, - prev: new(uint256.Int).Set(s.data.Balance), - }) + s.db.journal.JournalBalanceChange(s.address, s.data.Balance) if s.db.logger != nil && s.db.logger.OnBalanceChange != nil { s.db.logger.OnBalanceChange(s.address, s.Balance().ToBig(), amount.ToBig(), reason) } @@ -589,14 +574,10 @@ func (s *stateObject) CodeSize() int { } func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { - prevcode := s.Code() - s.db.journal.append(codeChange{ - account: &s.address, - prevhash: s.CodeHash(), - prevcode: prevcode, - }) + s.db.journal.JournalSetCode(s.address, s.Code(), s.CodeHash()) if s.db.logger != nil && s.db.logger.OnCodeChange != nil { - s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), prevcode, codeHash, code) + // TODO remove prevcode from this callback + s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), nil, codeHash, code) } s.setCode(codeHash, code) } @@ -608,10 +589,7 @@ func (s *stateObject) setCode(codeHash common.Hash, code []byte) { } func (s *stateObject) SetNonce(nonce uint64) { - s.db.journal.append(nonceChange{ - account: &s.address, - prev: s.data.Nonce, - }) + s.db.journal.JournalNonceChange(s.address, s.data.Nonce) if s.db.logger != nil && s.db.logger.OnNonceChange != nil { s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce) } diff --git a/core/state/statedb.go b/core/state/statedb.go index 80a53dbb17..0457628864 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -256,7 +256,7 @@ func (s *StateDB) Error() error { } func (s *StateDB) AddLog(log *types.Log) { - s.journal.append(addLogChange{txhash: s.thash}) + s.journal.JournalLog(s.thash) log.TxHash = s.thash log.TxIndex = uint(s.txIndex) @@ -290,7 +290,7 @@ func (s *StateDB) Logs() []*types.Log { // AddPreimage records a SHA3 preimage seen by the VM. func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) { if _, ok := s.preimages[hash]; !ok { - s.journal.append(addPreimageChange{hash: hash}) + s.journal.JournalAddPreimage(hash) s.preimages[hash] = slices.Clone(preimage) } } @@ -302,14 +302,14 @@ func (s *StateDB) Preimages() map[common.Hash][]byte { // AddRefund adds gas to the refund counter func (s *StateDB) AddRefund(gas uint64) { - s.journal.append(refundChange{prev: s.refund}) + s.journal.JournalRefundChange(s.refund) s.refund += gas } // SubRefund removes gas from the refund counter. // This method will panic if the refund counter goes below zero func (s *StateDB) SubRefund(gas uint64) { - s.journal.append(refundChange{prev: s.refund}) + s.journal.JournalRefundChange(s.refund) if gas > s.refund { panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund)) } @@ -510,14 +510,12 @@ func (s *StateDB) SelfDestruct(addr common.Address) { prev = new(uint256.Int).Set(stateObject.Balance()) n = new(uint256.Int) ) - s.journal.append(selfDestructChange{ - account: &addr, - prev: stateObject.selfDestructed, - prevbalance: prev, - }) + s.journal.JournalDestruct(addr, stateObject.selfDestructed, prev) + if s.logger != nil && s.logger.OnBalanceChange != nil && prev.Sign() > 0 { s.logger.OnBalanceChange(addr, prev.ToBig(), n.ToBig(), tracing.BalanceDecreaseSelfdestruct) } + stateObject.markSelfdestructed() stateObject.data.Balance = n } @@ -540,11 +538,7 @@ func (s *StateDB) SetTransientState(addr common.Address, key, value common.Hash) if prev == value { return } - s.journal.append(transientStorageChange{ - account: &addr, - key: key, - prevalue: prev, - }) + s.journal.JournalSetTransientState(addr, key, prev) s.setTransientState(addr, key, value) } @@ -663,7 +657,7 @@ func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject { // existing account with the given address, otherwise it will be silently overwritten. func (s *StateDB) createObject(addr common.Address) *stateObject { obj := newObject(s, addr, nil) - s.journal.append(createObjectChange{account: &addr}) + s.journal.JournalCreate(addr) s.setStateObject(obj) return obj } @@ -1419,7 +1413,7 @@ func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, d // AddAddressToAccessList adds the given address to the access list func (s *StateDB) AddAddressToAccessList(addr common.Address) { if s.accessList.AddAddress(addr) { - s.journal.append(accessListAddAccountChange{&addr}) + s.journal.JournalAccessListAddAccount(addr) } } @@ -1431,13 +1425,10 @@ func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { // scope of 'address' without having the 'address' become already added // to the access list (via call-variant, create, etc). // Better safe than sorry, though - s.journal.append(accessListAddAccountChange{&addr}) + s.journal.JournalAccessListAddAccount(addr) } if slotMod { - s.journal.append(accessListAddSlotChange{ - address: &addr, - slot: &slot, - }) + s.journal.JournalAccessListAddSlot(addr, slot) } }