forked from cerc-io/plugeth
core: eth: rpc: implement safe rpc block (#25165)
* core: eth: rpc: implement safe rpc block * core: fix setHead, panics
This commit is contained in:
+35
-3
@@ -51,6 +51,7 @@ var (
|
||||
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
|
||||
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
|
||||
headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
|
||||
headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil)
|
||||
|
||||
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
|
||||
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
|
||||
@@ -191,6 +192,7 @@ type BlockChain struct {
|
||||
currentBlock atomic.Value // Current head of the block chain
|
||||
currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!)
|
||||
currentFinalizedBlock atomic.Value // Current finalized head
|
||||
currentSafeBlock atomic.Value // Current safe head
|
||||
|
||||
stateCache state.Database // State database to reuse between imports (contains state cache)
|
||||
bodyCache *lru.Cache // Cache for the most recent block bodies
|
||||
@@ -267,6 +269,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
||||
bc.currentBlock.Store(nilBlock)
|
||||
bc.currentFastBlock.Store(nilBlock)
|
||||
bc.currentFinalizedBlock.Store(nilBlock)
|
||||
bc.currentSafeBlock.Store(nilBlock)
|
||||
|
||||
// Initialize the chain with ancient data if it isn't empty.
|
||||
var txIndexBlock uint64
|
||||
@@ -464,11 +467,15 @@ func (bc *BlockChain) loadLastState() error {
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the last known finalized block
|
||||
// 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{}) {
|
||||
if block := bc.GetBlockByHash(head); block != nil {
|
||||
bc.currentFinalizedBlock.Store(block)
|
||||
headFinalizedBlockGauge.Update(int64(block.NumberU64()))
|
||||
bc.currentSafeBlock.Store(block)
|
||||
headSafeBlockGauge.Update(int64(block.NumberU64()))
|
||||
}
|
||||
}
|
||||
// Issue a status log for the user
|
||||
@@ -504,8 +511,23 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
||||
// SetFinalized sets the finalized block.
|
||||
func (bc *BlockChain) SetFinalized(block *types.Block) {
|
||||
bc.currentFinalizedBlock.Store(block)
|
||||
rawdb.WriteFinalizedBlockHash(bc.db, block.Hash())
|
||||
headFinalizedBlockGauge.Update(int64(block.NumberU64()))
|
||||
if block != nil {
|
||||
rawdb.WriteFinalizedBlockHash(bc.db, block.Hash())
|
||||
headFinalizedBlockGauge.Update(int64(block.NumberU64()))
|
||||
} else {
|
||||
rawdb.WriteFinalizedBlockHash(bc.db, common.Hash{})
|
||||
headFinalizedBlockGauge.Update(0)
|
||||
}
|
||||
}
|
||||
|
||||
// SetSafe sets the safe block.
|
||||
func (bc *BlockChain) SetSafe(block *types.Block) {
|
||||
bc.currentSafeBlock.Store(block)
|
||||
if block != nil {
|
||||
headSafeBlockGauge.Update(int64(block.NumberU64()))
|
||||
} else {
|
||||
headSafeBlockGauge.Update(0)
|
||||
}
|
||||
}
|
||||
|
||||
// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
|
||||
@@ -663,6 +685,16 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash, repair bo
|
||||
bc.txLookupCache.Purge()
|
||||
bc.futureBlocks.Purge()
|
||||
|
||||
// Clear safe block, finalized block if needed
|
||||
if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.NumberU64() {
|
||||
log.Warn("SetHead invalidated safe block")
|
||||
bc.SetSafe(nil)
|
||||
}
|
||||
if finalized := bc.CurrentFinalizedBlock(); finalized != nil && head < finalized.NumberU64() {
|
||||
log.Error("SetHead invalidated finalized block")
|
||||
bc.SetFinalized(nil)
|
||||
}
|
||||
|
||||
return rootNumber, bc.loadLastState()
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@ func (bc *BlockChain) CurrentFinalizedBlock() *types.Block {
|
||||
return bc.currentFinalizedBlock.Load().(*types.Block)
|
||||
}
|
||||
|
||||
// CurrentSafeBlock retrieves the current safe block of the canonical
|
||||
// chain. The block is retrieved from the blockchain's internal cache.
|
||||
func (bc *BlockChain) CurrentSafeBlock() *types.Block {
|
||||
return bc.currentSafeBlock.Load().(*types.Block)
|
||||
}
|
||||
|
||||
// HasHeader checks if a block header is present in the database or not, caching
|
||||
// it if present.
|
||||
func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
|
||||
|
||||
Reference in New Issue
Block a user