From 22de1f6d080bd5eda656f3b5993ce121c899d69e Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 10 Aug 2017 16:09:22 -0700 Subject: [PATCH] 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. --- blockmanager.go | 100 ++++++++---------------------------------------- server.go | 86 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 89 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 201ac3ce..757ae71f 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -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() diff --git a/server.go b/server.go index cf8db264..ecf1a80d 100644 --- a/server.go +++ b/server.go @@ -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 +}