@@ -141,9 +141,9 @@ type L1MessageIterator struct {
141
141
maxQueueIndex uint64
142
142
}
143
143
144
- // IterateL1MessagesFrom creates an L1MessageIterator that iterates over
144
+ // iterateL1MessagesFrom creates an L1MessageIterator that iterates over
145
145
// all L1 message in the database starting at the provided enqueue index.
146
- func IterateL1MessagesFrom (db ethdb.Database , fromQueueIndex uint64 ) L1MessageIterator {
146
+ func iterateL1MessagesFrom (db ethdb.Database , fromQueueIndex uint64 ) L1MessageIterator {
147
147
start := encodeBigEndian (fromQueueIndex )
148
148
it := db .NewIterator (l1MessagePrefix , start )
149
149
keyLength := len (l1MessagePrefix ) + 8
@@ -208,10 +208,72 @@ func (it *L1MessageIterator) Error() error {
208
208
return it .inner .Error ()
209
209
}
210
210
211
- // ReadL1MessagesFrom retrieves up to `maxCount` L1 messages starting at `startIndex`.
212
- func ReadL1MessagesFrom (db ethdb.Database , startIndex , maxCount uint64 ) []types.L1MessageTx {
211
+ // L1MessageV1Iterator is a wrapper around L1MessageIterator that allows us to iterate over L1 messages V1.
212
+ type L1MessageV1Iterator struct {
213
+ db ethdb.Database
214
+ v2StartIndex * uint64
215
+ L1MessageIterator
216
+ }
217
+
218
+ // IterateL1MessagesV1From yields a L1MessageV1Iterator with following behavior:
219
+ // - If fromQueueIndex >= L1MessageV2StartIndex: yield 0 messages.
220
+ // - Otherwise, simply yield all messages (guaranteed to be V1) starting from `fromQueueIndex` until `L1MessageV2StartIndex`.
221
+ func IterateL1MessagesV1From (db ethdb.Database , fromQueueIndex uint64 ) L1MessageV1Iterator {
222
+ return L1MessageV1Iterator {
223
+ db : db ,
224
+ v2StartIndex : ReadL1MessageV2StartIndex (db ),
225
+ L1MessageIterator : iterateL1MessagesFrom (db , fromQueueIndex ),
226
+ }
227
+ }
228
+
229
+ func (it * L1MessageV1Iterator ) Next () bool {
230
+ for it .L1MessageIterator .Next () {
231
+ // L1MessageV2StartIndex is the first queue index of L1 messages that are from L1MessageQueueV2.
232
+ // Therefore, we stop reading L1 messages V1 when we reach this index.
233
+ // We need to check in every iteration if not yet set as the start index can be set in the meantime when we are reading L1 messages.
234
+ if it .v2StartIndex == nil {
235
+ it .v2StartIndex = ReadL1MessageV2StartIndex (it .db )
236
+ }
237
+
238
+ if it .v2StartIndex != nil && it .QueueIndex () >= * it .v2StartIndex {
239
+ return false
240
+ }
241
+ return true
242
+ }
243
+ return false
244
+ }
245
+
246
+ // L1MessageV2Iterator is a wrapper around L1MessageIterator that allows us to iterate over L1 messages V2.
247
+ type L1MessageV2Iterator struct {
248
+ v2StartIndex * uint64
249
+ L1MessageIterator
250
+ }
251
+
252
+ // IterateL1MessagesV2From yields a L1MessageV2Iterator with following behavior:
253
+ // - If fromQueueIndex < v2StartIndex: yield 0 messages.
254
+ // - Otherwise, simply yield all messages (guaranteed to be v2) starting from `fromQueueIndex`.
255
+ func IterateL1MessagesV2From (db ethdb.Database , fromQueueIndex uint64 ) L1MessageV2Iterator {
256
+ v2StartIndex := ReadL1MessageV2StartIndex (db )
257
+
258
+ return L1MessageV2Iterator {
259
+ v2StartIndex : v2StartIndex ,
260
+ L1MessageIterator : iterateL1MessagesFrom (db , fromQueueIndex ),
261
+ }
262
+ }
263
+
264
+ func (it * L1MessageV2Iterator ) Next () bool {
265
+ if it .v2StartIndex == nil {
266
+ return false
267
+ }
268
+
269
+ return it .L1MessageIterator .Next () && it .QueueIndex () >= * it .v2StartIndex
270
+ }
271
+
272
+ // ReadL1MessagesV1From retrieves up to `maxCount` L1 messages V1 starting at `startIndex`.
273
+ // If startIndex is >= L1MessageV2StartIndex, this function returns an empty slice.
274
+ func ReadL1MessagesV1From (db ethdb.Database , startIndex , maxCount uint64 ) []types.L1MessageTx {
213
275
msgs := make ([]types.L1MessageTx , 0 , maxCount )
214
- it := IterateL1MessagesFrom (db , startIndex )
276
+ it := IterateL1MessagesV1From (db , startIndex )
215
277
defer it .Release ()
216
278
217
279
index := startIndex
@@ -223,7 +285,50 @@ func ReadL1MessagesFrom(db ethdb.Database, startIndex, maxCount uint64) []types.
223
285
// sanity check
224
286
if msg .QueueIndex != index {
225
287
log .Crit (
226
- "Unexpected QueueIndex in ReadL1MessagesFrom" ,
288
+ "Unexpected QueueIndex in ReadL1MessagesV1From" ,
289
+ "expected" , index ,
290
+ "got" , msg .QueueIndex ,
291
+ "startIndex" , startIndex ,
292
+ "maxCount" , maxCount ,
293
+ )
294
+ }
295
+
296
+ msgs = append (msgs , msg )
297
+ index += 1
298
+ count -= 1
299
+
300
+ iteratorL1MessageSizeGauge .Update (int64 (unsafe .Sizeof (msg ) + uintptr (cap (msg .Data ))))
301
+
302
+ if msg .QueueIndex == it .maxQueueIndex {
303
+ break
304
+ }
305
+ }
306
+
307
+ if err := it .Error (); err != nil {
308
+ log .Crit ("Failed to read L1 messages" , "err" , err )
309
+ }
310
+
311
+ return msgs
312
+ }
313
+
314
+ // ReadL1MessagesV2From retrieves up to `maxCount` L1 messages V2 starting at `startIndex`.
315
+ // If startIndex is smaller than L1MessageV2StartIndex, this function returns an empty slice.
316
+ func ReadL1MessagesV2From (db ethdb.Database , startIndex , maxCount uint64 ) []types.L1MessageTx {
317
+ msgs := make ([]types.L1MessageTx , 0 , maxCount )
318
+
319
+ it := IterateL1MessagesV2From (db , startIndex )
320
+ defer it .Release ()
321
+
322
+ index := startIndex
323
+ count := maxCount
324
+
325
+ for count > 0 && it .Next () {
326
+ msg := it .L1Message ()
327
+
328
+ // sanity check
329
+ if msg .QueueIndex != index {
330
+ log .Crit (
331
+ "Unexpected QueueIndex in ReadL1MessagesV2From" ,
227
332
"expected" , index ,
228
333
"got" , msg .QueueIndex ,
229
334
"startIndex" , startIndex ,
@@ -275,3 +380,65 @@ func ReadFirstQueueIndexNotInL2Block(db ethdb.Reader, l2BlockHash common.Hash) *
275
380
queueIndex := binary .BigEndian .Uint64 (data )
276
381
return & queueIndex
277
382
}
383
+
384
+ // WriteL1MessageV2StartIndex writes the start index of L1 messages that are from L1MessageQueueV2.
385
+ func WriteL1MessageV2StartIndex (db ethdb.KeyValueWriter , queueIndex uint64 ) {
386
+ value := big .NewInt (0 ).SetUint64 (queueIndex ).Bytes ()
387
+
388
+ if err := db .Put (l1MessageV2StartIndexKey , value ); err != nil {
389
+ log .Crit ("Failed to update L1MessageV2 start index" , "err" , err )
390
+ }
391
+ }
392
+
393
+ // ReadL1MessageV2StartIndex retrieves the start index of L1 messages that are from L1MessageQueueV2.
394
+ func ReadL1MessageV2StartIndex (db ethdb.Reader ) * uint64 {
395
+ data , err := db .Get (l1MessageV2StartIndexKey )
396
+ if err != nil && isNotFoundErr (err ) {
397
+ return nil
398
+ }
399
+ if err != nil {
400
+ log .Crit ("Failed to read L1MessageV2 start index from database" , "err" , err )
401
+ }
402
+ if len (data ) == 0 {
403
+ return nil
404
+ }
405
+
406
+ number := new (big.Int ).SetBytes (data )
407
+ if ! number .IsUint64 () {
408
+ log .Crit ("Unexpected number for L1MessageV2 start index" , "number" , number )
409
+ }
410
+
411
+ res := number .Uint64 ()
412
+ return & res
413
+ }
414
+
415
+ // WriteL1MessageV2FirstL1BlockNumber writes the first synced L1 block number for L1MessageV2.
416
+ func WriteL1MessageV2FirstL1BlockNumber (db ethdb.KeyValueWriter , l1BlockNumber uint64 ) {
417
+ value := big .NewInt (0 ).SetUint64 (l1BlockNumber ).Bytes ()
418
+
419
+ if err := db .Put (l1MessageV2FirstL1BlockNumberKey , value ); err != nil {
420
+ log .Crit ("Failed to update L1MessageV2 start index" , "err" , err )
421
+ }
422
+ }
423
+
424
+ // ReadL1MessageV2FirstL1BlockNumber retrieves the first synced L1 block number for L1MessageV2.
425
+ func ReadL1MessageV2FirstL1BlockNumber (db ethdb.Reader ) * uint64 {
426
+ data , err := db .Get (l1MessageV2FirstL1BlockNumberKey )
427
+ if err != nil && isNotFoundErr (err ) {
428
+ return nil
429
+ }
430
+ if err != nil {
431
+ log .Crit ("Failed to read L1MessageV2 first L1 block number from database" , "err" , err )
432
+ }
433
+ if len (data ) == 0 {
434
+ return nil
435
+ }
436
+
437
+ number := new (big.Int ).SetBytes (data )
438
+ if ! number .IsUint64 () {
439
+ log .Crit ("Unexpected number for L1MessageV2 first L1 block number" , "number" , number )
440
+ }
441
+
442
+ res := number .Uint64 ()
443
+ return & res
444
+ }
0 commit comments