mining: Break dependency on block manager instance.

This modifies the block template generate for the mining code such that
it takes chain instance and params instead of requiring a fully
initialized blockManager instance.

Also, in preparation for being able to more easily separate the code, it
exposes and makes use of two new functions:
- BestSnapshot which returns the state snapshot from the underlying
  chain instance
- TxSource which returns the underlying transaction source

This is a step towards being able to separate the mining code into its
own package.  No functional change.
This commit is contained in:
Dave Collins 2016-10-27 10:58:01 -05:00
parent 671901486c
commit 660467259e
No known key found for this signature in database
GPG key ID: B8904D9D9C93D1F2
3 changed files with 51 additions and 33 deletions

View file

@ -160,7 +160,7 @@ func (m *CPUMiner) submitBlock(block *btcutil.Block) bool {
// detected and all work on the stale block is halted to start work on
// a new block, but the check only happens periodically, so it is
// possible a block was found and submitted in between.
latestHash := m.g.blockManager.chain.BestSnapshot().Hash
latestHash := m.g.BestSnapshot().Hash
msgBlock := block.MsgBlock()
if !msgBlock.Header.PrevBlock.IsEqual(latestHash) {
minrLog.Debugf("Block submitted via CPU miner with previous "+
@ -170,7 +170,7 @@ func (m *CPUMiner) submitBlock(block *btcutil.Block) bool {
// Process this block using the same rules as blocks coming from other
// nodes. This will in turn relay it to the network like normal.
isOrphan, err := m.g.blockManager.ProcessBlock(block, blockchain.BFNone)
isOrphan, err := m.cfg.ProcessBlock(block, blockchain.BFNone)
if err != nil {
// Anything other than a rule violation is an unexpected error,
// so log that error as an internal error.
@ -222,7 +222,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32,
// Initial state.
lastGenerated := time.Now()
lastTxUpdate := m.g.txSource.LastUpdated()
lastTxUpdate := m.g.TxSource().LastUpdated()
hashesCompleted := uint64(0)
// Note that the entire extra nonce range is iterated and the offset is
@ -248,7 +248,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32,
// The current block is stale if the best block
// has changed.
best := m.g.blockManager.chain.BestSnapshot()
best := m.g.BestSnapshot()
if !header.PrevBlock.IsEqual(best.Hash) {
return false
}
@ -257,7 +257,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32,
// has been updated since the block template was
// generated and it has been at least one
// minute.
if lastTxUpdate != m.g.txSource.LastUpdated() &&
if lastTxUpdate != m.g.TxSource().LastUpdated() &&
time.Now().After(lastGenerated.Add(time.Minute)) {
return false
@ -327,8 +327,8 @@ out:
// this would otherwise end up building a new block template on
// a block that is in the process of becoming stale.
m.submitBlockLock.Lock()
curHeight := m.g.blockManager.chain.BestSnapshot().Height
if curHeight != 0 && !m.g.blockManager.IsCurrent() {
curHeight := m.g.BestSnapshot().Height
if curHeight != 0 && !m.cfg.IsCurrent() {
m.submitBlockLock.Unlock()
time.Sleep(time.Second)
continue
@ -594,7 +594,7 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) {
// be changing and this would otherwise end up building a new block
// template on a block that is in the process of becoming stale.
m.submitBlockLock.Lock()
curHeight := m.g.blockManager.chain.BestSnapshot().Height
curHeight := m.g.BestSnapshot().Height
// Choose a payment address at random.
rand.Seed(time.Now().UnixNano())

View file

@ -10,6 +10,7 @@ import (
"time"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/mempool"
"github.com/btcsuite/btcd/mining"
@ -311,11 +312,12 @@ func medianAdjustedTime(chainState *blockchain.BestState, timeSource blockchain.
// See the NewBlockTemplate method for a detailed description of how the block
// template is generated.
type BlkTmplGenerator struct {
policy *mining.Policy
txSource mining.TxSource
sigCache *txscript.SigCache
blockManager *blockManager
timeSource blockchain.MedianTimeSource
policy *mining.Policy
chainParams *chaincfg.Params
txSource mining.TxSource
chain *blockchain.BlockChain
timeSource blockchain.MedianTimeSource
sigCache *txscript.SigCache
}
// newBlkTmplGenerator returns a new block template generator for the given
@ -324,16 +326,18 @@ type BlkTmplGenerator struct {
// The additional state-related fields are required in order to ensure the
// templates are built on top of the current best chain and adhere to the
// consensus rules.
func newBlkTmplGenerator(policy *mining.Policy, txSource mining.TxSource,
timeSource blockchain.MedianTimeSource, sigCache *txscript.SigCache,
blockManager *blockManager) *BlkTmplGenerator {
func newBlkTmplGenerator(policy *mining.Policy, params *chaincfg.Params,
txSource mining.TxSource, chain *blockchain.BlockChain,
timeSource blockchain.MedianTimeSource,
sigCache *txscript.SigCache) *BlkTmplGenerator {
return &BlkTmplGenerator{
policy: policy,
txSource: txSource,
sigCache: sigCache,
blockManager: blockManager,
timeSource: timeSource,
policy: policy,
chainParams: params,
txSource: txSource,
chain: chain,
timeSource: timeSource,
sigCache: sigCache,
}
}
@ -402,12 +406,11 @@ func newBlkTmplGenerator(policy *mining.Policy, txSource mining.TxSource,
func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*BlockTemplate, error) {
// Locals for faster access.
policy := g.policy
blockManager := g.blockManager
timeSource := g.timeSource
sigCache := g.sigCache
// Extend the most recently known best block.
best := blockManager.chain.BestSnapshot()
best := g.chain.BestSnapshot()
prevHash := best.Hash
nextBlockHeight := best.Height + 1
@ -490,7 +493,7 @@ mempoolLoop:
// mempool since a transaction which depends on other
// transactions in the mempool must come after those
// dependencies in the final generated block.
utxos, err := blockManager.chain.FetchUtxoView(tx)
utxos, err := g.chain.FetchUtxoView(tx)
if err != nil {
minrLog.Warnf("Unable to fetch utxo view for tx %s: "+
"%v", tx.Hash(), err)
@ -723,7 +726,7 @@ mempoolLoop:
// is potentially adjusted to ensure it comes after the median time of
// the last several blocks per the chain consensus rules.
ts := medianAdjustedTime(best, timeSource)
reqDifficulty, err := blockManager.chain.CalcNextRequiredDifficulty(ts)
reqDifficulty, err := g.chain.CalcNextRequiredDifficulty(ts)
if err != nil {
return nil, err
}
@ -749,7 +752,7 @@ mempoolLoop:
// chain with no issues.
block := btcutil.NewBlock(&msgBlock)
block.SetHeight(nextBlockHeight)
if err := blockManager.chain.CheckConnectBlock(block); err != nil {
if err := g.chain.CheckConnectBlock(block); err != nil {
return nil, err
}
@ -777,15 +780,13 @@ func (g *BlkTmplGenerator) UpdateBlockTime(msgBlock *wire.MsgBlock) error {
// The new timestamp is potentially adjusted to ensure it comes after
// the median time of the last several blocks per the chain consensus
// rules.
best := g.blockManager.chain.BestSnapshot()
newTimestamp := medianAdjustedTime(best, g.timeSource)
msgBlock.Header.Timestamp = newTimestamp
newTime := medianAdjustedTime(g.chain.BestSnapshot(), g.timeSource)
msgBlock.Header.Timestamp = newTime
// If running on a network that requires recalculating the difficulty,
// do so now.
if activeNetParams.ReduceMinDifficulty {
chain := g.blockManager.chain
difficulty, err := chain.CalcNextRequiredDifficulty(newTimestamp)
difficulty, err := g.chain.CalcNextRequiredDifficulty(newTime)
if err != nil {
return err
}
@ -822,3 +823,20 @@ func (g *BlkTmplGenerator) UpdateExtraNonce(msgBlock *wire.MsgBlock, blockHeight
msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]
return nil
}
// BestSnapshot returns information about the current best chain block and
// related state as of the current point in time using the chain instance
// associated with the block template generator. The returned state must be
// treated as immutable since it is shared by all callers.
//
// This function is safe for concurrent access.
func (g *BlkTmplGenerator) BestSnapshot() *blockchain.BestState {
return g.chain.BestSnapshot()
}
// TxSource returns the associated transaction source.
//
// This function is safe for concurrent access.
func (g *BlkTmplGenerator) TxSource() mining.TxSource {
return g.txSource
}

View file

@ -2380,8 +2380,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
BlockPrioritySize: cfg.BlockPrioritySize,
TxMinFreeFee: cfg.minRelayTxFee,
}
blockTemplateGenerator := newBlkTmplGenerator(&policy, s.txMemPool,
s.timeSource, s.sigCache, bm)
blockTemplateGenerator := newBlkTmplGenerator(&policy, s.chainParams,
s.txMemPool, s.blockManager.chain, s.timeSource, s.sigCache)
s.cpuMiner = newCPUMiner(&cpuminerConfig{
ChainParams: chainParams,
BlockTemplateGenerator: blockTemplateGenerator,