multi: decouple BlockManager from server.

This adds a blockManager config and removes direct references
to the server from the blockManager.
This commit is contained in:
Donald Adu-Poku 2019-06-25 19:05:47 +00:00
parent 6a3c1fea49
commit 6968dcfdbd
5 changed files with 226 additions and 173 deletions

View File

@ -22,6 +22,7 @@ import (
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/dcrd/database"
"github.com/decred/dcrd/dcrutil"
"github.com/decred/dcrd/fees"
"github.com/decred/dcrd/mempool/v2"
"github.com/decred/dcrd/wire"
)
@ -292,10 +293,51 @@ type headerNode struct {
hash *chainhash.Hash
}
// PeerNotifier provides an interface for server peer notifications.
type PeerNotifier interface {
// AnnounceNewTransactions generates and relays inventory vectors and
// notifies both websocket and getblocktemplate long poll clients of
// the passed transactions.
AnnounceNewTransactions(txns []*dcrutil.Tx)
// UpdatePeerHeights updates the heights of all peers who have have
// announced the latest connected main chain block, or a recognized orphan.
UpdatePeerHeights(latestBlkHash *chainhash.Hash, latestHeight int64, updateSource *serverPeer)
// RelayInventory relays the passed inventory vector to all connected peers
// that are not already known to have it.
RelayInventory(invVect *wire.InvVect, data interface{}, immediate bool)
// TransactionConfirmed marks the provided single confirmation transaction
// as no longer needing rebroadcasting.
TransactionConfirmed(tx *dcrutil.Tx)
}
// blockManangerConfig is a configuration struct for a blockManager.
type blockManagerConfig struct {
PeerNotifier PeerNotifier
TimeSource blockchain.MedianTimeSource
// The following fields are for accessing the chain and its configuration.
Chain *blockchain.BlockChain
ChainParams *chaincfg.Params
// The following fields provide access to the fee estimator, mempool and
// the background block template generator.
FeeEstimator *fees.Estimator
TxMemPool *mempool.TxPool
BgBlkTmplGenerator *BgBlkTmplGenerator
// The following fields are blockManger callbacks.
NotifyWinningTickets func(*WinningTicketsNtfnData)
PruneRebroadcastInventory func()
RpcServer func() *rpcServer
}
// blockManager provides a concurrency safe block manager for handling all
// incoming blocks.
type blockManager struct {
server *server
cfg *blockManagerConfig
started int32
shutdown int32
chain *blockchain.BlockChain
@ -368,7 +410,7 @@ func (b *blockManager) findNextHeaderCheckpoint(height int64) *chaincfg.Checkpoi
if cfg.DisableCheckpoints {
return nil
}
checkpoints := b.server.chainParams.Checkpoints
checkpoints := b.chain.Checkpoints()
if len(checkpoints) == 0 {
return nil
}
@ -613,7 +655,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) {
// Process the transaction to include validation, insertion in the
// memory pool, orphan handling, etc.
allowOrphans := cfg.MaxOrphanTxs > 0
acceptedTxs, err := b.server.txMemPool.ProcessTransaction(tmsg.tx,
acceptedTxs, err := b.cfg.TxMemPool.ProcessTransaction(tmsg.tx,
allowOrphans, true, true)
// Remove transaction from request maps. Either the mempool/chain
@ -649,7 +691,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) {
return
}
b.server.AnnounceNewTransactions(acceptedTxs)
b.cfg.PeerNotifier.AnnounceNewTransactions(acceptedTxs)
}
// current returns true if we believe we are synced with our peers, false if we
@ -732,7 +774,7 @@ func (b *blockManager) checkBlockForHiddenVotes(block *dcrutil.Block) {
var oldTickets []*dcrutil.Tx
var oldRevocations []*dcrutil.Tx
oldVoteMap := make(map[chainhash.Hash]struct{},
int(b.server.chainParams.TicketsPerBlock))
int(b.cfg.ChainParams.TicketsPerBlock))
templateBlock := dcrutil.NewBlock(template.Block)
// Add all the votes found in our template. Keep their
@ -768,12 +810,11 @@ func (b *blockManager) checkBlockForHiddenVotes(block *dcrutil.Block) {
// Check the length of the reconstructed voter list for
// integrity.
votesTotal := len(newVotes)
if votesTotal > int(b.server.chainParams.TicketsPerBlock) {
if votesTotal > int(b.cfg.ChainParams.TicketsPerBlock) {
bmgrLog.Warnf("error found while adding hidden votes "+
"from block %v to the old block template: %v max "+
"votes expected but %v votes found", block.Hash(),
int(b.server.chainParams.TicketsPerBlock),
votesTotal)
int(b.cfg.ChainParams.TicketsPerBlock), votesTotal)
return
}
@ -816,11 +857,9 @@ func (b *blockManager) checkBlockForHiddenVotes(block *dcrutil.Block) {
}
coinbase, err := createCoinbaseTx(b.chain.FetchSubsidyCache(),
template.Block.Transactions[0].TxIn[0].SignatureScript,
opReturnPkScript,
int64(template.Block.Header.Height),
opReturnPkScript, int64(template.Block.Header.Height),
cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))],
uint16(votesTotal),
b.server.chainParams)
uint16(votesTotal), b.cfg.ChainParams)
if err != nil {
bmgrLog.Errorf("failed to create coinbase while generating " +
"block with extra found voters")
@ -966,7 +1005,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
// votes in it that were hidden from the network and which
// validate our parent block. We should bolt these new votes
// into the tx tree stake of the old block template on parent.
svl := b.server.chainParams.StakeValidationHeight
svl := b.cfg.ChainParams.StakeValidationHeight
if b.AggressiveMining && bmsg.block.Height() >= svl {
b.checkBlockForHiddenVotes(bmsg.block)
}
@ -974,7 +1013,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
// Notify stake difficulty subscribers and prune invalidated
// transactions.
best := b.chain.BestSnapshot()
r := b.server.rpcServer
r := b.cfg.RpcServer()
if r != nil {
// Update registered websocket clients on the
// current stake difficulty.
@ -985,9 +1024,8 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
best.NextStakeDiff,
})
}
b.server.txMemPool.PruneStakeTx(best.NextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
b.cfg.TxMemPool.PruneStakeTx(best.NextStakeDiff, best.Height)
b.cfg.TxMemPool.PruneExpiredTx()
// Update this peer's latest block height, for future
// potential sync node candidancy.
@ -1000,9 +1038,8 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
// Allow any clients performing long polling via the
// getblocktemplate RPC to be notified when the new block causes
// their old block template to become stale.
rpcServer := b.server.rpcServer
if rpcServer != nil {
rpcServer.gbtWorkState.NotifyBlockConnected(blockHash)
if r := b.cfg.RpcServer(); r != nil {
r.gbtWorkState.NotifyBlockConnected(blockHash)
}
}
}
@ -1014,7 +1051,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
if blkHashUpdate != nil && heightUpdate != 0 {
bmsg.peer.UpdateLastBlockHeight(heightUpdate)
if isOrphan || b.current() {
go b.server.UpdatePeerHeights(blkHashUpdate, heightUpdate,
go b.cfg.PeerNotifier.UpdatePeerHeights(blkHashUpdate, heightUpdate,
bmsg.peer)
}
}
@ -1235,7 +1272,7 @@ func (b *blockManager) haveInventory(invVect *wire.InvVect) (bool, error) {
case wire.InvTypeTx:
// Ask the transaction memory pool if the transaction is known
// to it in any form (main pool or orphan).
if b.server.txMemPool.HaveTransaction(&invVect.Hash) {
if b.cfg.TxMemPool.HaveTransaction(&invVect.Hash) {
return true, nil
}
@ -1290,7 +1327,6 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) {
if lastBlock != -1 && isCurrent {
blkHeight, err := b.chain.BlockHeightByHash(&invVects[lastBlock].Hash)
if err == nil {
imsg.peer.UpdateLastBlockHeight(blkHeight)
}
}
@ -1515,7 +1551,7 @@ out:
// Notify stake difficulty subscribers and prune
// invalidated transactions.
best := b.chain.BestSnapshot()
r := b.server.rpcServer
r := b.cfg.RpcServer()
if r != nil {
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
@ -1524,9 +1560,9 @@ out:
best.NextStakeDiff,
})
}
b.server.txMemPool.PruneStakeTx(best.NextStakeDiff,
b.cfg.TxMemPool.PruneStakeTx(best.NextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
b.cfg.TxMemPool.PruneExpiredTx()
}
msg.reply <- forceReorganizationResponse{
@ -1552,12 +1588,12 @@ out:
continue
}
r := b.cfg.RpcServer()
onMainChain := !isOrphan && forkLen == 0
if onMainChain {
// Notify stake difficulty subscribers and prune
// invalidated transactions.
best := b.chain.BestSnapshot()
r := b.server.rpcServer
if r != nil {
r.ntfnMgr.NotifyStakeDifficulty(
&StakeDifficultyNtfnData{
@ -1566,17 +1602,16 @@ out:
best.NextStakeDiff,
})
}
b.server.txMemPool.PruneStakeTx(best.NextStakeDiff,
b.cfg.TxMemPool.PruneStakeTx(best.NextStakeDiff,
best.Height)
b.server.txMemPool.PruneExpiredTx()
b.cfg.TxMemPool.PruneExpiredTx()
}
// Allow any clients performing long polling via the
// getblocktemplate RPC to be notified when the new block causes
// their old block template to become stale.
rpcServer := b.server.rpcServer
if rpcServer != nil {
rpcServer.gbtWorkState.NotifyBlockConnected(msg.block.Hash())
if r != nil {
r.gbtWorkState.NotifyBlockConnected(msg.block.Hash())
}
msg.reply <- processBlockResponse{
@ -1585,7 +1620,7 @@ out:
}
case processTransactionMsg:
acceptedTxs, err := b.server.txMemPool.ProcessTransaction(msg.tx,
acceptedTxs, err := b.cfg.TxMemPool.ProcessTransaction(msg.tx,
msg.allowOrphans, msg.rateLimit, msg.allowHighFees)
msg.reply <- processTransactionResponse{
acceptedTxs: acceptedTxs,
@ -1616,8 +1651,7 @@ out:
msg.reply <- setParentTemplateResponse{}
default:
bmgrLog.Warnf("Invalid message type in block "+
"handler: %T", msg)
bmgrLog.Warnf("Invalid message type in block handler: %T", msg)
}
case <-b.quit:
@ -1667,9 +1701,10 @@ func isDoubleSpendOrDuplicateError(err error) bool {
return false
}
// handleNotifyMsg handles notifications from blockchain. It does things such
// as request orphan block parents and relay accepted blocks to connected peers.
func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// handleBlockchainNotification handles notifications from blockchain. It does
// things such as request orphan block parents and relay accepted blocks to
// connected peers.
func (b *blockManager) handleBlockchainNotification(notification *blockchain.Notification) {
switch notification.Type {
// A block that intends to extend the main chain has passed all sanity and
// contextual checks and the chain is believed to be current. Relay it to
@ -1686,7 +1721,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// Generate the inventory vector and relay it immediately.
iv := wire.NewInvVect(wire.InvTypeBlock, block.Hash())
b.server.RelayInventory(iv, block.MsgBlock().Header, true)
b.cfg.PeerNotifier.RelayInventory(iv, block.MsgBlock().Header, true)
b.announcedBlockMtx.Lock()
b.announcedBlock = block.Hash()
b.announcedBlockMtx.Unlock()
@ -1738,10 +1773,10 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
bestHeight := band.BestHeight
blockHeight := int64(block.MsgBlock().Header.Height)
reorgDepth := bestHeight - (blockHeight - band.ForkLen)
if b.server.rpcServer != nil &&
blockHeight >= b.server.chainParams.StakeValidationHeight-1 &&
if b.cfg.RpcServer() != nil &&
blockHeight >= b.cfg.ChainParams.StakeValidationHeight-1 &&
reorgDepth < maxReorgDepthNotify &&
blockHeight > b.server.chainParams.LatestCheckpointHeight() &&
blockHeight > b.cfg.ChainParams.LatestCheckpointHeight() &&
!b.notifiedWinningTickets(blockHash) {
// Obtain the winning tickets for this block. handleNotifyMsg
@ -1752,15 +1787,14 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
bmgrLog.Errorf("Couldn't calculate winning tickets for "+
"accepted block %v: %v", blockHash, err.Error())
} else {
ntfnData := &WinningTicketsNtfnData{
// Notify registered websocket clients of newly
// eligible tickets to vote on.
b.cfg.NotifyWinningTickets(&WinningTicketsNtfnData{
BlockHash: *blockHash,
BlockHeight: blockHeight,
Tickets: wt,
}
})
// Notify registered websocket clients of newly
// eligible tickets to vote on.
b.server.rpcServer.ntfnMgr.NotifyWinningTickets(ntfnData)
b.lotteryDataBroadcastMutex.Lock()
b.lotteryDataBroadcast[*blockHash] = struct{}{}
b.lotteryDataBroadcastMutex.Unlock()
@ -1775,32 +1809,32 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
b.announcedBlockMtx.Unlock()
if !sent {
iv := wire.NewInvVect(wire.InvTypeBlock, blockHash)
b.server.RelayInventory(iv, block.MsgBlock().Header, true)
b.cfg.PeerNotifier.RelayInventory(iv, block.MsgBlock().Header, true)
}
// Inform the background block template generator about the accepted
// block.
if b.server.bg != nil {
b.server.bg.BlockAccepted(block)
if b.cfg.BgBlkTmplGenerator != nil {
b.cfg.BgBlkTmplGenerator.BlockAccepted(block)
}
if !b.server.feeEstimator.IsEnabled() {
if !b.cfg.FeeEstimator.IsEnabled() {
// fee estimation can only start after we have performed an initial
// sync, otherwise we'll start adding mempool transactions at the
// wrong height.
b.server.feeEstimator.Enable(block.Height())
b.cfg.FeeEstimator.Enable(block.Height())
}
// A block has been connected to the main block chain.
case blockchain.NTBlockConnected:
blockSlice, ok := notification.Data.([]*dcrutil.Block)
if !ok {
bmgrLog.Warnf("Chain connected notification is not a block slice.")
bmgrLog.Warnf("Block connected notification is not a block slice.")
break
}
if len(blockSlice) != 2 {
bmgrLog.Warnf("Chain connected notification is wrong size slice.")
bmgrLog.Warnf("Block connected notification is wrong size slice.")
break
}
@ -1811,7 +1845,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// estimation. This must be done before attempting to remove
// transactions from the mempool because the mempool will alert the
// estimator of the txs that are leaving
b.server.feeEstimator.ProcessBlock(block)
b.cfg.FeeEstimator.ProcessBlock(block)
// TODO: In the case the new tip disapproves the previous block, any
// transactions the previous block contains in its regular tree which
@ -1837,22 +1871,19 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
//
// Also, in the case the RPC server is enabled, stop rebroadcasting any
// transactions in the block that were setup to be rebroadcast.
txMemPool := b.server.txMemPool
txMemPool := b.cfg.TxMemPool
handleConnectedBlockTxns := func(txns []*dcrutil.Tx) {
for _, tx := range txns {
txMemPool.RemoveTransaction(tx, false)
txMemPool.RemoveDoubleSpends(tx)
txMemPool.RemoveOrphan(tx)
acceptedTxs := txMemPool.ProcessOrphans(tx)
b.server.AnnounceNewTransactions(acceptedTxs)
b.cfg.PeerNotifier.AnnounceNewTransactions(acceptedTxs)
// Now that this block is in the blockchain, mark the
// transaction (except the coinbase) as no longer needing
// rebroadcasting.
if b.server.rpcServer != nil {
iv := wire.NewInvVect(wire.InvTypeTx, tx.Hash())
b.server.RemoveRebroadcastInventory(iv)
}
b.cfg.PeerNotifier.TransactionConfirmed(tx)
}
}
handleConnectedBlockTxns(block.Transactions()[1:])
@ -1887,16 +1918,16 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
}
}
if r := b.server.rpcServer; r != nil {
if r := b.cfg.RpcServer(); r != nil {
// Filter and update the rebroadcast inventory.
b.server.PruneRebroadcastInventory()
b.cfg.PruneRebroadcastInventory()
// Notify registered websocket clients of incoming block.
r.ntfnMgr.NotifyBlockConnected(block)
}
if b.server.bg != nil {
b.server.bg.BlockConnected(block)
if b.cfg.BgBlkTmplGenerator != nil {
b.cfg.BgBlkTmplGenerator.BlockConnected(block)
}
// Stake tickets are spent or missed from the most recently connected block.
@ -1908,7 +1939,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
break
}
if r := b.server.rpcServer; r != nil {
if r := b.cfg.RpcServer(); r != nil {
r.ntfnMgr.NotifySpentAndMissedTickets(tnd)
}
@ -1921,7 +1952,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
break
}
if r := b.server.rpcServer; r != nil {
if r := b.cfg.RpcServer(); r != nil {
r.ntfnMgr.NotifyNewTickets(tnd)
}
@ -1929,12 +1960,12 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
case blockchain.NTBlockDisconnected:
blockSlice, ok := notification.Data.([]*dcrutil.Block)
if !ok {
bmgrLog.Warnf("Chain disconnected notification is not a block slice.")
bmgrLog.Warnf("Block disconnected notification is not a block slice.")
break
}
if len(blockSlice) != 2 {
bmgrLog.Warnf("Chain disconnected notification is wrong size slice.")
bmgrLog.Warnf("Block disconnected notification is wrong size slice.")
break
}
@ -1947,7 +1978,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// transactions and any that are now double spends from the transaction
// pool. Transactions which depend on a confirmed transaction are NOT
// removed recursively because they are still valid.
txMemPool := b.server.txMemPool
txMemPool := b.cfg.TxMemPool
if !headerApprovesParent(&block.MsgBlock().Header) {
for _, tx := range parentBlock.Transactions()[1:] {
txMemPool.RemoveTransaction(tx, false)
@ -1990,17 +2021,14 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
handleDisconnectedBlockTxns(block.Transactions()[1:])
handleDisconnectedBlockTxns(block.STransactions())
if b.server.bg != nil {
b.server.bg.BlockDisconnected(block)
if b.cfg.BgBlkTmplGenerator != nil {
b.cfg.BgBlkTmplGenerator.BlockDisconnected(block)
}
// Filter and update the rebroadcast inventory.
b.server.PruneRebroadcastInventory()
// Notify registered websocket clients.
if r := b.server.rpcServer; r != nil {
if r := b.cfg.RpcServer(); r != nil {
// Filter and update the rebroadcast inventory.
b.server.PruneRebroadcastInventory()
b.cfg.PruneRebroadcastInventory()
// Notify registered websocket clients.
r.ntfnMgr.NotifyBlockDisconnected(block)
@ -2008,14 +2036,14 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// Chain reorganization has commenced.
case blockchain.NTChainReorgStarted:
if b.server.bg != nil {
b.server.bg.ChainReorgStarted()
if b.cfg.BgBlkTmplGenerator != nil {
b.cfg.BgBlkTmplGenerator.ChainReorgStarted()
}
// Chain reorganization has concluded.
case blockchain.NTChainReorgDone:
if b.server.bg != nil {
b.server.bg.ChainReorgDone()
if b.cfg.BgBlkTmplGenerator != nil {
b.cfg.BgBlkTmplGenerator.ChainReorgDone()
}
// The blockchain is reorganizing.
@ -2027,7 +2055,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
}
// Notify registered websocket clients.
if r := b.server.rpcServer; r != nil {
if r := b.cfg.RpcServer(); r != nil {
r.ntfnMgr.NotifyReorganization(rd)
}
@ -2194,7 +2222,7 @@ func (b *blockManager) requestFromPeer(p *serverPeer, blocks, txs []*chainhash.H
// Ask the transaction memory pool if the transaction is known
// to it in any form (main pool or orphan).
if b.server.txMemPool.HaveTransaction(vh) {
if b.cfg.TxMemPool.HaveTransaction(vh) {
continue
}
@ -2357,9 +2385,10 @@ func (b *blockManager) SetParentTemplate(bt *BlockTemplate) {
// newBlockManager returns a new Decred block manager.
// Use Start to begin processing asynchronous block and inv updates.
func newBlockManager(s *server, indexManager blockchain.IndexManager, interrupt <-chan struct{}) (*blockManager, error) {
func newBlockManager(config *blockManagerConfig) (*blockManager, error) {
bm := blockManager{
server: s,
cfg: config,
chain: config.Chain,
rejectedTxns: make(map[chainhash.Hash]struct{}),
requestedTxns: make(map[chainhash.Hash]struct{}),
requestedBlocks: make(map[chainhash.Hash]struct{}),
@ -2370,20 +2399,6 @@ func newBlockManager(s *server, indexManager blockchain.IndexManager, interrupt
quit: make(chan struct{}),
}
// Create a new block chain instance with the appropriate configuration.
var err error
bm.chain, err = blockchain.New(&blockchain.Config{
DB: s.db,
Interrupt: interrupt,
ChainParams: s.chainParams,
TimeSource: s.timeSource,
Notifications: bm.handleNotifyMsg,
SigCache: s.sigCache,
IndexManager: indexManager,
})
if err != nil {
return nil, err
}
best := bm.chain.BestSnapshot()
bm.chain.DisableCheckpoints(cfg.DisableCheckpoints)
if !cfg.DisableCheckpoints {
@ -2398,7 +2413,7 @@ func newBlockManager(s *server, indexManager blockchain.IndexManager, interrupt
// Dump the blockchain here if asked for it, and quit.
if cfg.DumpBlockchain != "" {
err = dumpBlockChain(bm.chain, best.Height)
err := dumpBlockChain(bm.chain, best.Height)
if err != nil {
return nil, err
}

View File

@ -776,8 +776,8 @@ func deepCopyBlockTemplate(blockTemplate *BlockTemplate) *BlockTemplate {
// miner.
// Safe for concurrent access.
func handleTooFewVoters(subsidyCache *blockchain.SubsidyCache, nextHeight int64, miningAddress dcrutil.Address, bm *blockManager) (*BlockTemplate, error) {
timeSource := bm.server.timeSource
stakeValidationHeight := bm.server.chainParams.StakeValidationHeight
timeSource := bm.cfg.TimeSource
stakeValidationHeight := bm.cfg.ChainParams.StakeValidationHeight
curTemplate := bm.GetCurrentTemplate()
// Check to see if we've fallen off the chain, for example if a
@ -807,7 +807,7 @@ func handleTooFewVoters(subsidyCache *blockchain.SubsidyCache, nextHeight int64,
// If we're on testnet, the time since this last block
// listed as the parent must be taken into consideration.
if bm.server.chainParams.ReduceMinDifficulty {
if bm.cfg.ChainParams.ReduceMinDifficulty {
parentHash := cptCopy.Block.Header.PrevBlock
requiredDifficulty, err :=
@ -876,13 +876,9 @@ func handleTooFewVoters(subsidyCache *blockchain.SubsidyCache, nextHeight int64,
if err != nil {
return nil, err
}
coinbaseTx, err := createCoinbaseTx(subsidyCache,
coinbaseScript,
opReturnPkScript,
topBlock.Height(),
miningAddress,
topBlock.MsgBlock().Header.Voters,
bm.server.chainParams)
coinbaseTx, err := createCoinbaseTx(subsidyCache, coinbaseScript,
opReturnPkScript, topBlock.Height(), miningAddress,
topBlock.MsgBlock().Header.Voters, bm.cfg.ChainParams)
if err != nil {
return nil, err
}
@ -901,7 +897,7 @@ func handleTooFewVoters(subsidyCache *blockchain.SubsidyCache, nextHeight int64,
// If we're on testnet, the time since this last block
// listed as the parent must be taken into consideration.
if bm.server.chainParams.ReduceMinDifficulty {
if bm.cfg.ChainParams.ReduceMinDifficulty {
parentHash := topBlock.MsgBlock().Header.PrevBlock
requiredDifficulty, err :=

View File

@ -1392,7 +1392,7 @@ func handleEstimateStakeDiff(s *rpcServer, cmd interface{}, closeChan <-chan str
c := cmd.(*dcrjson.EstimateStakeDiffCmd)
// Minimum possible stake difficulty.
chain := s.server.blockManager.chain
chain := s.server.chain
min, err := chain.EstimateNextStakeDifficulty(0, false)
if err != nil {
return nil, rpcInternalError(err.Error(), "Could not "+
@ -1409,7 +1409,7 @@ func handleEstimateStakeDiff(s *rpcServer, cmd interface{}, closeChan <-chan str
// The expected stake difficulty. Average the number of fresh stake
// since the last retarget to get the number of tickets per block,
// then use that to estimate the next stake difficulty.
bestHeight := s.server.blockManager.chain.BestSnapshot().Height
bestHeight := chain.BestSnapshot().Height
lastAdjustment := (bestHeight / activeNetParams.StakeDiffWindowSize) *
activeNetParams.StakeDiffWindowSize
nextAdjustment := ((bestHeight / activeNetParams.StakeDiffWindowSize) +
@ -1525,7 +1525,7 @@ func handleExistsMissedTickets(s *rpcServer, cmd interface{}, closeChan <-chan s
return nil, err
}
exists := s.server.blockManager.chain.CheckMissedTickets(hashes)
exists := s.server.chain.CheckMissedTickets(hashes)
if len(exists) != len(hashes) {
return nil, rpcInvalidError("Invalid missed ticket count "+
"got %v, want %v", len(exists), len(hashes))
@ -1551,7 +1551,7 @@ func handleExistsExpiredTickets(s *rpcServer, cmd interface{}, closeChan <-chan
return nil, err
}
exists := s.server.blockManager.chain.CheckExpiredTickets(hashes)
exists := s.server.chain.CheckExpiredTickets(hashes)
if len(exists) != len(hashes) {
return nil, rpcInvalidError("Invalid expired ticket count "+
"got %v, want %v", len(exists), len(hashes))
@ -1577,7 +1577,7 @@ func handleExistsLiveTicket(s *rpcServer, cmd interface{}, closeChan <-chan stru
return nil, rpcDecodeHexError(c.TxHash)
}
return s.server.blockManager.chain.CheckLiveTicket(*hash), nil
return s.server.chain.CheckLiveTicket(*hash), nil
}
// handleExistsLiveTickets implements the existslivetickets command.
@ -1589,7 +1589,7 @@ func handleExistsLiveTickets(s *rpcServer, cmd interface{}, closeChan <-chan str
return nil, err
}
exists := s.server.blockManager.chain.CheckLiveTickets(hashes)
exists := s.server.chain.CheckLiveTickets(hashes)
if len(exists) != len(hashes) {
return nil, rpcInvalidError("Invalid live ticket count got "+
"%v, want %v", len(exists), len(hashes))
@ -1809,7 +1809,7 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i
if err != nil {
return nil, rpcDecodeHexError(c.Hash)
}
blk, err := s.server.blockManager.chain.BlockByHash(hash)
blk, err := s.server.chain.BlockByHash(hash)
if err != nil {
return nil, &dcrjson.RPCError{
Code: dcrjson.ErrRPCBlockNotFound,
@ -2307,7 +2307,7 @@ func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bo
// generated.
var msgBlock *wire.MsgBlock
var targetDifficulty string
best := s.server.blockManager.chain.BestSnapshot()
best := s.server.chain.BestSnapshot()
latestHash := best.Hash
template := state.template
if template == nil || state.prevHash == nil ||
@ -2795,7 +2795,7 @@ func handleGetBlockTemplateRequest(s *rpcServer, request *dcrjson.TemplateReques
}
// No point in generating or accepting work before the chain is synced.
bestHeight := s.server.blockManager.chain.BestSnapshot().Height
bestHeight := s.server.chain.BestSnapshot().Height
if bestHeight != 0 && !s.server.blockManager.IsCurrent() {
return nil, &dcrjson.RPCError{
Code: dcrjson.ErrRPCClientInInitialDownload,
@ -2944,13 +2944,13 @@ func handleGetBlockTemplateProposal(s *rpcServer, request *dcrjson.TemplateReque
block := dcrutil.NewBlock(&msgBlock)
// Ensure the block is building from the expected previous block.
expectedPrevHash := &s.server.blockManager.chain.BestSnapshot().Hash
expectedPrevHash := &s.server.chain.BestSnapshot().Hash
prevHash := &block.MsgBlock().Header.PrevBlock
if *expectedPrevHash != *prevHash {
return "bad-prevblk", nil
}
err = s.server.blockManager.chain.CheckConnectBlockTemplate(block)
err = s.server.chain.CheckConnectBlockTemplate(block)
if err != nil {
if _, ok := err.(blockchain.RuleError); !ok {
errStr := fmt.Sprintf("Failed to process block "+
@ -3164,7 +3164,7 @@ func handleGetHeaders(s *rpcServer, cmd interface{}, closeChan <-chan struct{})
locators[i] = &blockLocators[i]
}
chain := s.server.blockManager.chain
chain := s.server.chain
headers := chain.LocateHeaders(locators, &hashStop)
// Return the serialized block headers as hex-encoded strings.
@ -4040,7 +4040,7 @@ func handleGetWorkRequest(s *rpcServer) (interface{}, error) {
// it has been at least one minute since the last template was
// generated.
lastTxUpdate := s.server.txMemPool.LastUpdated()
best := s.server.blockManager.chain.BestSnapshot()
best := s.server.chain.BestSnapshot()
msgBlock := state.msgBlock
// The current code pulls down a new template every second, however
@ -4338,7 +4338,7 @@ func handleGetWork(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (in
}
// No point in generating or accepting work before the chain is synced.
bestHeight := s.server.blockManager.chain.BestSnapshot().Height
bestHeight := s.server.chain.BestSnapshot().Height
if bestHeight != 0 && !s.server.blockManager.IsCurrent() {
return nil, &dcrjson.RPCError{
Code: dcrjson.ErrRPCClientInInitialDownload,
@ -4402,7 +4402,7 @@ func handleHelp(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (inter
// handleLiveTickets implements the livetickets command.
func handleLiveTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
lt, err := s.server.blockManager.chain.LiveTickets()
lt, err := s.server.chain.LiveTickets()
if err != nil {
return nil, rpcInternalError("Could not get live tickets "+
err.Error(), "")
@ -4418,7 +4418,7 @@ func handleLiveTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{})
// handleMissedTickets implements the missedtickets command.
func handleMissedTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
mt, err := s.server.blockManager.chain.MissedTickets()
mt, err := s.server.chain.MissedTickets()
if err != nil {
return nil, rpcInternalError("Could not get missed tickets "+
err.Error(), "")
@ -4447,8 +4447,8 @@ func handlePing(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (inter
// handleRebroadcastMissed implements the rebroadcastmissed command.
func handleRebroadcastMissed(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
best := s.server.blockManager.chain.BestSnapshot()
mt, err := s.server.blockManager.chain.MissedTickets()
best := s.server.chain.BestSnapshot()
mt, err := s.server.chain.MissedTickets()
if err != nil {
return nil, rpcInternalError("Could not get missed tickets "+
err.Error(), "")
@ -4476,7 +4476,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) {
bestHeight := s.server.blockManager.chain.BestSnapshot().Height
bestHeight := s.server.chain.BestSnapshot().Height
blocks, err := s.server.blockManager.TipGeneration()
if err != nil {
return nil, rpcInternalError("Could not get generation "+
@ -4485,7 +4485,7 @@ func handleRebroadcastWinners(s *rpcServer, cmd interface{}, closeChan <-chan st
for i := range blocks {
winningTickets, _, _, err :=
s.server.blockManager.chain.LotteryDataForBlock(&blocks[i])
s.server.chain.LotteryDataForBlock(&blocks[i])
if err != nil {
return nil, rpcInternalError("Lottery data for block "+
"failed: "+err.Error(), "")
@ -5051,7 +5051,7 @@ func handleSendRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan st
// JSON-RPC error is returned to the client with the
// deserialization error code (to match bitcoind behavior).
if rErr, ok := err.(mempool.RuleError); ok {
err = fmt.Errorf("Rejected transaction %v: %v", tx.Hash(),
err = fmt.Errorf("rejected transaction %v: %v", tx.Hash(),
err)
rpcsLog.Debugf("%v", err)
txRuleErr, ok := rErr.Err.(mempool.TxRuleError)
@ -5376,7 +5376,7 @@ func ticketFeeInfoForRange(s *rpcServer, start int64, end int64, txType stake.Tx
func handleTicketFeeInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*dcrjson.TicketFeeInfoCmd)
bestHeight := s.server.blockManager.chain.BestSnapshot().Height
bestHeight := s.server.chain.BestSnapshot().Height
// Memory pool first.
feeInfoMempool := feeInfoForMempool(s, stake.TxTypeSStx)
@ -5462,10 +5462,9 @@ func handleTicketsForAddress(s *rpcServer, cmd interface{}, closeChan <-chan str
return nil, rpcInvalidError("Invalid address: %v", err)
}
tickets, err := s.server.blockManager.chain.TicketsWithAddress(addr)
tickets, err := s.server.chain.TicketsWithAddress(addr)
if err != nil {
return nil, rpcInternalError(err.Error(),
"Could not obtain tickets")
return nil, rpcInternalError(err.Error(), "could not obtain tickets")
}
ticketStrings := make([]string, len(tickets))
@ -5487,15 +5486,14 @@ func handleTicketVWAP(s *rpcServer, cmd interface{}, closeChan <-chan struct{})
// The default VWAP is for the past WorkDiffWindows * WorkDiffWindowSize
// many blocks.
bestHeight := s.server.blockManager.chain.BestSnapshot().Height
bestHeight := s.server.chain.BestSnapshot().Height
var start uint32
if c.Start == nil {
toEval := activeNetParams.WorkDiffWindows *
activeNetParams.WorkDiffWindowSize
startI64 := bestHeight - toEval
// Use 1 as the first block if there aren't
// enough blocks.
// Use 1 as the first block if there aren't enough blocks.
if startI64 <= 0 {
start = 1
} else {
@ -5544,7 +5542,7 @@ func handleTicketVWAP(s *rpcServer, cmd interface{}, closeChan <-chan struct{})
func handleTxFeeInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*dcrjson.TxFeeInfoCmd)
bestHeight := s.server.blockManager.chain.BestSnapshot().Height
bestHeight := s.server.chain.BestSnapshot().Height
// Memory pool first.
feeInfoMempool := feeInfoForMempool(s, stake.TxTypeRegular)
@ -6432,7 +6430,7 @@ func newRPCServer(listenAddrs []string, generator *BlkTmplGenerator, s *server)
rpc := rpcServer{
server: s,
generator: generator,
chain: s.blockManager.chain,
chain: s.chain,
statusLines: make(map[int]string),
workState: newWorkState(),
templatePool: make(map[[merkleRootPairSize]byte]*workStateBlockInfo),

View File

@ -2190,7 +2190,7 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) {
// Iterate over each block in the request and rescan. When a block
// contains relevant transactions, add it to the response.
bc := wsc.server.server.blockManager.chain
bc := wsc.server.chain
var lastBlockHash *chainhash.Hash
for i := range blockHashes {
block, err := bc.BlockByHash(&blockHashes[i])

106
server.go
View File

@ -194,6 +194,7 @@ type server struct {
rpcServer *rpcServer
blockManager *blockManager
bg *BgBlkTmplGenerator
chain *blockchain.BlockChain
txMemPool *mempool.TxPool
feeEstimator *fees.Estimator
cpuMiner *CPUMiner
@ -271,7 +272,7 @@ func newServerPeer(s *server, isPersistent bool) *serverPeer {
// newestBlock returns the current best block hash and height using the format
// required by the configuration for the peer package.
func (sp *serverPeer) newestBlock() (*chainhash.Hash, int64, error) {
best := sp.server.blockManager.chain.BestSnapshot()
best := sp.server.chain.BestSnapshot()
return &best.Hash, best.Height, nil
}
@ -532,7 +533,7 @@ func (sp *serverPeer) OnGetMiningState(p *peer.Peer, msg *wire.MsgGetMiningState
// Access the block manager and get the list of best blocks to mine on.
bm := sp.server.blockManager
mp := sp.server.txMemPool
best := bm.chain.BestSnapshot()
best := sp.server.chain.BestSnapshot()
// Send out blank mining states if it's early in the blockchain.
if best.Height < activeNetParams.StakeValidationHeight-1 {
@ -559,7 +560,7 @@ func (sp *serverPeer) OnGetMiningState(p *peer.Peer, msg *wire.MsgGetMiningState
// per mining state message. There is nothing to send when there are no
// eligible blocks.
blockHashes := SortParentsByVotes(mp, best.Hash, children,
bm.server.chainParams)
bm.cfg.ChainParams)
numBlocks := len(blockHashes)
if numBlocks == 0 {
return
@ -777,7 +778,7 @@ func (sp *serverPeer) OnGetBlocks(p *peer.Peer, msg *wire.MsgGetBlocks) {
// Use the block after the genesis block if no other blocks in the
// provided locator are known. This does mean the client will start
// over with the genesis block if unknown block locators are provided.
chain := sp.server.blockManager.chain
chain := sp.server.chain
hashList := chain.LocateBlocks(msg.BlockLocatorHashes, &msg.HashStop,
wire.MaxBlocksPerMsg)
@ -818,7 +819,7 @@ func (sp *serverPeer) OnGetHeaders(p *peer.Peer, msg *wire.MsgGetHeaders) {
// Use the block after the genesis block if no other blocks in the
// provided locator are known. This does mean the client will start
// over with the genesis block if unknown block locators are provided.
chain := sp.server.blockManager.chain
chain := sp.server.chain
headers := chain.LocateHeaders(msg.BlockLocatorHashes, &msg.HashStop)
// Send found headers to the requesting peer.
@ -892,7 +893,7 @@ func (sp *serverPeer) OnGetCFilter(p *peer.Peer, msg *wire.MsgGetCFilter) {
// block was disconnected, or this has always been a sidechain block) build
// the filter on the spot.
if len(filterBytes) == 0 {
block, err := sp.server.blockManager.chain.BlockByHash(&msg.BlockHash)
block, err := sp.server.chain.BlockByHash(&msg.BlockHash)
if err != nil {
peerLog.Errorf("OnGetCFilter: failed to fetch non-mainchain "+
"block %v: %v", &msg.BlockHash, err)
@ -961,7 +962,7 @@ func (sp *serverPeer) OnGetCFHeaders(p *peer.Peer, msg *wire.MsgGetCFHeaders) {
// Use the block after the genesis block if no other blocks in the provided
// locator are known. This does mean the served filter headers will start
// over at the genesis block if unknown block locators are provided.
chain := sp.server.blockManager.chain
chain := sp.server.chain
hashList := chain.LocateBlocks(msg.BlockLocatorHashes, &msg.HashStop,
wire.MaxCFHeadersPerMsg)
if len(hashList) == 0 {
@ -1158,11 +1159,11 @@ func (s *server) PruneRebroadcastInventory() {
// both websocket and getblocktemplate long poll clients of the passed
// transactions. This function should be called whenever new transactions
// are added to the mempool.
func (s *server) AnnounceNewTransactions(newTxs []*dcrutil.Tx) {
func (s *server) AnnounceNewTransactions(txns []*dcrutil.Tx) {
// Generate and relay inventory vectors for all newly accepted
// transactions into the memory pool due to the original being
// accepted.
for _, tx := range newTxs {
for _, tx := range txns {
// Generate the inventory vector and relay it.
iv := wire.NewInvVect(wire.InvTypeTx, tx.Hash())
s.RelayInventory(iv, tx, false)
@ -1173,12 +1174,21 @@ func (s *server) AnnounceNewTransactions(newTxs []*dcrutil.Tx) {
// Potentially notify any getblocktemplate long poll clients
// about stale block templates due to the new transaction.
s.rpcServer.gbtWorkState.NotifyMempoolTx(
s.txMemPool.LastUpdated())
s.rpcServer.gbtWorkState.NotifyMempoolTx(s.txMemPool.LastUpdated())
}
}
}
// TransactionConfirmed marks the provided single confirmation transaction as
// no longer needing rebroadcasting.
func (s *server) TransactionConfirmed(tx *dcrutil.Tx) {
// Rebroadcasting is only necessary when the RPC server is active.
if s.rpcServer != nil {
iv := wire.NewInvVect(wire.InvTypeTx, tx.Hash())
s.RemoveRebroadcastInventory(iv)
}
}
// pushTxMsg sends a tx message for the provided transaction hash to the
// connected peer. An error is returned if the transaction hash is not known.
func (s *server) pushTxMsg(sp *serverPeer, hash *chainhash.Hash, doneChan chan<- struct{}, waitChan <-chan struct{}) error {
@ -1212,7 +1222,7 @@ func (s *server) pushTxMsg(sp *serverPeer, hash *chainhash.Hash, doneChan chan<-
// pushBlockMsg sends a block message for the provided block hash to the
// connected peer. An error is returned if the block hash is not known.
func (s *server) pushBlockMsg(sp *serverPeer, hash *chainhash.Hash, doneChan chan<- struct{}, waitChan <-chan struct{}) error {
block, err := sp.server.blockManager.chain.BlockByHash(hash)
block, err := sp.server.chain.BlockByHash(hash)
if err != nil {
peerLog.Tracef("Unable to fetch requested block hash %v: %v",
hash, err)
@ -1244,7 +1254,7 @@ func (s *server) pushBlockMsg(sp *serverPeer, hash *chainhash.Hash, doneChan cha
// to trigger it to issue another getblocks message for the next
// batch of inventory.
if sendInv {
best := sp.server.blockManager.chain.BestSnapshot()
best := sp.server.chain.BestSnapshot()
invMsg := wire.NewMsgInvSizeHint(1)
iv := wire.NewInvVect(wire.InvTypeBlock, &best.Hash)
invMsg.AddInvVect(iv)
@ -2016,9 +2026,9 @@ out:
delete(pendingInvs, *msg)
case broadcastPruneInventory:
best := s.blockManager.chain.BestSnapshot()
best := s.chain.BestSnapshot()
nextStakeDiff, err :=
s.blockManager.chain.CalcNextRequiredStakeDifficulty()
s.chain.CalcNextRequiredStakeDifficulty()
if err != nil {
srvrLog.Errorf("Failed to get next stake difficulty: %v",
err)
@ -2058,7 +2068,7 @@ out:
// ticket has been revived.
if txType == stake.TxTypeSSRtx {
refSStxHash := tx.MsgTx().TxIn[0].PreviousOutPoint.Hash
if !s.blockManager.chain.CheckLiveTicket(refSStxHash) {
if !s.chain.CheckLiveTicket(refSStxHash) {
delete(pendingInvs, iv)
srvrLog.Debugf("Pending revocation broadcast "+
"inventory for tx %v removed. "+
@ -2534,11 +2544,24 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
if len(indexes) > 0 {
indexManager = indexers.NewManager(db, indexes, chainParams)
}
bm, err := newBlockManager(&s, indexManager, interrupt)
// Create a new block chain instance with the appropriate configuration.
s.chain, err = blockchain.New(&blockchain.Config{
DB: s.db,
Interrupt: interrupt,
ChainParams: s.chainParams,
TimeSource: s.timeSource,
Notifications: func(notification *blockchain.Notification) {
if s.blockManager != nil {
s.blockManager.handleBlockchainNotification(notification)
}
},
SigCache: s.sigCache,
IndexManager: indexManager,
})
if err != nil {
return nil, err
}
s.blockManager = bm
txC := mempool.Config{
Policy: mempool.Policy{
@ -2552,23 +2575,23 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
MinRelayTxFee: cfg.minRelayTxFee,
AllowOldVotes: cfg.AllowOldVotes,
StandardVerifyFlags: func() (txscript.ScriptFlags, error) {
return standardScriptVerifyFlags(bm.chain)
return standardScriptVerifyFlags(s.chain)
},
AcceptSequenceLocks: bm.chain.IsFixSeqLocksAgendaActive,
AcceptSequenceLocks: s.chain.IsFixSeqLocksAgendaActive,
},
ChainParams: chainParams,
NextStakeDifficulty: func() (int64, error) {
return bm.chain.BestSnapshot().NextStakeDiff, nil
return s.chain.BestSnapshot().NextStakeDiff, nil
},
FetchUtxoView: bm.chain.FetchUtxoView,
BlockByHash: bm.chain.BlockByHash,
BestHash: func() *chainhash.Hash { return &bm.chain.BestSnapshot().Hash },
BestHeight: func() int64 { return bm.chain.BestSnapshot().Height },
CalcSequenceLock: bm.chain.CalcSequenceLock,
SubsidyCache: bm.chain.FetchSubsidyCache(),
FetchUtxoView: s.chain.FetchUtxoView,
BlockByHash: s.chain.BlockByHash,
BestHash: func() *chainhash.Hash { return &s.chain.BestSnapshot().Hash },
BestHeight: func() int64 { return s.chain.BestSnapshot().Height },
CalcSequenceLock: s.chain.CalcSequenceLock,
SubsidyCache: s.chain.FetchSubsidyCache(),
SigCache: s.sigCache,
PastMedianTime: func() time.Time {
return bm.chain.BestSnapshot().MedianTime
return s.chain.BestSnapshot().MedianTime
},
AddrIndex: s.addrIndex,
ExistsAddrIndex: s.existsAddrIndex,
@ -2581,6 +2604,27 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
},
}
s.txMemPool = mempool.New(&txC)
s.blockManager, err = newBlockManager(&blockManagerConfig{
PeerNotifier: &s,
Chain: s.chain,
ChainParams: s.chainParams,
TimeSource: s.timeSource,
FeeEstimator: s.feeEstimator,
TxMemPool: s.txMemPool,
BgBlkTmplGenerator: s.bg,
NotifyWinningTickets: func(wtnd *WinningTicketsNtfnData) {
if s.rpcServer != nil {
s.rpcServer.ntfnMgr.NotifyWinningTickets(wtnd)
}
},
PruneRebroadcastInventory: s.PruneRebroadcastInventory,
RpcServer: func() *rpcServer {
return s.rpcServer
},
})
if err != nil {
return nil, err
}
// Create the mining policy and block template generator based on the
// configuration options.
@ -2594,7 +2638,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
TxMinFreeFee: cfg.minRelayTxFee,
}
tg := newBlkTmplGenerator(&policy, s.txMemPool, s.timeSource, s.sigCache,
s.chainParams, bm.chain, bm)
s.chainParams, s.chain, s.blockManager)
// Create the background block template generator if the config has a
// mining address.
@ -2607,9 +2651,9 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
PermitConnectionlessMining: cfg.SimNet,
BlockTemplateGenerator: tg,
MiningAddrs: cfg.miningAddrs,
ProcessBlock: bm.ProcessBlock,
ProcessBlock: s.blockManager.ProcessBlock,
ConnectedCount: s.ConnectedCount,
IsCurrent: bm.IsCurrent,
IsCurrent: s.blockManager.IsCurrent,
})
// Only setup a function to return new addresses to connect to when