From 95b29b69e99f9e8f8b724b797d58b41bd0c41dc3 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sat, 23 Nov 2024 20:12:56 +0100 Subject: [PATCH] core/state: fixes for issues found during fuzzing --- core/state/journal_linear.go | 15 ++++++++++++++- core/state/journal_set.go | 7 ++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/core/state/journal_linear.go b/core/state/journal_linear.go index e4b5571ef6..8ad8f8b7ea 100644 --- a/core/state/journal_linear.go +++ b/core/state/journal_linear.go @@ -65,6 +65,7 @@ func (j *linearJournal) reset() { j.entries = j.entries[:0] j.revisions = j.revisions[:0] clear(j.dirties) + j.snapshot() } func (j linearJournal) dirtyAccounts() []common.Address { @@ -84,10 +85,17 @@ func (j *linearJournal) snapshot() { // revertSnapshot reverts all state changes made since the last call to snapshot(). func (j *linearJournal) revertSnapshot(s *StateDB) { id := len(j.revisions) - 1 + if id < 0 { + j.snapshot() + return + } revision := j.revisions[id] // Replay the linearJournal to undo changes and remove invalidated snapshots j.revertTo(s, revision) j.revisions = j.revisions[:id] + if id == 0 { + j.snapshot() + } } // discardSnapshot removes the latest snapshot; after calling this @@ -95,7 +103,7 @@ func (j *linearJournal) revertSnapshot(s *StateDB) { // changes are considered part of the parent scope. func (j *linearJournal) discardSnapshot() { id := len(j.revisions) - 1 - if id == 0 { + if id <= 0 { // If a transaction is applied successfully, the statedb.Finalize will // end by clearing and resetting the journal. Invoking a discardSnapshot // afterwards will land here: calling discard on an empty journal. @@ -312,6 +320,11 @@ func (ch createContractChange) revert(s *StateDB) { } func (ch createContractChange) dirtied() *common.Address { + // This method returns nil, since the transformation from non-contract to + // contract is not an operation which has an effect on the trie: + // it does not make the account part of the dirty-set. + // Creating the account (createObject) or setting the code (setCode) + // however, do, and are. return nil } diff --git a/core/state/journal_set.go b/core/state/journal_set.go index d3dd57ea64..1fa5e60006 100644 --- a/core/state/journal_set.go +++ b/core/state/journal_set.go @@ -334,12 +334,14 @@ func newSparseJournal() *sparseJournal { // slices can be reused func (j *sparseJournal) reset() { j.entries = j.entries[:0] + j.ripeMagic = false j.snapshot() } func (j *sparseJournal) copy() journal { cp := &sparseJournal{ - entries: make([]*scopedJournal, 0, len(j.entries)), + entries: make([]*scopedJournal, 0, len(j.entries)), + ripeMagic: j.ripeMagic, } for _, entry := range j.entries { cp.entries = append(cp.entries, entry.deepCopy()) @@ -360,6 +362,9 @@ func (j *sparseJournal) revertSnapshot(s *StateDB) { id := len(j.entries) - 1 j.entries[id].revert(s) j.entries = j.entries[:id] + if id == 0 { + j.snapshot() + } } // discardSnapshot removes the latest snapshot; after calling this