@@ -47,9 +47,10 @@ import (
47
47
)
48
48
49
49
var (
50
- headBlockGauge = metrics .NewRegisteredGauge ("chain/head/block" , nil )
51
- headHeaderGauge = metrics .NewRegisteredGauge ("chain/head/header" , nil )
52
- headFastBlockGauge = metrics .NewRegisteredGauge ("chain/head/receipt" , nil )
50
+ headBlockGauge = metrics .NewRegisteredGauge ("chain/head/block" , nil )
51
+ headHeaderGauge = metrics .NewRegisteredGauge ("chain/head/header" , nil )
52
+ headFastBlockGauge = metrics .NewRegisteredGauge ("chain/head/receipt" , nil )
53
+ headFinalizedBlockGauge = metrics .NewRegisteredGauge ("chain/head/finalized" , nil )
53
54
54
55
accountReadTimer = metrics .NewRegisteredTimer ("chain/account/reads" , nil )
55
56
accountHashTimer = metrics .NewRegisteredTimer ("chain/account/hashes" , nil )
@@ -188,8 +189,9 @@ type BlockChain struct {
188
189
// Readers don't need to take it, they can just read the database.
189
190
chainmu * syncx.ClosableMutex
190
191
191
- currentBlock atomic.Value // Current head of the block chain
192
- currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!)
192
+ currentBlock atomic.Value // Current head of the block chain
193
+ currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!)
194
+ currentFinalizedBlock atomic.Value // Current finalized head
193
195
194
196
stateCache state.Database // State database to reuse between imports (contains state cache)
195
197
bodyCache * lru.Cache // Cache for the most recent block bodies
@@ -265,6 +267,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
265
267
var nilBlock * types.Block
266
268
bc .currentBlock .Store (nilBlock )
267
269
bc .currentFastBlock .Store (nilBlock )
270
+ bc .currentFinalizedBlock .Store (nilBlock )
268
271
269
272
// Initialize the chain with ancient data if it isn't empty.
270
273
var txIndexBlock uint64
@@ -461,8 +464,17 @@ func (bc *BlockChain) loadLastState() error {
461
464
headFastBlockGauge .Update (int64 (block .NumberU64 ()))
462
465
}
463
466
}
467
+
468
+ // Restore the last known finalized block
469
+ if head := rawdb .ReadFinalizedBlockHash (bc .db ); head != (common.Hash {}) {
470
+ if block := bc .GetBlockByHash (head ); block != nil {
471
+ bc .currentFinalizedBlock .Store (block )
472
+ headFinalizedBlockGauge .Update (int64 (block .NumberU64 ()))
473
+ }
474
+ }
464
475
// Issue a status log for the user
465
476
currentFastBlock := bc .CurrentFastBlock ()
477
+ currentFinalizedBlock := bc .CurrentFinalizedBlock ()
466
478
467
479
headerTd := bc .GetTd (currentHeader .Hash (), currentHeader .Number .Uint64 ())
468
480
blockTd := bc .GetTd (currentBlock .Hash (), currentBlock .NumberU64 ())
@@ -471,6 +483,11 @@ func (bc *BlockChain) loadLastState() error {
471
483
log .Info ("Loaded most recent local header" , "number" , currentHeader .Number , "hash" , currentHeader .Hash (), "td" , headerTd , "age" , common .PrettyAge (time .Unix (int64 (currentHeader .Time ), 0 )))
472
484
log .Info ("Loaded most recent local full block" , "number" , currentBlock .Number (), "hash" , currentBlock .Hash (), "td" , blockTd , "age" , common .PrettyAge (time .Unix (int64 (currentBlock .Time ()), 0 )))
473
485
log .Info ("Loaded most recent local fast block" , "number" , currentFastBlock .Number (), "hash" , currentFastBlock .Hash (), "td" , fastTd , "age" , common .PrettyAge (time .Unix (int64 (currentFastBlock .Time ()), 0 )))
486
+
487
+ if currentFinalizedBlock != nil {
488
+ finalTd := bc .GetTd (currentFinalizedBlock .Hash (), currentFinalizedBlock .NumberU64 ())
489
+ log .Info ("Loaded most recent local finalized block" , "number" , currentFinalizedBlock .Number (), "hash" , currentFinalizedBlock .Hash (), "td" , finalTd , "age" , common .PrettyAge (time .Unix (int64 (currentFinalizedBlock .Time ()), 0 )))
490
+ }
474
491
if pivot := rawdb .ReadLastPivotNumber (bc .db ); pivot != nil {
475
492
log .Info ("Loaded last fast-sync pivot marker" , "number" , * pivot )
476
493
}
@@ -485,6 +502,13 @@ func (bc *BlockChain) SetHead(head uint64) error {
485
502
return err
486
503
}
487
504
505
+ // SetFinalized sets the finalized block.
506
+ func (bc * BlockChain ) SetFinalized (block * types.Block ) {
507
+ bc .currentFinalizedBlock .Store (block )
508
+ rawdb .WriteFinalizedBlockHash (bc .db , block .Hash ())
509
+ headFinalizedBlockGauge .Update (int64 (block .NumberU64 ()))
510
+ }
511
+
488
512
// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
489
513
// that the rewind must pass the specified state root. This method is meant to be
490
514
// used when rewinding with snapshots enabled to ensure that we go back further than
0 commit comments