Create blockmanager with reference to txMemPool.

The objective is to remove the reference from blockManager to
server. Since the blockManager is responsible for keeping the mempool
in sync, it should have a direct reference to it.
This commit is contained in:
Jim Posen 2017-08-10 16:09:22 -07:00
parent 19b42c3c9b
commit 22de1f6d08
2 changed files with 97 additions and 89 deletions

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -141,6 +141,7 @@ type blockManager struct {
started int32
shutdown int32
chain *blockchain.BlockChain
txMemPool *mempool.TxPool
rejectedTxns map[chainhash.Hash]struct{}
requestedTxns map[chainhash.Hash]struct{}
requestedBlocks map[chainhash.Hash]struct{}
@ -431,7 +432,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.txMemPool.ProcessTransaction(tmsg.tx,
allowOrphans, true, mempool.Tag(tmsg.peer.ID()))
// Remove transaction from request maps. Either the mempool/chain
@ -867,7 +868,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.txMemPool.HaveTransaction(&invVect.Hash) {
return true, nil
}
@ -1215,10 +1216,10 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// transaction are NOT removed recursively because they are still
// valid.
for _, tx := range block.Transactions()[1:] {
b.server.txMemPool.RemoveTransaction(tx, false)
b.server.txMemPool.RemoveDoubleSpends(tx)
b.server.txMemPool.RemoveOrphan(tx)
acceptedTxs := b.server.txMemPool.ProcessOrphans(tx)
b.txMemPool.RemoveTransaction(tx, false)
b.txMemPool.RemoveDoubleSpends(tx)
b.txMemPool.RemoveOrphan(tx)
acceptedTxs := b.txMemPool.ProcessOrphans(tx)
b.server.AnnounceNewTransactions(acceptedTxs)
}
@ -1246,13 +1247,13 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// Reinsert all of the transactions (except the coinbase) into
// the transaction pool.
for _, tx := range block.Transactions()[1:] {
_, _, err := b.server.txMemPool.MaybeAcceptTransaction(tx,
_, _, err := b.txMemPool.MaybeAcceptTransaction(tx,
false, false)
if err != nil {
// Remove the transaction and all transactions
// that depend on it if it wasn't accepted into
// the transaction pool.
b.server.txMemPool.RemoveTransaction(tx, true)
b.txMemPool.RemoveTransaction(tx, true)
}
}
@ -1390,64 +1391,16 @@ func (b *blockManager) Pause() chan<- struct{} {
return c
}
// checkpointSorter implements sort.Interface to allow a slice of checkpoints to
// be sorted.
type checkpointSorter []chaincfg.Checkpoint
// Len returns the number of checkpoints in the slice. It is part of the
// sort.Interface implementation.
func (s checkpointSorter) Len() int {
return len(s)
}
// Swap swaps the checkpoints at the passed indices. It is part of the
// sort.Interface implementation.
func (s checkpointSorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Less returns whether the checkpoint with index i should sort before the
// checkpoint with index j. It is part of the sort.Interface implementation.
func (s checkpointSorter) Less(i, j int) bool {
return s[i].Height < s[j].Height
}
// mergeCheckpoints returns two slices of checkpoints merged into one slice
// such that the checkpoints are sorted by height. In the case the additional
// checkpoints contain a checkpoint with the same height as a checkpoint in the
// default checkpoints, the additional checkpoint will take precedence and
// overwrite the default one.
func mergeCheckpoints(defaultCheckpoints, additional []chaincfg.Checkpoint) []chaincfg.Checkpoint {
// Create a map of the additional checkpoints to remove duplicates while
// leaving the most recently-specified checkpoint.
extra := make(map[int32]chaincfg.Checkpoint)
for _, checkpoint := range additional {
extra[checkpoint.Height] = checkpoint
}
// Add all default checkpoints that do not have an override in the
// additional checkpoints.
numDefault := len(defaultCheckpoints)
checkpoints := make([]chaincfg.Checkpoint, 0, numDefault+len(extra))
for _, checkpoint := range defaultCheckpoints {
if _, exists := extra[checkpoint.Height]; !exists {
checkpoints = append(checkpoints, checkpoint)
}
}
// Append the additional checkpoints and return the sorted results.
for _, checkpoint := range extra {
checkpoints = append(checkpoints, checkpoint)
}
sort.Sort(checkpointSorter(checkpoints))
return checkpoints
}
// newBlockManager returns a new bitcoin block manager.
// Use Start to begin processing asynchronous block and inv updates.
func newBlockManager(s *server, indexManager blockchain.IndexManager) (*blockManager, error) {
func newBlockManager(
s *server, indexManager blockchain.IndexManager,
chain *blockchain.BlockChain, txMemPool *mempool.TxPool,
) (*blockManager, error) {
bm := blockManager{
server: s,
chain: chain,
txMemPool: txMemPool,
rejectedTxns: make(map[chainhash.Hash]struct{}),
requestedTxns: make(map[chainhash.Hash]struct{}),
requestedBlocks: make(map[chainhash.Hash]struct{}),
@ -1457,26 +1410,7 @@ func newBlockManager(s *server, indexManager blockchain.IndexManager) (*blockMan
quit: make(chan struct{}),
}
// Merge given checkpoints with the default ones unless they are disabled.
var checkpoints []chaincfg.Checkpoint
if !cfg.DisableCheckpoints {
checkpoints = mergeCheckpoints(s.chainParams.Checkpoints, cfg.addCheckpoints)
}
// Create a new block chain instance with the appropriate configuration.
var err error
bm.chain, err = blockchain.New(&blockchain.Config{
DB: s.db,
ChainParams: s.chainParams,
Checkpoints: checkpoints,
TimeSource: s.timeSource,
SigCache: s.sigCache,
IndexManager: indexManager,
HashCache: s.hashCache,
})
if err != nil {
return nil, err
}
// Register blockchain notification callbacks
bm.chain.Subscribe(bm.handleNotifyMsg)
best := bm.chain.BestSnapshot()

View file

@ -2448,11 +2448,27 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
if len(indexes) > 0 {
indexManager = indexers.NewManager(db, indexes)
}
bm, err := newBlockManager(&s, indexManager)
// Merge given checkpoints with the default ones unless they are disabled.
var checkpoints []chaincfg.Checkpoint
if !cfg.DisableCheckpoints {
checkpoints = mergeCheckpoints(s.chainParams.Checkpoints, cfg.addCheckpoints)
}
// Create a new block chain instance with the appropriate configuration.
chain, err := blockchain.New(&blockchain.Config{
DB: s.db,
ChainParams: s.chainParams,
Checkpoints: checkpoints,
TimeSource: s.timeSource,
Notifications: bm.handleNotifyMsg,
SigCache: s.sigCache,
IndexManager: indexManager,
HashCache: s.hashCache,
})
if err != nil {
return nil, err
}
s.blockManager = bm
txC := mempool.Config{
Policy: mempool.Policy{
@ -2466,11 +2482,11 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
MaxTxVersion: 2,
},
ChainParams: chainParams,
FetchUtxoView: s.blockManager.chain.FetchUtxoView,
BestHeight: func() int32 { return bm.chain.BestSnapshot().Height },
MedianTimePast: func() time.Time { return bm.chain.BestSnapshot().MedianTime },
FetchUtxoView: chain.FetchUtxoView,
BestHeight: func() int32 { return chain.BestSnapshot().Height },
MedianTimePast: func() time.Time { return chain.BestSnapshot().MedianTime },
CalcSequenceLock: func(tx *btcutil.Tx, view *blockchain.UtxoViewpoint) (*blockchain.SequenceLock, error) {
return bm.chain.CalcSequenceLock(tx, view, true)
return chain.CalcSequenceLock(tx, view, true)
},
IsDeploymentActive: bm.chain.IsDeploymentActive,
SigCache: s.sigCache,
@ -2479,6 +2495,11 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
}
s.txMemPool = mempool.New(&txC)
s.bm, err = newBlockManager(&s, indexManager, &chain, s.txMemPool)
if err != nil {
return nil, err
}
// Create the mining policy and block template generator based on the
// configuration options.
//
@ -2672,3 +2693,56 @@ func dynamicTickDuration(remaining time.Duration) time.Duration {
}
return time.Hour
}
// checkpointSorter implements sort.Interface to allow a slice of checkpoints to
// be sorted.
type checkpointSorter []chaincfg.Checkpoint
// Len returns the number of checkpoints in the slice. It is part of the
// sort.Interface implementation.
func (s checkpointSorter) Len() int {
return len(s)
}
// Swap swaps the checkpoints at the passed indices. It is part of the
// sort.Interface implementation.
func (s checkpointSorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Less returns whether the checkpoint with index i should sort before the
// checkpoint with index j. It is part of the sort.Interface implementation.
func (s checkpointSorter) Less(i, j int) bool {
return s[i].Height < s[j].Height
}
// mergeCheckpoints returns two slices of checkpoints merged into one slice
// such that the checkpoints are sorted by height. In the case the additional
// checkpoints contain a checkpoint with the same height as a checkpoint in the
// default checkpoints, the additional checkpoint will take precedence and
// overwrite the default one.
func mergeCheckpoints(defaultCheckpoints, additional []chaincfg.Checkpoint) []chaincfg.Checkpoint {
// Create a map of the additional checkpoints to remove duplicates while
// leaving the most recently-specified checkpoint.
extra := make(map[int32]chaincfg.Checkpoint)
for _, checkpoint := range additional {
extra[checkpoint.Height] = checkpoint
}
// Add all default checkpoints that do not have an override in the
// additional checkpoints.
numDefault := len(defaultCheckpoints)
checkpoints := make([]chaincfg.Checkpoint, 0, numDefault+len(extra))
for _, checkpoint := range defaultCheckpoints {
if _, exists := extra[checkpoint.Height]; !exists {
checkpoints = append(checkpoints, checkpoint)
}
}
// Append the additional checkpoints and return the sorted results.
for _, checkpoint := range extra {
checkpoints = append(checkpoints, checkpoint)
}
sort.Sort(checkpointSorter(checkpoints))
return checkpoints
}