From eeb2d43a7989dd960bce55b740050c47d1d8a074 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 31 Jan 2025 16:10:29 +0900 Subject: [PATCH] blockchain: add exports methods based on block header tip The added exported methods on BlockChain provide access to the block header tip like fetching block hashes and heights from the headers chain. --- blockchain/chain.go | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index 58d7256d..960e2807 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1344,6 +1344,15 @@ func (b *BlockChain) BestSnapshot() *BestState { return snapshot } +// BestHeader returns the hash and the height of the best header. +func (b *BlockChain) BestHeader() (chainhash.Hash, int32) { + b.chainLock.RLock() + defer b.chainLock.RUnlock() + + best := b.bestHeader.Tip() + return best.hash, best.height +} + // TipStatus is the status of a chain tip. type TipStatus byte @@ -1535,6 +1544,54 @@ func (b *BlockChain) BlockHashByHeight(blockHeight int32) (*chainhash.Hash, erro return &node.hash, nil } +// IsValidHeader checks that we've already checked that this header connects to the +// chain of best headers and did not receive an invalid state. +func (b *BlockChain) IsValidHeader(blockHash *chainhash.Hash) bool { + node := b.index.LookupNode(blockHash) + if node == nil || !b.bestHeader.Contains(node) { + return false + } + + return !b.index.NodeStatus(node).KnownInvalid() +} + +// LatestBlockLocatorByHeader returns a block locator for the latest known tip of the +// header chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) LatestBlockLocatorByHeader() (BlockLocator, error) { + b.chainLock.RLock() + locator := b.bestHeader.BlockLocator(nil) + b.chainLock.RUnlock() + return locator, nil +} + +// HeaderHashByHeight returns the block header's hash given its height. +// +// NOTE: If the blockNode at the given blockHeight is not included in the +// bestHeader chain, the function will return an error indicating that the +// blockHeight wasn't found. +func (b *BlockChain) HeaderHashByHeight(blockHeight int32) ( + *chainhash.Hash, error) { + + node := b.bestHeader.NodeByHeight(blockHeight) + if node == nil || !b.bestHeader.Contains(node) { + return nil, fmt.Errorf("blockheight %v not found", blockHeight) + } + + return &node.hash, nil +} + +// HeaderHeightByHash returns the height of the header given its hash. +func (b *BlockChain) HeaderHeightByHash(blockHash chainhash.Hash) (int32, error) { + node := b.index.LookupNode(&blockHash) + if node == nil || !b.bestHeader.Contains(node) { + return -1, fmt.Errorf("blockhash %v not found", blockHash) + } + + return node.height, nil +} + // HeightRange returns a range of block hashes for the given start and end // heights. It is inclusive of the start height and exclusive of the end // height. The end height will be limited to the current main chain height.