core/state: refactor journalling by implementing journal API

This commit is contained in:
Martin Holst Swende 2024-01-26 14:46:47 +01:00
parent df645e77b7
commit 8d5ceb6cad
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
3 changed files with 105 additions and 51 deletions

View file

@ -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 ( type (
// Changes to the account trie. // Changes to the account trie.
createObjectChange struct { createObjectChange struct {

View file

@ -114,14 +114,7 @@ func (s *stateObject) markSelfdestructed() {
} }
func (s *stateObject) touch() { func (s *stateObject) touch() {
s.db.journal.append(touchChange{ s.db.journal.JournalTouch(s.address)
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)
}
} }
// getTrie returns the associated storage trie. The trie will be opened if it's // 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 return
} }
// New value is different, update and journal the change // New value is different, update and journal the change
s.db.journal.append(storageChange{ s.db.journal.JournalSetState(s.address, key, prev, origin)
account: &s.address, s.setState(key, value, origin)
key: key,
prevvalue: prev,
origvalue: origin,
})
if s.db.logger != nil && s.db.logger.OnStorageChange != nil { if s.db.logger != nil && s.db.logger.OnStorageChange != nil {
s.db.logger.OnStorageChange(s.address, key, prev, value) 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 // 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) { func (s *stateObject) SetBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) {
s.db.journal.append(balanceChange{ s.db.journal.JournalBalanceChange(s.address, s.data.Balance)
account: &s.address,
prev: new(uint256.Int).Set(s.data.Balance),
})
if s.db.logger != nil && s.db.logger.OnBalanceChange != nil { if s.db.logger != nil && s.db.logger.OnBalanceChange != nil {
s.db.logger.OnBalanceChange(s.address, s.Balance().ToBig(), amount.ToBig(), reason) 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) { func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
prevcode := s.Code() s.db.journal.JournalSetCode(s.address, s.Code(), s.CodeHash())
s.db.journal.append(codeChange{
account: &s.address,
prevhash: s.CodeHash(),
prevcode: prevcode,
})
if s.db.logger != nil && s.db.logger.OnCodeChange != nil { 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) s.setCode(codeHash, code)
} }
@ -608,10 +589,7 @@ func (s *stateObject) setCode(codeHash common.Hash, code []byte) {
} }
func (s *stateObject) SetNonce(nonce uint64) { func (s *stateObject) SetNonce(nonce uint64) {
s.db.journal.append(nonceChange{ s.db.journal.JournalNonceChange(s.address, s.data.Nonce)
account: &s.address,
prev: s.data.Nonce,
})
if s.db.logger != nil && s.db.logger.OnNonceChange != nil { if s.db.logger != nil && s.db.logger.OnNonceChange != nil {
s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce) s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce)
} }

View file

@ -256,7 +256,7 @@ func (s *StateDB) Error() error {
} }
func (s *StateDB) AddLog(log *types.Log) { func (s *StateDB) AddLog(log *types.Log) {
s.journal.append(addLogChange{txhash: s.thash}) s.journal.JournalLog(s.thash)
log.TxHash = s.thash log.TxHash = s.thash
log.TxIndex = uint(s.txIndex) log.TxIndex = uint(s.txIndex)
@ -290,7 +290,7 @@ func (s *StateDB) Logs() []*types.Log {
// AddPreimage records a SHA3 preimage seen by the VM. // AddPreimage records a SHA3 preimage seen by the VM.
func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) { func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) {
if _, ok := s.preimages[hash]; !ok { if _, ok := s.preimages[hash]; !ok {
s.journal.append(addPreimageChange{hash: hash}) s.journal.JournalAddPreimage(hash)
s.preimages[hash] = slices.Clone(preimage) 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 // AddRefund adds gas to the refund counter
func (s *StateDB) AddRefund(gas uint64) { func (s *StateDB) AddRefund(gas uint64) {
s.journal.append(refundChange{prev: s.refund}) s.journal.JournalRefundChange(s.refund)
s.refund += gas s.refund += gas
} }
// SubRefund removes gas from the refund counter. // SubRefund removes gas from the refund counter.
// This method will panic if the refund counter goes below zero // This method will panic if the refund counter goes below zero
func (s *StateDB) SubRefund(gas uint64) { func (s *StateDB) SubRefund(gas uint64) {
s.journal.append(refundChange{prev: s.refund}) s.journal.JournalRefundChange(s.refund)
if gas > s.refund { if gas > s.refund {
panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", 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()) prev = new(uint256.Int).Set(stateObject.Balance())
n = new(uint256.Int) n = new(uint256.Int)
) )
s.journal.append(selfDestructChange{ s.journal.JournalDestruct(addr, stateObject.selfDestructed, prev)
account: &addr,
prev: stateObject.selfDestructed,
prevbalance: prev,
})
if s.logger != nil && s.logger.OnBalanceChange != nil && prev.Sign() > 0 { if s.logger != nil && s.logger.OnBalanceChange != nil && prev.Sign() > 0 {
s.logger.OnBalanceChange(addr, prev.ToBig(), n.ToBig(), tracing.BalanceDecreaseSelfdestruct) s.logger.OnBalanceChange(addr, prev.ToBig(), n.ToBig(), tracing.BalanceDecreaseSelfdestruct)
} }
stateObject.markSelfdestructed() stateObject.markSelfdestructed()
stateObject.data.Balance = n stateObject.data.Balance = n
} }
@ -540,11 +538,7 @@ func (s *StateDB) SetTransientState(addr common.Address, key, value common.Hash)
if prev == value { if prev == value {
return return
} }
s.journal.append(transientStorageChange{ s.journal.JournalSetTransientState(addr, key, prev)
account: &addr,
key: key,
prevalue: prev,
})
s.setTransientState(addr, key, value) 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. // existing account with the given address, otherwise it will be silently overwritten.
func (s *StateDB) createObject(addr common.Address) *stateObject { func (s *StateDB) createObject(addr common.Address) *stateObject {
obj := newObject(s, addr, nil) obj := newObject(s, addr, nil)
s.journal.append(createObjectChange{account: &addr}) s.journal.JournalCreate(addr)
s.setStateObject(obj) s.setStateObject(obj)
return 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 // AddAddressToAccessList adds the given address to the access list
func (s *StateDB) AddAddressToAccessList(addr common.Address) { func (s *StateDB) AddAddressToAccessList(addr common.Address) {
if s.accessList.AddAddress(addr) { 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 // scope of 'address' without having the 'address' become already added
// to the access list (via call-variant, create, etc). // to the access list (via call-variant, create, etc).
// Better safe than sorry, though // Better safe than sorry, though
s.journal.append(accessListAddAccountChange{&addr}) s.journal.JournalAccessListAddAccount(addr)
} }
if slotMod { if slotMod {
s.journal.append(accessListAddSlotChange{ s.journal.JournalAccessListAddSlot(addr, slot)
address: &addr,
slot: &slot,
})
} }
} }