@@ -225,14 +225,15 @@ type BlockChain struct {
225225 statedb * state.CachingDB // State database to reuse between imports (contains state cache)
226226 txIndexer * txIndexer // Transaction indexer, might be nil if not enabled
227227
228- hc * HeaderChain
229- rmLogsFeed event.Feed
230- chainFeed event.Feed
231- chainHeadFeed event.Feed
232- logsFeed event.Feed
233- blockProcFeed event.Feed
234- scope event.SubscriptionScope
235- genesisBlock * types.Block
228+ hc * HeaderChain
229+ rmLogsFeed event.Feed
230+ chainFeed event.Feed
231+ chainHeadFeed event.Feed
232+ logsFeed event.Feed
233+ blockProcFeed event.Feed
234+ finalizedHeaderFeed event.Feed
235+ scope event.SubscriptionScope
236+ genesisBlock * types.Block
236237
237238 // This mutex synchronizes chain write operations.
238239 // Readers don't need to take it, they can just read the database.
@@ -497,6 +498,17 @@ func (bc *BlockChain) empty() bool {
497498 return true
498499}
499500
501+ // GetFinalizedNumber returns the highest finalized number before the specific block.
502+ func (bc * BlockChain ) GetFinalizedNumber (header * types.Header ) uint64 {
503+ if p , ok := bc .engine .(consensus.PoS ); ok {
504+ if finalizedHeader := p .GetFinalizedHeader (bc , header ); finalizedHeader != nil {
505+ return finalizedHeader .Number .Uint64 ()
506+ }
507+ }
508+
509+ return 0
510+ }
511+
500512// loadLastState loads the last known chain state from the database. This method
501513// assumes that the chain manager mutex is held.
502514func (bc * BlockChain ) loadLastState () error {
@@ -551,8 +563,7 @@ func (bc *BlockChain) loadLastState() error {
551563 }
552564 // Issue a status log for the user
553565 var (
554- currentSnapBlock = bc .CurrentSnapBlock ()
555- currentFinalBlock = bc .CurrentFinalBlock ()
566+ currentSnapBlock = bc .CurrentSnapBlock ()
556567
557568 headerTd = bc .GetTd (headHeader .Hash (), headHeader .Number .Uint64 ())
558569 blockTd = bc .GetTd (headBlock .Hash (), headBlock .NumberU64 ())
@@ -565,9 +576,14 @@ func (bc *BlockChain) loadLastState() error {
565576 snapTd := bc .GetTd (currentSnapBlock .Hash (), currentSnapBlock .Number .Uint64 ())
566577 log .Info ("Loaded most recent local snap block" , "number" , currentSnapBlock .Number , "hash" , currentSnapBlock .Hash (), "td" , snapTd , "age" , common .PrettyAge (time .Unix (int64 (currentSnapBlock .Time ), 0 )))
567578 }
568- if currentFinalBlock != nil {
569- finalTd := bc .GetTd (currentFinalBlock .Hash (), currentFinalBlock .Number .Uint64 ())
570- log .Info ("Loaded most recent local finalized block" , "number" , currentFinalBlock .Number , "hash" , currentFinalBlock .Hash (), "td" , finalTd , "age" , common .PrettyAge (time .Unix (int64 (currentFinalBlock .Time ), 0 )))
579+ if p , ok := bc .engine .(consensus.PoS ); ok {
580+ if currentFinalizedHeader := p .GetFinalizedHeader (bc , headHeader ); currentFinalizedHeader != nil {
581+ bc .currentFinalBlock .Store (currentFinalizedHeader )
582+ if currentFinalizedBlock := bc .GetBlockByHash (currentFinalizedHeader .Hash ()); currentFinalizedBlock != nil {
583+ finalTd := bc .GetTd (currentFinalizedBlock .Hash (), currentFinalizedBlock .NumberU64 ())
584+ log .Info ("Loaded most recent local finalized block" , "number" , currentFinalizedBlock .Number (), "hash" , currentFinalizedBlock .Hash (), "root" , currentFinalizedBlock .Root (), "td" , finalTd , "age" , common .PrettyAge (time .Unix (int64 (currentFinalizedBlock .Time ()), 0 )))
585+ }
586+ }
571587 }
572588 if pivot := rawdb .ReadLastPivotNumber (bc .db ); pivot != nil {
573589 log .Info ("Loaded last snap-sync pivot marker" , "number" , * pivot )
@@ -1615,13 +1631,24 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
16151631 if len (logs ) > 0 {
16161632 bc .logsFeed .Send (logs )
16171633 }
1634+
1635+ var finalizedHeader * types.Header
1636+ if p , ok := bc .Engine ().(consensus.PoS ); ok {
1637+ if finalizedHeader = p .GetFinalizedHeader (bc , block .Header ()); finalizedHeader != nil {
1638+ bc .SetFinalized (finalizedHeader )
1639+ }
1640+ }
1641+
16181642 // In theory, we should fire a ChainHeadEvent when we inject
16191643 // a canonical block, but sometimes we can insert a batch of
16201644 // canonical blocks. Avoid firing too many ChainHeadEvents,
16211645 // we will fire an accumulated ChainHeadEvent and disable fire
16221646 // event here.
16231647 if emitHeadEvent {
16241648 bc .chainHeadFeed .Send (ChainHeadEvent {Header : block .Header ()})
1649+ if finalizedHeader != nil {
1650+ bc .finalizedHeaderFeed .Send (FinalizedHeaderEvent {finalizedHeader })
1651+ }
16251652 }
16261653 }
16271654 return status , nil
@@ -1708,6 +1735,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
17081735 defer func () {
17091736 if lastCanon != nil && bc .CurrentBlock ().Hash () == lastCanon .Hash () {
17101737 bc .chainHeadFeed .Send (ChainHeadEvent {Header : lastCanon .Header ()})
1738+ if p , ok := bc .Engine ().(consensus.PoS ); ok {
1739+ if finalizedHeader := p .GetFinalizedHeader (bc , lastCanon .Header ()); finalizedHeader != nil {
1740+ bc .finalizedHeaderFeed .Send (FinalizedHeaderEvent {finalizedHeader })
1741+ }
1742+ }
17111743 }
17121744 }()
17131745 // Start the parallel header verifier
0 commit comments