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

View file

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/mempool"
"github.com/btcsuite/btcd/mining" "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 // See the NewBlockTemplate method for a detailed description of how the block
// template is generated. // template is generated.
type BlkTmplGenerator struct { type BlkTmplGenerator struct {
policy *mining.Policy policy *mining.Policy
txSource mining.TxSource chainParams *chaincfg.Params
sigCache *txscript.SigCache txSource mining.TxSource
blockManager *blockManager chain *blockchain.BlockChain
timeSource blockchain.MedianTimeSource timeSource blockchain.MedianTimeSource
sigCache *txscript.SigCache
} }
// newBlkTmplGenerator returns a new block template generator for the given // 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 // 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 // templates are built on top of the current best chain and adhere to the
// consensus rules. // consensus rules.
func newBlkTmplGenerator(policy *mining.Policy, txSource mining.TxSource, func newBlkTmplGenerator(policy *mining.Policy, params *chaincfg.Params,
timeSource blockchain.MedianTimeSource, sigCache *txscript.SigCache, txSource mining.TxSource, chain *blockchain.BlockChain,
blockManager *blockManager) *BlkTmplGenerator { timeSource blockchain.MedianTimeSource,
sigCache *txscript.SigCache) *BlkTmplGenerator {
return &BlkTmplGenerator{ return &BlkTmplGenerator{
policy: policy, policy: policy,
txSource: txSource, chainParams: params,
sigCache: sigCache, txSource: txSource,
blockManager: blockManager, chain: chain,
timeSource: timeSource, 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) { func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*BlockTemplate, error) {
// Locals for faster access. // Locals for faster access.
policy := g.policy policy := g.policy
blockManager := g.blockManager
timeSource := g.timeSource timeSource := g.timeSource
sigCache := g.sigCache sigCache := g.sigCache
// Extend the most recently known best block. // Extend the most recently known best block.
best := blockManager.chain.BestSnapshot() best := g.chain.BestSnapshot()
prevHash := best.Hash prevHash := best.Hash
nextBlockHeight := best.Height + 1 nextBlockHeight := best.Height + 1
@ -490,7 +493,7 @@ mempoolLoop:
// mempool since a transaction which depends on other // mempool since a transaction which depends on other
// transactions in the mempool must come after those // transactions in the mempool must come after those
// dependencies in the final generated block. // dependencies in the final generated block.
utxos, err := blockManager.chain.FetchUtxoView(tx) utxos, err := g.chain.FetchUtxoView(tx)
if err != nil { if err != nil {
minrLog.Warnf("Unable to fetch utxo view for tx %s: "+ minrLog.Warnf("Unable to fetch utxo view for tx %s: "+
"%v", tx.Hash(), err) "%v", tx.Hash(), err)
@ -723,7 +726,7 @@ mempoolLoop:
// is potentially adjusted to ensure it comes after the median time of // is potentially adjusted to ensure it comes after the median time of
// the last several blocks per the chain consensus rules. // the last several blocks per the chain consensus rules.
ts := medianAdjustedTime(best, timeSource) ts := medianAdjustedTime(best, timeSource)
reqDifficulty, err := blockManager.chain.CalcNextRequiredDifficulty(ts) reqDifficulty, err := g.chain.CalcNextRequiredDifficulty(ts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -749,7 +752,7 @@ mempoolLoop:
// chain with no issues. // chain with no issues.
block := btcutil.NewBlock(&msgBlock) block := btcutil.NewBlock(&msgBlock)
block.SetHeight(nextBlockHeight) block.SetHeight(nextBlockHeight)
if err := blockManager.chain.CheckConnectBlock(block); err != nil { if err := g.chain.CheckConnectBlock(block); err != nil {
return nil, err 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 new timestamp is potentially adjusted to ensure it comes after
// the median time of the last several blocks per the chain consensus // the median time of the last several blocks per the chain consensus
// rules. // rules.
best := g.blockManager.chain.BestSnapshot() newTime := medianAdjustedTime(g.chain.BestSnapshot(), g.timeSource)
newTimestamp := medianAdjustedTime(best, g.timeSource) msgBlock.Header.Timestamp = newTime
msgBlock.Header.Timestamp = newTimestamp
// If running on a network that requires recalculating the difficulty, // If running on a network that requires recalculating the difficulty,
// do so now. // do so now.
if activeNetParams.ReduceMinDifficulty { if activeNetParams.ReduceMinDifficulty {
chain := g.blockManager.chain difficulty, err := g.chain.CalcNextRequiredDifficulty(newTime)
difficulty, err := chain.CalcNextRequiredDifficulty(newTimestamp)
if err != nil { if err != nil {
return err return err
} }
@ -822,3 +823,20 @@ func (g *BlkTmplGenerator) UpdateExtraNonce(msgBlock *wire.MsgBlock, blockHeight
msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1] msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]
return nil 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, BlockPrioritySize: cfg.BlockPrioritySize,
TxMinFreeFee: cfg.minRelayTxFee, TxMinFreeFee: cfg.minRelayTxFee,
} }
blockTemplateGenerator := newBlkTmplGenerator(&policy, s.txMemPool, blockTemplateGenerator := newBlkTmplGenerator(&policy, s.chainParams,
s.timeSource, s.sigCache, bm) s.txMemPool, s.blockManager.chain, s.timeSource, s.sigCache)
s.cpuMiner = newCPUMiner(&cpuminerConfig{ s.cpuMiner = newCPUMiner(&cpuminerConfig{
ChainParams: chainParams, ChainParams: chainParams,
BlockTemplateGenerator: blockTemplateGenerator, BlockTemplateGenerator: blockTemplateGenerator,