Skip to content

Commit

Permalink
core/state: modify how self-destruct journalling works
Browse files Browse the repository at this point in the history
The self-destruct journalling is a bit strange: we allow the
'selfdestruct' operation to be journalled several times. This makes it
so that we also are forced to store whether the account was
already destructed.
What we can do instead, is to only journal the first destruction, and after
that only journal balance-changes, but not journal the selfdestruct itself.

This simplifies the journalling, so that internals about state management
does not leak into the journal-API.
  • Loading branch information
holiman committed Apr 26, 2024
1 parent 7e0be7c commit 5aecb6d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 25 deletions.
19 changes: 5 additions & 14 deletions core/state/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,8 @@ 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) JournalDestruct(addr common.Address) {
j.append(selfDestructChange{account: &addr})
}

func (j *journal) JournalSetState(addr common.Address, key common.Hash, prev *common.Hash) {
Expand Down Expand Up @@ -239,9 +235,7 @@ type (
}

selfDestructChange struct {
account *common.Address
prev bool // whether account had already self-destructed
prevbalance *uint256.Int
account *common.Address
}

// Changes to individual accounts.
Expand Down Expand Up @@ -323,8 +317,7 @@ func (ch createContractChange) copy() journalEntry {
func (ch selfDestructChange) revert(s *StateDB) {
obj := s.getStateObject(*ch.account)
if obj != nil {
obj.selfDestructed = ch.prev
obj.setBalance(ch.prevbalance)
obj.selfDestructed = false
}
}

Expand All @@ -334,9 +327,7 @@ func (ch selfDestructChange) dirtied() *common.Address {

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

Expand Down
24 changes: 13 additions & 11 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,18 +472,20 @@ func (s *StateDB) SelfDestruct(addr common.Address) {
if stateObject == nil {
return
}
var (
prev = new(uint256.Int).Set(stateObject.Balance())
n = new(uint256.Int)
)
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)
// Regardless of whether it is already destructed or not, we do have to
// journal the balance-change, if we set it to zero here.
if !stateObject.Balance().IsZero() {
stateObject.SetBalance(new(uint256.Int), tracing.BalanceDecreaseSelfdestruct)
if s.logger != nil && s.logger.OnBalanceChange != nil {
s.logger.OnBalanceChange(addr, stateObject.Balance().ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
}
}
// If it is already marked as self-destructed, we do not need to add it
// for journalling a second time.
if !stateObject.selfDestructed {
s.journal.JournalDestruct(addr)
stateObject.markSelfdestructed()
}

stateObject.markSelfdestructed()
stateObject.data.Balance = n
}

func (s *StateDB) Selfdestruct6780(addr common.Address) {
Expand Down

0 comments on commit 5aecb6d

Please sign in to comment.