blockchain: Reduce GetGeneration to TipGeneration.

This replaces the GetGeneration function which allowed getting the
entire generation (all children stemming from the same parent) of an
arbitrary bock with TipGeneration which only returns the same
information for the tip block.

This is being done because the function is only used for mining purposes
to get the generation of the current tip.  The code is simplified by
reducing its scope to its actual purpose as an initial benefit.  It also
provides much better optimization opportunities later.
This commit is contained in:
Dave Collins 2018-02-24 17:33:13 -06:00
parent 5d06f6b858
commit 479bfdead8
No known key found for this signature in database
GPG Key ID: B8904D9D9C93D1F2
5 changed files with 34 additions and 39 deletions

View File

@ -468,23 +468,13 @@ func (b *BlockChain) addOrphanBlock(block *dcrutil.Block) {
b.prevOrphans[*prevHash] = append(b.prevOrphans[*prevHash], oBlock)
}
// getGeneration gets a generation of blocks who all have the same parent by
// taking a hash as input, locating its parent node, and then returning all
// children for that parent node including the hash passed. This can then be
// used by the mempool downstream to locate all potential block template
// parents.
func (b *BlockChain) getGeneration(h chainhash.Hash) ([]chainhash.Hash, error) {
// This typically happens because the main chain has recently
// reorganized and the block the miner is looking at is on
// a fork. Usually it corrects itself after failure.
node, err := b.findNode(&h, maxSearchDepth)
if err != nil {
return nil, fmt.Errorf("couldn't find block node in best chain: %v",
err.Error())
}
// Get the parent of this node.
p, err := b.index.PrevNodeFromNode(node)
// tipGeneration returns the entire generation of blocks stemming from the
// parent of the current tip.
//
// This function MUST be called with the chain lock held (for reads).
func (b *BlockChain) tipGeneration() ([]chainhash.Hash, error) {
// Get the parent of this tip.
p, err := b.index.PrevNodeFromNode(b.bestNode)
if err != nil {
return nil, fmt.Errorf("block is orphan (parent missing)")
}
@ -502,9 +492,15 @@ func (b *BlockChain) getGeneration(h chainhash.Hash) ([]chainhash.Hash, error) {
return allChildren, nil
}
// GetGeneration is the exported version of getGeneration.
func (b *BlockChain) GetGeneration(hash chainhash.Hash) ([]chainhash.Hash, error) {
return b.getGeneration(hash)
// TipGeneration returns the entire generation of blocks stemming from the
// parent of the current tip.
//
// The function is safe for concurrent access.
func (b *BlockChain) TipGeneration() ([]chainhash.Hash, error) {
b.chainLock.Lock()
children, err := b.tipGeneration()
b.chainLock.Unlock()
return children, err
}
// findNode finds the node scaling backwards from best chain or return an

View File

@ -163,19 +163,18 @@ type calcNextReqStakeDifficultyMsg struct {
reply chan calcNextReqStakeDifficultyResponse
}
// getGenerationResponse is a response sent to the reply channel of a
// getGenerationMsg query.
type getGenerationResponse struct {
// tipGenerationResponse is a response sent to the reply channel of a
// tipGenerationMsg query.
type tipGenerationResponse struct {
hashes []chainhash.Hash
err error
}
// getGenerationMsg is a message type to be sent across the message
// tipGenerationMsg is a message type to be sent across the message
// channel for requesting the required the entire generation of a
// block node.
type getGenerationMsg struct {
hash chainhash.Hash
reply chan getGenerationResponse
type tipGenerationMsg struct {
reply chan tipGenerationResponse
}
// forceReorganizationResponse is a response sent to the reply channel of a
@ -1761,9 +1760,9 @@ out:
err: err,
}
case getGenerationMsg:
g, err := b.chain.GetGeneration(msg.hash)
msg.reply <- getGenerationResponse{
case tipGenerationMsg:
g, err := b.chain.TipGeneration()
msg.reply <- tipGenerationResponse{
hashes: g,
err: err,
}
@ -2453,12 +2452,12 @@ func (b *blockManager) ForceReorganization(formerBest, newBest chainhash.Hash) e
return response.err
}
// GetGeneration returns the hashes of all the children of a parent for the
// block hash that is passed to the function. It is funneled through the block
// manager since blockchain is not safe for concurrent access.
func (b *blockManager) GetGeneration(h chainhash.Hash) ([]chainhash.Hash, error) {
reply := make(chan getGenerationResponse)
b.msgChan <- getGenerationMsg{hash: h, reply: reply}
// TipGeneration returns the hashes of all the children of the current best
// chain tip. It is funneled through the block manager since blockchain is not
// safe for concurrent access.
func (b *blockManager) TipGeneration() ([]chainhash.Hash, error) {
reply := make(chan tipGenerationResponse)
b.msgChan <- tipGenerationMsg{reply: reply}
response := <-reply
return response.hashes, response.err
}

View File

@ -1193,7 +1193,7 @@ func NewBlockTemplate(policy *mining.Policy, server *server,
if nextBlockHeight >= stakeValidationHeight {
// Obtain the entire generation of blocks stemming from this parent.
children, err := blockManager.GetGeneration(*prevHash)
children, err := blockManager.TipGeneration()
if err != nil {
return nil, miningRuleError(ErrFailedToGetGeneration, err.Error())
}

View File

@ -4380,7 +4380,7 @@ func handleRebroadcastMissed(s *rpcServer, cmd interface{}, closeChan <-chan str
// handleRebroadcastWinners implements the rebroadcastwinners command.
func handleRebroadcastWinners(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
hash, height := s.server.blockManager.chainState.Best()
blocks, err := s.server.blockManager.GetGeneration(*hash)
blocks, err := s.server.blockManager.TipGeneration()
if err != nil {
return nil, rpcInternalError("Could not get generation "+
err.Error(), "")

View File

@ -463,7 +463,7 @@ func (sp *serverPeer) OnGetMiningState(p *peer.Peer, msg *wire.MsgGetMiningState
// Obtain the entire generation of blocks stemming from the parent of
// the current tip.
children, err := bm.GetGeneration(*newest)
children, err := bm.TipGeneration()
if err != nil {
peerLog.Warnf("failed to access block manager to get the generation "+
"for a mining state request (block: %v): %v", newest, err)