Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/finalizer core blockchain elaboration #77

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 27 additions & 33 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ var (
headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil)
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
headJustifiedBlockGauge = metrics.NewRegisteredGauge("chain/head/justified", nil)
headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)

justifiedBlockGauge = metrics.NewRegisteredGauge("chain/head/justified", nil)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

justifiedBlockGaugeの方がBSCと同じで検索しやすいので、変更しました。
また、go-etherumには存在しないことをわかりやすくするために、headは付けない方がいいと思われます。


chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)

accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
Expand Down Expand Up @@ -323,6 +324,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis

bc.currentBlock.Store(nil)
bc.currentSnapBlock.Store(nil)
bc.currentFinalBlock.Store(nil)

// Update chain info data metrics
chainInfoGauge.Update(metrics.GaugeInfoValue{"chain_id": bc.chainConfig.ChainID.String()})
Expand Down Expand Up @@ -511,17 +513,6 @@ func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 {
return 0
}

// getFinalizedNumber returns the highest finalized number before the specific block.
func (bc *BlockChain) getFinalizedNumber(header *types.Header) uint64 {
if p, ok := bc.engine.(consensus.PoS); ok {
if finalizedHeader := p.GetFinalizedHeader(bc, header); finalizedHeader != nil {
return finalizedHeader.Number.Uint64()
}
}

return 0
}

// loadLastState loads the last known chain state from the database. This method
// assumes that the chain manager mutex is held.
func (bc *BlockChain) loadLastState() error {
Expand All @@ -542,8 +533,6 @@ func (bc *BlockChain) loadLastState() error {
// Everything seems to be fine, set as the head block
bc.currentBlock.Store(headBlock.Header())
headBlockGauge.Update(int64(headBlock.NumberU64()))
headJustifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(headBlock.Header())))
headFinalizedBlockGauge.Update(int64(bc.getFinalizedNumber(headBlock.Header())))

// Restore the last known head header
headHeader := headBlock.Header()
Expand All @@ -565,9 +554,19 @@ func (bc *BlockChain) loadLastState() error {
}
}

// Restore the last known finalized block and safe block
// Note: the safe block is not stored on disk and it is set to the last
// known finalized block on startup
if head := rawdb.ReadFinalizedBlockHash(bc.db); head != (common.Hash{}) {
Copy link
Contributor Author

@tak1827 tak1827 Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この処理を戻しました。
loadLastState内で、Oasysコンセンサスにアクセスできないので
参照: discordでの補足

Q: ストレージから読み出したblockをセットしていいかどうか?
loadLastStateは起動時と、setHeadBeyondRootの2箇所で呼ばれます。
起動時にセットするのは自然。
問題は、setHeadBeyondRootのケース。
この処理内でストレージに書き込む処理(=SetFinalized)を行っています。
なので、ここで読み出すのは正しいはず

if block := bc.GetBlockByHash(head); block != nil {
bc.currentFinalBlock.Store(block.Header())
headFinalizedBlockGauge.Update(int64(block.NumberU64()))
}
}
// Issue a status log for the user
var (
currentSnapBlock = bc.CurrentSnapBlock()
currentSnapBlock = bc.CurrentSnapBlock()
currentFinalBlock = bc.CurrentFinalBlock()

headerTd = bc.GetTd(headHeader.Hash(), headHeader.Number.Uint64())
blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64())
Expand All @@ -580,13 +579,9 @@ func (bc *BlockChain) loadLastState() error {
snapTd := bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64())
log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "root", currentSnapBlock.Root, "td", snapTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0)))
}
if posa, ok := bc.engine.(consensus.PoS); ok {
if currentFinalizedHeader := posa.GetFinalizedHeader(bc, headHeader); currentFinalizedHeader != nil {
if currentFinalizedBlock := bc.GetBlockByHash(currentFinalizedHeader.Hash()); currentFinalizedBlock != nil {
finalTd := bc.GetTd(currentFinalizedBlock.Hash(), currentFinalizedBlock.NumberU64())
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)))
}
}
if currentFinalBlock != nil {
finalTd := bc.GetTd(currentFinalBlock.Hash(), currentFinalBlock.Number.Uint64())
log.Info("Loaded most recent local finalized block", "number", currentFinalBlock.Number, "hash", currentFinalBlock.Hash(), "root", currentFinalBlock.Root, "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalBlock.Time), 0)))
}
if pivot := rawdb.ReadLastPivotNumber(bc.db); pivot != nil {
log.Info("Loaded last snap-sync pivot marker", "number", *pivot)
Expand Down Expand Up @@ -817,7 +812,11 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
bc.txLookupCache.Purge()
bc.futureBlocks.Purge()

// Clear finalized block if needed
// Clear safe block, finalized block if needed
if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.Number.Uint64() {
log.Warn("SetHead invalidated safe block")
justifiedBlockGauge.Update(0)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

justifiedのゲージもゼロにセット

}
if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() {
log.Error("SetHead invalidated finalized block")
bc.SetFinalized(nil)
Expand Down Expand Up @@ -849,8 +848,6 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
}
bc.currentBlock.Store(block.Header())
headBlockGauge.Update(int64(block.NumberU64()))
headJustifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(block.Header())))
headFinalizedBlockGauge.Update(int64(bc.getFinalizedNumber(block.Header())))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここではセットしない。
writeBlockAndSetHeadで更新するようにしたので。

bc.chainmu.Unlock()

// Destroy any existing state snapshot and regenerate it in the background,
Expand Down Expand Up @@ -892,7 +889,7 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
bc.genesisBlock = genesis
bc.currentBlock.Store(bc.genesisBlock.Header())
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
headJustifiedBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
justifiedBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
headFinalizedBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
bc.hc.SetGenesis(bc.genesisBlock.Header())
bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
Expand Down Expand Up @@ -965,8 +962,6 @@ func (bc *BlockChain) writeHeadBlock(block *types.Block) {

bc.currentBlock.Store(block.Header())
headBlockGauge.Update(int64(block.NumberU64()))
headJustifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(block.Header())))
headFinalizedBlockGauge.Update(int64(bc.getFinalizedNumber(block.Header())))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここでセットしなくても、いずれ(writeBlockAndSetHeadで)セットされる

}

// stopWithoutSaving stops the blockchain service. If any imports are currently in progress
Expand Down Expand Up @@ -1541,6 +1536,9 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
if finalizedHeader = pos.GetFinalizedHeader(bc, block.Header()); finalizedHeader != nil {
bc.SetFinalized(finalizedHeader)
}
if justifiedBlockNumber, _, err := pos.GetJustifiedNumberAndHash(bc, []*types.Header{block.Header()}); err == nil {
justifiedBlockGauge.Update(int64(justifiedBlockNumber))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

justifiedのゲージも合わせて更新

}
}
// In theory, we should fire a ChainHeadEvent when we inject
// a canonical block, but sometimes we can insert a batch of
Expand Down Expand Up @@ -2288,7 +2286,6 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
var (
indexesBatch = bc.db.NewBatch()
diffs = types.HashDifference(deletedTxs, addedTxs)
blockBatch = bc.db.NewBatch()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indexesBatchと重複してるので削除。go-etherumに合わせた

)
for _, tx := range diffs {
rawdb.DeleteTxLookupEntry(indexesBatch, tx)
Expand All @@ -2305,14 +2302,11 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
if hash == (common.Hash{}) {
break
}
rawdb.DeleteCanonicalHash(blockBatch, i)
rawdb.DeleteCanonicalHash(indexesBatch, i)
}
if err := indexesBatch.Write(); err != nil {
log.Crit("Failed to delete useless indexes", "err", err)
}
if err := blockBatch.Write(); err != nil {
log.Crit("Failed to delete useless indexes use block batch", "err", err)
}

// Send out events for logs from the old canon chain, and 'reborn'
// logs from the new canon chain. The number of logs can be very
Expand Down
10 changes: 1 addition & 9 deletions core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,7 @@ func (bc *BlockChain) CurrentSnapBlock() *types.Header {
// CurrentFinalBlock retrieves the current finalized block of the canonical
// chain. The block is retrieved from the blockchain's internal cache.
func (bc *BlockChain) CurrentFinalBlock() *types.Header {
if p, ok := bc.engine.(consensus.PoS); ok {
currentHeader := bc.CurrentHeader()
if currentHeader == nil {
return nil
}
return p.GetFinalizedHeader(bc, currentHeader)
}

return nil
return bc.currentFinalBlock.Load()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

キャッシュの値を信頼できるようにしました。
currentFinalBlockは3箇所でセットされます。

  1. 起動にNulをセット
  2. 起動時にストレージからの読み出し値をセット
  3. SetFinalizedされた時にセット

3のSetFinalizedが呼ばれるタイミングは、
Blockを自分で作ったとき、Syncしたとき、SetHeadしたとき
すべてのケースをカバーしているはず

}

// CurrentSafeBlock retrieves the current safe block of the canonical
Expand Down
17 changes: 0 additions & 17 deletions core/headerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
}
hc.currentHeaderHash = hc.CurrentHeader().Hash()
headHeaderGauge.Update(hc.CurrentHeader().Number.Int64())
headJustifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(hc.CurrentHeader())))
headFinalizedBlockGauge.Update(int64(hc.getFinalizedNumber(hc.CurrentHeader())))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

パニックするので削除


return hc, nil
}
Expand All @@ -123,17 +121,6 @@ func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 {
return 0
}

// getFinalizedNumber returns the highest finalized number before the specific block.
func (hc *HeaderChain) getFinalizedNumber(header *types.Header) uint64 {
if p, ok := hc.engine.(consensus.PoS); ok {
if finalizedHeader := p.GetFinalizedHeader(hc, header); finalizedHeader != nil {
return finalizedHeader.Number.Uint64()
}
}

return 0
}

// GetBlockNumber retrieves the block number belonging to the given hash
// from the cache or database
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
Expand Down Expand Up @@ -561,8 +548,6 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
hc.currentHeader.Store(head)
hc.currentHeaderHash = head.Hash()
headHeaderGauge.Update(head.Number.Int64())
headJustifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(head)))
headFinalizedBlockGauge.Update(int64(hc.getFinalizedNumber(head)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetCurrentHeaderが呼ばれるのと同じタイミングで、
finalizeとjustifyのゲージも更新される。つまり、重複更新なので削除

}

type (
Expand Down Expand Up @@ -649,8 +634,6 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
hc.currentHeader.Store(parent)
hc.currentHeaderHash = parentHash
headHeaderGauge.Update(parent.Number.Int64())
headJustifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(parent)))
headFinalizedBlockGauge.Update(int64(hc.getFinalizedNumber(parent)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここも重複更新


// If this is the first iteration, wipe any leftover data upwards too so
// we don't end up with dangling daps in the database
Expand Down