@@ -53,6 +53,8 @@ func NewFromEntryStore(logger log.Logger, m Metrics, store EntryStore) (*DB, err
5353
5454// Rewind to the last entry that was derived from a L1 block with the given block number.
5555func (db * DB ) Rewind (derivedFrom uint64 ) error {
56+ db .rwLock .Lock ()
57+ defer db .rwLock .Unlock ()
5658 index , _ , err := db .lastDerivedAt (derivedFrom )
5759 if err != nil {
5860 return fmt .Errorf ("failed to find point to rewind to: %w" , err )
@@ -66,29 +68,36 @@ func (db *DB) Rewind(derivedFrom uint64) error {
6668}
6769
6870// First returns the first known values, alike to Latest.
69- func (db * DB ) First () (derivedFrom types.BlockSeal , derived types. BlockSeal , err error ) {
71+ func (db * DB ) First () (pair types.DerivedBlockSealPair , err error ) {
7072 db .rwLock .RLock ()
7173 defer db .rwLock .RUnlock ()
7274 lastIndex := db .store .LastEntryIdx ()
7375 if lastIndex < 0 {
74- return types.BlockSeal {}, types. BlockSeal {}, types .ErrFuture
76+ return types.DerivedBlockSealPair {}, types .ErrFuture
7577 }
7678 last , err := db .readAt (0 )
7779 if err != nil {
78- return types.BlockSeal {}, types. BlockSeal {}, fmt .Errorf ("failed to read first derivation data: %w" , err )
80+ return types.DerivedBlockSealPair {}, fmt .Errorf ("failed to read first derivation data: %w" , err )
7981 }
80- return last .derivedFrom , last . derived , nil
82+ return last .sealOrErr ()
8183}
8284
8385func (db * DB ) PreviousDerived (derived eth.BlockID ) (prevDerived types.BlockSeal , err error ) {
8486 db .rwLock .RLock ()
8587 defer db .rwLock .RUnlock ()
86- // get the last time this L2 block was seen.
88+ // last
89+ _ , lastCanonical , err := db .lastDerivedFrom (derived .Number )
90+ if err != nil {
91+ return types.BlockSeal {}, fmt .Errorf ("failed to find last derived %d: %w" , derived .Number , err )
92+ }
93+ // get the first time this L2 block was seen.
8794 selfIndex , self , err := db .firstDerivedFrom (derived .Number )
8895 if err != nil {
89- return types.BlockSeal {}, fmt .Errorf ("failed to find derived %d: %w" , derived .Number , err )
96+ return types.BlockSeal {}, fmt .Errorf ("failed to find first derived %d: %w" , derived .Number , err )
9097 }
91- if self .derived .ID () != derived {
98+ // The first entry might not match, since it may have been invalidated with a later L1 scope.
99+ // But the last entry should always match.
100+ if lastCanonical .derived .ID () != derived {
92101 return types.BlockSeal {}, fmt .Errorf ("found %s, but expected %s: %w" , self .derived , derived , types .ErrConflict )
93102 }
94103 if selfIndex == 0 { // genesis block has a zeroed block as parent block
@@ -104,26 +113,48 @@ func (db *DB) PreviousDerived(derived eth.BlockID) (prevDerived types.BlockSeal,
104113// Latest returns the last known values:
105114// derivedFrom: the L1 block that the L2 block is safe for (not necessarily the first, multiple L2 blocks may be derived from the same L1 block).
106115// derived: the L2 block that was derived (not necessarily the first, the L1 block may have been empty and repeated the last safe L2 block).
107- func (db * DB ) Latest () (derivedFrom types.BlockSeal , derived types.BlockSeal , err error ) {
116+ // If the last entry is invalidated, this returns a types.ErrAwaitReplacementBlock error.
117+ func (db * DB ) Latest () (pair types.DerivedBlockSealPair , err error ) {
118+ db .rwLock .RLock ()
119+ defer db .rwLock .RUnlock ()
120+ link , err := db .latest ()
121+ if err != nil {
122+ return types.DerivedBlockSealPair {}, err
123+ }
124+ return link .sealOrErr ()
125+ }
126+
127+ func (db * DB ) Invalidated () (pair types.DerivedBlockSealPair , err error ) {
108128 db .rwLock .RLock ()
109129 defer db .rwLock .RUnlock ()
110- return db .latest ()
130+ link , err := db .latest ()
131+ if err != nil {
132+ return types.DerivedBlockSealPair {}, err
133+ }
134+ if ! link .invalidated {
135+ return types.DerivedBlockSealPair {}, fmt .Errorf ("last entry %s is not invalidated: %w" , link , types .ErrConflict )
136+ }
137+ return types.DerivedBlockSealPair {
138+ DerivedFrom : link .derivedFrom ,
139+ Derived : link .derived ,
140+ }, nil
111141}
112142
113143// latest is like Latest, but without lock, for internal use.
114- func (db * DB ) latest () (derivedFrom types. BlockSeal , derived types. BlockSeal , err error ) {
144+ func (db * DB ) latest () (link LinkEntry , err error ) {
115145 lastIndex := db .store .LastEntryIdx ()
116146 if lastIndex < 0 {
117- return types. BlockSeal {}, types. BlockSeal {}, types .ErrFuture
147+ return LinkEntry {}, types .ErrFuture
118148 }
119149 last , err := db .readAt (lastIndex )
120150 if err != nil {
121- return types. BlockSeal {}, types. BlockSeal {}, fmt .Errorf ("failed to read last derivation data: %w" , err )
151+ return LinkEntry {}, fmt .Errorf ("failed to read last derivation data: %w" , err )
122152 }
123- return last . derivedFrom , last . derived , nil
153+ return last , nil
124154}
125155
126156// LastDerivedAt returns the last L2 block derived from the given L1 block.
157+ // This may return types.ErrAwaitReplacementBlock if the entry was invalidated and needs replacement.
127158func (db * DB ) LastDerivedAt (derivedFrom eth.BlockID ) (derived types.BlockSeal , err error ) {
128159 db .rwLock .RLock ()
129160 defer db .rwLock .RUnlock ()
@@ -135,26 +166,30 @@ func (db *DB) LastDerivedAt(derivedFrom eth.BlockID) (derived types.BlockSeal, e
135166 return types.BlockSeal {}, fmt .Errorf ("searched for last derived-from %s but found %s: %w" ,
136167 derivedFrom , link .derivedFrom , types .ErrConflict )
137168 }
169+ if link .invalidated {
170+ return types.BlockSeal {}, types .ErrAwaitReplacementBlock
171+ }
138172 return link .derived , nil
139173}
140174
141- // NextDerived finds the next L2 block after derived, and what it was derived from
142- func (db * DB ) NextDerived (derived eth.BlockID ) (derivedFrom types.BlockSeal , nextDerived types.BlockSeal , err error ) {
175+ // NextDerived finds the next L2 block after derived, and what it was derived from.
176+ // This may return types.ErrAwaitReplacementBlock if the entry was invalidated and needs replacement.
177+ func (db * DB ) NextDerived (derived eth.BlockID ) (pair types.DerivedBlockSealPair , err error ) {
143178 db .rwLock .RLock ()
144179 defer db .rwLock .RUnlock ()
145180 // get the last time this L2 block was seen.
146181 selfIndex , self , err := db .lastDerivedFrom (derived .Number )
147182 if err != nil {
148- return types.BlockSeal {}, types. BlockSeal {}, fmt .Errorf ("failed to find derived %d: %w" , derived .Number , err )
183+ return types.DerivedBlockSealPair {}, fmt .Errorf ("failed to find derived %d: %w" , derived .Number , err )
149184 }
150185 if self .derived .ID () != derived {
151- return types.BlockSeal {}, types. BlockSeal {}, fmt .Errorf ("found %s, but expected %s: %w" , self .derived , derived , types .ErrConflict )
186+ return types.DerivedBlockSealPair {}, fmt .Errorf ("found %s, but expected %s: %w" , self .derived , derived , types .ErrConflict )
152187 }
153188 next , err := db .readAt (selfIndex + 1 )
154189 if err != nil {
155- return types.BlockSeal {}, types. BlockSeal {}, fmt .Errorf ("cannot find next derived after %s: %w" , derived , err )
190+ return types.DerivedBlockSealPair {}, fmt .Errorf ("cannot find next derived after %s: %w" , derived , err )
156191 }
157- return next .derivedFrom , next . derived , nil
192+ return next .sealOrErr ()
158193}
159194
160195// DerivedFrom determines where a L2 block was first derived from.
@@ -176,6 +211,10 @@ func (db *DB) DerivedFrom(derived eth.BlockID) (derivedFrom types.BlockSeal, err
176211func (db * DB ) PreviousDerivedFrom (derivedFrom eth.BlockID ) (prevDerivedFrom types.BlockSeal , err error ) {
177212 db .rwLock .RLock ()
178213 defer db .rwLock .RUnlock ()
214+ return db .previousDerivedFrom (derivedFrom )
215+ }
216+
217+ func (db * DB ) previousDerivedFrom (derivedFrom eth.BlockID ) (prevDerivedFrom types.BlockSeal , err error ) {
179218 // get the last time this L1 block was seen.
180219 selfIndex , self , err := db .firstDerivedAt (derivedFrom .Number )
181220 if err != nil {
@@ -219,25 +258,26 @@ func (db *DB) NextDerivedFrom(derivedFrom eth.BlockID) (nextDerivedFrom types.Bl
219258}
220259
221260// FirstAfter determines the next entry after the given pair of derivedFrom, derived.
222- // Either one or both of the two entries will be an increment by 1
223- func (db * DB ) FirstAfter (derivedFrom , derived eth.BlockID ) (nextDerivedFrom , nextDerived types.BlockSeal , err error ) {
261+ // Either one or both of the two entries will be an increment by 1.
262+ // This may return types.ErrAwaitReplacementBlock if the entry was invalidated and needs replacement.
263+ func (db * DB ) FirstAfter (derivedFrom , derived eth.BlockID ) (pair types.DerivedBlockSealPair , err error ) {
224264 db .rwLock .RLock ()
225265 defer db .rwLock .RUnlock ()
226266 selfIndex , selfLink , err := db .lookup (derivedFrom .Number , derived .Number )
227267 if err != nil {
228- return types.BlockSeal {}, types. BlockSeal {}, err
268+ return types.DerivedBlockSealPair {}, err
229269 }
230270 if selfLink .derivedFrom .ID () != derivedFrom {
231- return types.BlockSeal {}, types. BlockSeal {}, fmt .Errorf ("DB has derived-from %s but expected %s: %w" , selfLink .derivedFrom , derivedFrom , types .ErrConflict )
271+ return types.DerivedBlockSealPair {}, fmt .Errorf ("DB has derived-from %s but expected %s: %w" , selfLink .derivedFrom , derivedFrom , types .ErrConflict )
232272 }
233273 if selfLink .derived .ID () != derived {
234- return types.BlockSeal {}, types. BlockSeal {}, fmt .Errorf ("DB has derived %s but expected %s: %w" , selfLink .derived , derived , types .ErrConflict )
274+ return types.DerivedBlockSealPair {}, fmt .Errorf ("DB has derived %s but expected %s: %w" , selfLink .derived , derived , types .ErrConflict )
235275 }
236276 next , err := db .readAt (selfIndex + 1 )
237277 if err != nil {
238- return types.BlockSeal {}, types. BlockSeal {}, err
278+ return types.DerivedBlockSealPair {}, err
239279 }
240- return next .derivedFrom , next . derived , nil
280+ return next .sealOrErr ()
241281}
242282
243283func (db * DB ) lastDerivedFrom (derived uint64 ) (entrydb.EntryIdx , LinkEntry , error ) {
0 commit comments