@@ -91,6 +91,7 @@ type work struct {
91
91
cccLogger * ccc.Logger
92
92
vmConfig vm.Config
93
93
94
+ reorging bool
94
95
reorgReason error
95
96
96
97
// accumulated state
@@ -287,7 +288,7 @@ func (w *worker) mainLoop() {
287
288
var retryableCommitError * retryableCommitError
288
289
if errors .As (err , & retryableCommitError ) {
289
290
log .Warn ("failed to commit to a block, retrying" , "err" , err )
290
- if _ , err = w .tryCommitNewWork (time .Now (), w .current .header .ParentHash , w .current .reorgReason ); err != nil {
291
+ if _ , err = w .tryCommitNewWork (time .Now (), w .current .header .ParentHash , w .current .reorging , w . current . reorgReason ); err != nil {
291
292
continue
292
293
}
293
294
} else if err != nil {
@@ -305,21 +306,20 @@ func (w *worker) mainLoop() {
305
306
return
306
307
}
307
308
}
308
-
309
- _ , err = w .tryCommitNewWork (time .Now (), w .chain .CurrentHeader ().Hash (), nil )
309
+ _ , err = w .tryCommitNewWork (time .Now (), w .chain .CurrentHeader ().Hash (), false , nil )
310
310
case trigger := <- w .reorgCh :
311
311
idleTimer .UpdateSince (idleStart )
312
312
err = w .handleReorg (& trigger )
313
313
case chainHead := <- w .chainHeadCh :
314
314
idleTimer .UpdateSince (idleStart )
315
315
if w .isCanonical (chainHead .Block .Header ()) {
316
- _ , err = w .tryCommitNewWork (time .Now (), chainHead .Block .Hash (), nil )
316
+ _ , err = w .tryCommitNewWork (time .Now (), chainHead .Block .Hash (), false , nil )
317
317
}
318
318
case <- w .current .deadlineCh ():
319
319
idleTimer .UpdateSince (idleStart )
320
320
w .current .deadlineReached = true
321
321
if len (w .current .txs ) > 0 {
322
- _ , err = w .commit (false )
322
+ _ , err = w .commit ()
323
323
}
324
324
case ev := <- w .txsCh :
325
325
idleTimer .UpdateSince (idleStart )
@@ -330,8 +330,8 @@ func (w *worker) mainLoop() {
330
330
// be automatically eliminated.
331
331
if w .current != nil {
332
332
shouldCommit , _ := w .processTxnSlice (ev .Txs )
333
- if shouldCommit || w .current .deadlineReached {
334
- _ , err = w .commit (false )
333
+ if shouldCommit || ( w .current .deadlineReached && len ( w . current . txs ) > 0 ) {
334
+ _ , err = w .commit ()
335
335
}
336
336
}
337
337
w .newTxs .Add (int32 (len (ev .Txs )))
@@ -370,7 +370,7 @@ func (w *worker) collectPendingL1Messages(startIndex uint64) []types.L1MessageTx
370
370
}
371
371
372
372
// newWork
373
- func (w * worker ) newWork (now time.Time , parentHash common.Hash , reorgReason error ) error {
373
+ func (w * worker ) newWork (now time.Time , parentHash common.Hash , reorging bool , reorgReason error ) error {
374
374
parent := w .chain .GetBlockByHash (parentHash )
375
375
header := & types.Header {
376
376
ParentHash : parent .Hash (),
@@ -380,6 +380,13 @@ func (w *worker) newWork(now time.Time, parentHash common.Hash, reorgReason erro
380
380
Time : uint64 (now .Unix ()),
381
381
}
382
382
383
+ if reorgReason != nil {
384
+ // if we are replacing a failing block, reuse the timestamp to make sure
385
+ // the information we get from AsyncChecker is reliable. Changing timestamp
386
+ // might alter execution flow of reorged transactions.
387
+ header .Time = w .chain .GetHeaderByNumber (header .Number .Uint64 ()).Time
388
+ }
389
+
383
390
parentState , err := w .chain .StateAt (parent .Root ())
384
391
if err != nil {
385
392
return fmt .Errorf ("failed to fetch parent state: %w" , err )
@@ -431,14 +438,19 @@ func (w *worker) newWork(now time.Time, parentHash common.Hash, reorgReason erro
431
438
coalescedLogs : []* types.Log {},
432
439
gasPool : new (core.GasPool ).AddGas (header .GasLimit ),
433
440
nextL1MsgIndex : nextL1MsgIndex ,
441
+ reorging : reorging ,
434
442
reorgReason : reorgReason ,
435
443
}
444
+
445
+ // initiliaze pending block with an empty block to make sure we always have
446
+ // a pending block to serve RPC requests
447
+ w .updateSnapshot ()
436
448
return nil
437
449
}
438
450
439
451
// tryCommitNewWork
440
- func (w * worker ) tryCommitNewWork (now time.Time , parent common.Hash , reorgReason error ) (common.Hash , error ) {
441
- err := w .newWork (now , parent , reorgReason )
452
+ func (w * worker ) tryCommitNewWork (now time.Time , parent common.Hash , reorging bool , reorgReason error ) (common.Hash , error ) {
453
+ err := w .newWork (now , parent , reorging , reorgReason )
442
454
if err != nil {
443
455
return common.Hash {}, fmt .Errorf ("failed creating new work: %w" , err )
444
456
}
@@ -449,8 +461,7 @@ func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorgReason
449
461
}
450
462
451
463
// check if we are reorging
452
- reorging := w .chain .GetBlockByNumber (w .current .header .Number .Uint64 ()) != nil
453
- if ! shouldCommit && reorging {
464
+ if ! shouldCommit && w .current .reorging {
454
465
shouldCommit , err = w .processReorgedTxns (w .current .reorgReason )
455
466
}
456
467
if err != nil {
@@ -468,7 +479,7 @@ func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorgReason
468
479
// if reorging, force committing even if we are not "running"
469
480
// this can happen when sequencer is instructed to shutdown while handling a reorg
470
481
// we should make sure reorg is not interrupted
471
- if blockHash , err := w .commit (reorging ); err != nil {
482
+ if blockHash , err := w .commit (); err != nil {
472
483
return common.Hash {}, fmt .Errorf ("failed committing new work: %w" , err )
473
484
} else {
474
485
return blockHash , nil
@@ -595,6 +606,10 @@ func (w *worker) processTxnSlice(txns types.Transactions) (bool, error) {
595
606
// processReorgedTxns
596
607
func (w * worker ) processReorgedTxns (reason error ) (bool , error ) {
597
608
reorgedBlock := w .chain .GetBlockByNumber (w .current .header .Number .Uint64 ())
609
+ if reorgedBlock == nil {
610
+ return false , nil
611
+ }
612
+
598
613
commitGasCounter .Dec (int64 (reorgedBlock .GasUsed ()))
599
614
reorgedTxns := reorgedBlock .Transactions ()
600
615
var errorWithTxnIdx * ccc.ErrorWithTxnIdx
@@ -729,14 +744,14 @@ func (e retryableCommitError) Unwrap() error {
729
744
730
745
// commit runs any post-transaction state modifications, assembles the final block
731
746
// and commits new work if consensus engine is running.
732
- func (w * worker ) commit (reorging bool ) (common.Hash , error ) {
747
+ func (w * worker ) commit () (common.Hash , error ) {
733
748
sealDelay := time .Duration (0 )
734
749
defer func (t0 time.Time ) {
735
750
l2CommitTimer .Update (time .Since (t0 ) - sealDelay )
736
751
}(time .Now ())
737
752
738
753
w .updateSnapshot ()
739
- if ! w .isRunning () && ! reorging {
754
+ if ! w .isRunning () && ! w . current . reorging {
740
755
return common.Hash {}, nil
741
756
}
742
757
@@ -813,7 +828,7 @@ func (w *worker) commit(reorging bool) (common.Hash, error) {
813
828
814
829
currentHeight := w .current .header .Number .Uint64 ()
815
830
maxReorgDepth := uint64 (w .config .CCCMaxWorkers + 1 )
816
- if ! reorging && currentHeight > maxReorgDepth {
831
+ if ! w . current . reorging && currentHeight > maxReorgDepth {
817
832
ancestorHeight := currentHeight - maxReorgDepth
818
833
ancestorHash := w .chain .GetHeaderByNumber (ancestorHeight ).Hash ()
819
834
if rawdb .ReadBlockRowConsumption (w .chain .Database (), ancestorHash ) == nil {
@@ -980,7 +995,7 @@ func (w *worker) handleReorg(trigger *reorgTrigger) error {
980
995
return nil
981
996
}
982
997
983
- newBlockHash , err := w .tryCommitNewWork (time .Now (), parentHash , reorgReason )
998
+ newBlockHash , err := w .tryCommitNewWork (time .Now (), parentHash , true , reorgReason )
984
999
if err != nil {
985
1000
return err
986
1001
}
@@ -989,7 +1004,7 @@ func (w *worker) handleReorg(trigger *reorgTrigger) error {
989
1004
if newBlockHash == (common.Hash {}) {
990
1005
// force committing the new canonical head to trigger a reorg in blockchain
991
1006
// otherwise we might ignore CCC errors from the new side chain since it is not canonical yet
992
- newBlockHash , err = w .commit (true )
1007
+ newBlockHash , err = w .commit ()
993
1008
if err != nil {
994
1009
return err
995
1010
}
0 commit comments