1717package state
1818
1919import (
20- "fmt"
2120 "maps"
2221 "slices"
23- "sort"
2422
2523 "github.com/ethereum/go-ethereum/common"
2624 "github.com/ethereum/go-ethereum/core/types"
2725 "github.com/holiman/uint256"
2826)
2927
30- type revision struct {
31- id int
32- journalIndex int
33- }
34-
3528// journalEntry is a modification entry in the state change linear journal that can be
3629// reverted on demand.
3730type journalEntry interface {
@@ -52,8 +45,7 @@ type linearJournal struct {
5245 entries []journalEntry // Current changes tracked by the linearJournal
5346 dirties map [common.Address ]int // Dirty accounts and the number of changes
5447
55- validRevisions []revision
56- nextRevisionId int
48+ revisions []int // sequence of indexes to points in time designating snapshots
5749}
5850
5951// compile-time interface check
@@ -71,9 +63,8 @@ func newLinearJournal() *linearJournal {
7163// can be reused.
7264func (j * linearJournal ) reset () {
7365 j .entries = j .entries [:0 ]
74- j .validRevisions = j .validRevisions [:0 ]
66+ j .revisions = j .revisions [:0 ]
7567 clear (j .dirties )
76- j .nextRevisionId = 0
7768}
7869
7970func (j linearJournal ) dirtyAccounts () []common.Address {
@@ -85,33 +76,33 @@ func (j linearJournal) dirtyAccounts() []common.Address {
8576 return dirty
8677}
8778
88- // snapshot returns an identifier for the current revision of the state.
89- func (j * linearJournal ) snapshot () int {
90- id := j .nextRevisionId
91- j .nextRevisionId ++
92- j .validRevisions = append (j .validRevisions , revision {id , j .length ()})
93- return id
79+ // snapshot starts a new journal scope which can be reverted or discarded.
80+ func (j * linearJournal ) snapshot () {
81+ j .revisions = append (j .revisions , len (j .entries ))
9482}
9583
96- func (j * linearJournal ) revertToSnapshot (revid int , s * StateDB ) {
97- // Find the snapshot in the stack of valid snapshots.
98- idx := sort .Search (len (j .validRevisions ), func (i int ) bool {
99- return j .validRevisions [i ].id >= revid
100- })
101- if idx == len (j .validRevisions ) || j .validRevisions [idx ].id != revid {
102- panic (fmt .Errorf ("revision id %v cannot be reverted (valid revisions: %d)" , revid , len (j .validRevisions )))
103- }
104- snapshot := j .validRevisions [idx ].journalIndex
105-
84+ // revertSnapshot reverts all state changes made since the last call to snapshot().
85+ func (j * linearJournal ) revertSnapshot (s * StateDB ) {
86+ id := len (j .revisions ) - 1
87+ revision := j .revisions [id ]
10688 // Replay the linearJournal to undo changes and remove invalidated snapshots
107- j .revert (s , snapshot )
108- j .validRevisions = j .validRevisions [: idx ]
89+ j .revertTo (s , revision )
90+ j .revisions = j .revisions [: id ]
10991}
11092
111- // discardSnapshot removes the snapshot with the given id ; after calling this
93+ // discardSnapshot removes the latest snapshot ; after calling this
11294// method, it is no longer possible to revert to that particular snapshot, the
11395// changes are considered part of the parent scope.
114- func (j * linearJournal ) discardSnapshot (id int ) {
96+ func (j * linearJournal ) discardSnapshot () {
97+ id := len (j .revisions ) - 1
98+ if id == 0 {
99+ // If a transaction is applied successfully, the statedb.Finalize will
100+ // end by clearing and resetting the journal. Invoking a discardSnapshot
101+ // afterwards will land here: calling discard on an empty journal.
102+ // This is fine
103+ return
104+ }
105+ j .revisions = j .revisions [:id ]
115106}
116107
117108// append inserts a new modification entry to the end of the change linearJournal.
@@ -124,7 +115,7 @@ func (j *linearJournal) append(entry journalEntry) {
124115
125116// revert undoes a batch of journalled modifications along with any reverted
126117// dirty handling too.
127- func (j * linearJournal ) revert (statedb * StateDB , snapshot int ) {
118+ func (j * linearJournal ) revertTo (statedb * StateDB , snapshot int ) {
128119 for i := len (j .entries ) - 1 ; i >= snapshot ; i -- {
129120 // Undo the changes made by the operation
130121 j .entries [i ].revert (statedb )
@@ -158,10 +149,9 @@ func (j *linearJournal) copy() journal {
158149 entries = append (entries , j .entries [i ].copy ())
159150 }
160151 return & linearJournal {
161- entries : entries ,
162- dirties : maps .Clone (j .dirties ),
163- validRevisions : slices .Clone (j .validRevisions ),
164- nextRevisionId : j .nextRevisionId ,
152+ entries : entries ,
153+ dirties : maps .Clone (j .dirties ),
154+ revisions : slices .Clone (j .revisions ),
165155 }
166156}
167157
0 commit comments