diff options
author | MarcoFalke <falke.marco@gmail.com> | 2021-04-01 10:58:37 +0200 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2021-04-01 10:58:53 +0200 |
commit | 80a699fda9ff1129546cabbf17e955680a1cc705 (patch) | |
tree | 782dbdd906096d3b1a60ccae2f8604d8e25aa25d | |
parent | c2caa0fc4d5668308a717de454003d3ff46a6a85 (diff) | |
parent | 693414d27181cf967f787a2ca72344e52c58c7f0 (diff) |
Merge #21525: [Bundle 4.5/n] Followup fixups to bundle 4
693414d27181cf967f787a2ca72344e52c58c7f0 node/ifaces: ChainImpl: Use an accessor for ChainMan (Carl Dong)
98c4e252f0d09bebb2e4ad3289407459c2cda5d5 node/ifaces: NodeImpl: Use an accessor for ChainMan (Carl Dong)
7e8b5ee814b0b8c34acb20637ed4fc988ccba555 validation: Make BlockManager::LookupBlockIndex const (Carl Dong)
88aead263c61d86e5f836028f517cfbf2a575498 node: Avoid potential UB by asserting assumptions (Carl Dong)
1dd8ed7a8491e51b76eeb236b15b794d9254f674 net_processing: Move comments to declarations (Carl Dong)
07156eb387ea580be5e2ce4a1744992ce7575903 node/coinstats: Replace #include with fwd-declaration (Carl Dong)
7b8e976cd5ac78a22f1be2b2fed8562c693af5d9 miner: Add chainstate member to BlockAssembler (Carl Dong)
e62067e7bcad5a559899afff2e4a8e8b7e9f4301 Revert "miner: Pass in chainstate to BlockAssembler::CreateNewBlock" (Carl Dong)
eede0647b06b6009080c4e536a2705e911d6ee19 Revert "scripted-diff: Invoke CreateNewBlock with chainstate" (Carl Dong)
0c1b2bc549aec77b247f0103652d883227841ac5 Revert "miner: Remove old CreateNewBlock w/o chainstate param" (Carl Dong)
Pull request description:
Chronological history of this changeset:
1. Bundle 4 (#21270) got merged
2. Posthumous reviews were posted
3. These changes were prepended in bundle 5
4. More reviews were added in bundle 5
5. Someone suggested that we split the prepended changes up to another PR
6. This is that PR
In the future, I will just do posthumous review changes in another PR instead. I apologize for the confusion.
Addresses posthumous reviews on bundle 4:
- From jnewbery:
- https://github.com/bitcoin/bitcoin/pull/21270#issuecomment-796738048
- I didn't fix this one, but I added a `TODO` comment so that we don't lost track of it
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r592291225
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r592296942
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r592299738
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r592301704
- From MarcoFalke:
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r593096212
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r593097032
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r593097867
- https://github.com/bitcoin/bitcoin/pull/21270#discussion_r593100570
Addresses reviews on bundle 5:
- Checking chainman existence before locking cs_main
- MarcoFalke
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r596601776
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r596601876
- Appropriate locking, usage of chainman, and control flow in `src/node/interfaces.cpp`
- MarcoFalke
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r596601383
- jnewbery
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r597029360
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r597029921
- ryanofsky
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r597163828
- Style/comment formatting changes
- jnewbery
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r597026552
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r597027186
- Making LookupBlockIndex const
- jnewbery
- https://github.com/bitcoin/bitcoin/pull/21391#discussion_r597035062
ACKs for top commit:
MarcoFalke:
review ACK 693414d27181cf967f787a2ca72344e52c58c7f0 🛐
ryanofsky:
Code review ACK 693414d27181cf967f787a2ca72344e52c58c7f0. I reviewed this previously as part of #21391. I am a fan of the increasingly complicated bundle numbering, and kind of hope there in the next round there is some way we can get bundles 5.333333 and 5.666667!
jamesob:
ACK 693414d27181cf967f787a2ca72344e52c58c7f0 ([`jamesob/ackr/21525.1.dongcarl.bundle_4_5_n_followup_f`](https://github.com/jamesob/bitcoin/tree/ackr/21525.1.dongcarl.bundle_4_5_n_followup_f))
Tree-SHA512: 9bdc199f70400d01764e1bd03c25bdb6cff26dcef60e4ca3b649baf8d017a2dfc1f058099067962b4b6ccd32d078002b1389d733039f4c337558cb70324c0ee3
-rw-r--r-- | src/miner.cpp | 19 | ||||
-rw-r--r-- | src/miner.h | 8 | ||||
-rw-r--r-- | src/net_processing.cpp | 101 | ||||
-rw-r--r-- | src/node/coin.cpp | 1 | ||||
-rw-r--r-- | src/node/coinstats.h | 2 | ||||
-rw-r--r-- | src/node/interfaces.cpp | 69 | ||||
-rw-r--r-- | src/node/transaction.cpp | 1 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 6 | ||||
-rw-r--r-- | src/test/blockfilter_index_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/miner_tests.cpp | 40 | ||||
-rw-r--r-- | src/test/util/mining.cpp | 4 | ||||
-rw-r--r-- | src/test/util/setup_common.cpp | 2 | ||||
-rw-r--r-- | src/test/validation_block_tests.cpp | 4 | ||||
-rw-r--r-- | src/validation.cpp | 2 | ||||
-rw-r--r-- | src/validation.h | 2 |
15 files changed, 148 insertions, 115 deletions
diff --git a/src/miner.cpp b/src/miner.cpp index fe7a54c052..8a9406f810 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -55,9 +55,10 @@ BlockAssembler::Options::Options() { nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; } -BlockAssembler::BlockAssembler(const CTxMemPool& mempool, const CChainParams& params, const Options& options) +BlockAssembler::BlockAssembler(CChainState& chainstate, const CTxMemPool& mempool, const CChainParams& params, const Options& options) : chainparams(params), - m_mempool(mempool) + m_mempool(mempool), + m_chainstate(chainstate) { blockMinFeeRate = options.blockMinFeeRate; // Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity: @@ -79,8 +80,8 @@ static BlockAssembler::Options DefaultOptions() return options; } -BlockAssembler::BlockAssembler(const CTxMemPool& mempool, const CChainParams& params) - : BlockAssembler(mempool, params, DefaultOptions()) {} +BlockAssembler::BlockAssembler(CChainState& chainstate, const CTxMemPool& mempool, const CChainParams& params) + : BlockAssembler(chainstate, mempool, params, DefaultOptions()) {} void BlockAssembler::resetBlock() { @@ -96,7 +97,7 @@ void BlockAssembler::resetBlock() nFees = 0; } -std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(CChainState& chainstate, const CScript& scriptPubKeyIn) +std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) { int64_t nTimeStart = GetTimeMicros(); @@ -114,8 +115,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(CChainState& chai pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end LOCK2(cs_main, m_mempool.cs); - assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*chainstate.m_chain.Tip())); - CBlockIndex* pindexPrev = chainstate.m_chain.Tip(); + assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*m_chainstate.m_chain.Tip())); + CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip(); assert(pindexPrev != nullptr); nHeight = pindexPrev->nHeight + 1; @@ -174,8 +175,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(CChainState& chai pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); BlockValidationState state; - assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate)); - if (!TestBlockValidity(state, chainparams, chainstate, *pblock, pindexPrev, false, false)) { + assert(std::addressof(::ChainstateActive()) == std::addressof(m_chainstate)); + if (!TestBlockValidity(state, chainparams, m_chainstate, *pblock, pindexPrev, false, false)) { throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString())); } int64_t nTime2 = GetTimeMicros(); diff --git a/src/miner.h b/src/miner.h index 023635814c..c400c90f6c 100644 --- a/src/miner.h +++ b/src/miner.h @@ -146,6 +146,7 @@ private: int64_t nLockTimeCutoff; const CChainParams& chainparams; const CTxMemPool& m_mempool; + CChainState& m_chainstate; public: struct Options { @@ -154,11 +155,11 @@ public: CFeeRate blockMinFeeRate; }; - explicit BlockAssembler(const CTxMemPool& mempool, const CChainParams& params); - explicit BlockAssembler(const CTxMemPool& mempool, const CChainParams& params, const Options& options); + explicit BlockAssembler(CChainState& chainstate, const CTxMemPool& mempool, const CChainParams& params); + explicit BlockAssembler(CChainState& chainstate, const CTxMemPool& mempool, const CChainParams& params, const Options& options); /** Construct a new block template with coinbase to scriptPubKeyIn */ - std::unique_ptr<CBlockTemplate> CreateNewBlock(CChainState& chainstate, const CScript& scriptPubKeyIn); + std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn); inline static std::optional<int64_t> m_last_block_num_txs{}; inline static std::optional<int64_t> m_last_block_weight{}; @@ -201,6 +202,7 @@ private: void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce); int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); +// TODO just accept a CBlockIndex* /** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */ void RegenerateCommitments(CBlock& block, BlockManager& blockman); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 14b628acf0..17d7619ff5 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -482,19 +482,70 @@ private: /** Offset into vExtraTxnForCompact to insert the next tx */ size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0; + /** Check whether the last unknown block a peer advertised is not yet known. */ void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + /** Update tracking information about which blocks a peer is assumed to have. */ void UpdateBlockAvailability(NodeId nodeid, const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool CanDirectFetch() EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + /** + * To prevent fingerprinting attacks, only send blocks/headers outside of + * the active chain if they are no more than a month older (both in time, + * and in best equivalent proof of work) than the best header chain we know + * about and we fully-validated them at some point. + */ bool BlockRequestAllowed(const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool AlreadyHaveBlock(const uint256& block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); void ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& inv); + + /** + * Validation logic for compact filters request handling. + * + * May disconnect from the peer in the case of a bad request. + * + * @param[in] peer The peer that we received the request from + * @param[in] filter_type The filter type the request is for. Must be basic filters. + * @param[in] start_height The start height for the request + * @param[in] stop_hash The stop_hash for the request + * @param[in] max_height_diff The maximum number of items permitted to request, as specified in BIP 157 + * @param[out] stop_index The CBlockIndex for the stop_hash block, if the request can be serviced. + * @param[out] filter_index The filter index, if the request can be serviced. + * @return True if the request can be serviced. + */ bool PrepareBlockFilterRequest(CNode& peer, BlockFilterType filter_type, uint32_t start_height, const uint256& stop_hash, uint32_t max_height_diff, const CBlockIndex*& stop_index, BlockFilterIndex*& filter_index); + + /** + * Handle a cfilters request. + * + * May disconnect from the peer in the case of a bad request. + * + * @param[in] peer The peer that we received the request from + * @param[in] vRecv The raw message received + */ void ProcessGetCFilters(CNode& peer, CDataStream& vRecv); + + /** + * Handle a cfheaders request. + * + * May disconnect from the peer in the case of a bad request. + * + * @param[in] peer The peer that we received the request from + * @param[in] vRecv The raw message received + */ void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv); + + /** + * Handle a getcfcheckpt request. + * + * May disconnect from the peer in the case of a bad request. + * + * @param[in] peer The peer that we received the request from + * @param[in] vRecv The raw message received + */ void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv); }; } // namespace @@ -748,7 +799,6 @@ static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIV return false; } -/** Check whether the last unknown block a peer advertised is not yet known. */ void PeerManagerImpl::ProcessBlockAvailability(NodeId nodeid) { CNodeState *state = State(nodeid); assert(state != nullptr); @@ -764,7 +814,6 @@ void PeerManagerImpl::ProcessBlockAvailability(NodeId nodeid) { } } -/** Update tracking information about which blocks a peer is assumed to have. */ void PeerManagerImpl::UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { CNodeState *state = State(nodeid); assert(state != nullptr); @@ -1191,16 +1240,6 @@ bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationStat return false; } - -////////////////////////////////////////////////////////////////////////////// -// -// blockchain -> download logic notification -// - -// To prevent fingerprinting attacks, only send blocks/headers outside of the -// active chain if they are no more than a month older (both in time, and in -// best equivalent proof of work) than the best header chain we know about and -// we fully-validated them at some point. bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex) { AssertLockHeld(cs_main); @@ -2101,20 +2140,6 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set) m_mempool.check(m_chainman.ActiveChainstate()); } -/** - * Validation logic for compact filters request handling. - * - * May disconnect from the peer in the case of a bad request. - * - * @param[in] peer The peer that we received the request from - * @param[in] filter_type The filter type the request is for. Must be basic filters. - * @param[in] start_height The start height for the request - * @param[in] stop_hash The stop_hash for the request - * @param[in] max_height_diff The maximum number of items permitted to request, as specified in BIP 157 - * @param[out] stop_index The CBlockIndex for the stop_hash block, if the request can be serviced. - * @param[out] filter_index The filter index, if the request can be serviced. - * @return True if the request can be serviced. - */ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, BlockFilterType filter_type, uint32_t start_height, const uint256& stop_hash, uint32_t max_height_diff, @@ -2168,14 +2193,6 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, return true; } -/** - * Handle a cfilters request. - * - * May disconnect from the peer in the case of a bad request. - * - * @param[in] peer The peer that we received the request from - * @param[in] vRecv The raw message received - */ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv) { uint8_t filter_type_ser; @@ -2207,14 +2224,6 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv) } } -/** - * Handle a cfheaders request. - * - * May disconnect from the peer in the case of a bad request. - * - * @param[in] peer The peer that we received the request from - * @param[in] vRecv The raw message received - */ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv) { uint8_t filter_type_ser; @@ -2259,14 +2268,6 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv) m_connman.PushMessage(&peer, std::move(msg)); } -/** - * Handle a getcfcheckpt request. - * - * May disconnect from the peer in the case of a bad request. - * - * @param[in] peer The peer that we received the request from - * @param[in] vRecv The raw message received - */ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv) { uint8_t filter_type_ser; diff --git a/src/node/coin.cpp b/src/node/coin.cpp index 263dcff657..23d4fa2aae 100644 --- a/src/node/coin.cpp +++ b/src/node/coin.cpp @@ -11,6 +11,7 @@ void FindCoins(const NodeContext& node, std::map<COutPoint, Coin>& coins) { assert(node.mempool); + assert(node.chainman); LOCK2(cs_main, node.mempool->cs); assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate())); CCoinsViewCache& chain_view = node.chainman->ActiveChainstate().CoinsTip(); diff --git a/src/node/coinstats.h b/src/node/coinstats.h index 83f228aa7e..975651dcc4 100644 --- a/src/node/coinstats.h +++ b/src/node/coinstats.h @@ -8,11 +8,11 @@ #include <amount.h> #include <uint256.h> -#include <validation.h> #include <cstdint> #include <functional> +class BlockManager; class CCoinsView; enum class CoinStatsHashType { diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 0f4094e14b..7ad02f81dc 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -65,6 +65,8 @@ namespace node { namespace { class NodeImpl : public Node { +private: + ChainstateManager& chainman() { return *Assert(m_context->chainman); } public: explicit NodeImpl(NodeContext* context) { setContext(context); } void initLogging() override { InitLogging(*Assert(m_context->args)); } @@ -183,21 +185,28 @@ public: int getNumBlocks() override { LOCK(::cs_main); - assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain())); - return m_context->chainman->ActiveChain().Height(); + assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain())); + return chainman().ActiveChain().Height(); } uint256 getBestBlockHash() override { - assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain())); - const CBlockIndex* tip = WITH_LOCK(::cs_main, return m_context->chainman->ActiveChain().Tip()); + const CBlockIndex* tip; + { + // TODO: Temporary scope to check correctness of refactored code. + // Should be removed manually after merge of + // https://github.com/bitcoin/bitcoin/pull/20158 + LOCK(cs_main); + assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain())); + tip = chainman().ActiveChain().Tip(); + } return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash(); } int64_t getLastBlockTime() override { LOCK(::cs_main); - assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain())); - if (m_context->chainman->ActiveChain().Tip()) { - return m_context->chainman->ActiveChain().Tip()->GetBlockTime(); + assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain())); + if (chainman().ActiveChain().Tip()) { + return chainman().ActiveChain().Tip()->GetBlockTime(); } return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network } @@ -206,14 +215,22 @@ public: const CBlockIndex* tip; { LOCK(::cs_main); - assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain())); - tip = m_context->chainman->ActiveChain().Tip(); + assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain())); + tip = chainman().ActiveChain().Tip(); } return GuessVerificationProgress(Params().TxData(), tip); } bool isInitialBlockDownload() override { - assert(std::addressof(::ChainstateActive()) == std::addressof(m_context->chainman->ActiveChainstate())); - return m_context->chainman->ActiveChainstate().IsInitialBlockDownload(); + const CChainState* active_chainstate; + { + // TODO: Temporary scope to check correctness of refactored code. + // Should be removed manually after merge of + // https://github.com/bitcoin/bitcoin/pull/20158 + LOCK(::cs_main); + active_chainstate = &m_context->chainman->ActiveChainstate(); + assert(std::addressof(::ChainstateActive()) == std::addressof(*active_chainstate)); + } + return active_chainstate->IsInitialBlockDownload(); } bool getReindex() override { return ::fReindex; } bool getImporting() override { return ::fImporting; } @@ -239,8 +256,8 @@ public: bool getUnspentOutput(const COutPoint& output, Coin& coin) override { LOCK(::cs_main); - assert(std::addressof(::ChainstateActive()) == std::addressof(m_context->chainman->ActiveChainstate())); - return m_context->chainman->ActiveChainstate().CoinsTip().GetCoin(output, coin); + assert(std::addressof(::ChainstateActive()) == std::addressof(chainman().ActiveChainstate())); + return chainman().ActiveChainstate().CoinsTip().GetCoin(output, coin); } WalletClient& walletClient() override { @@ -414,6 +431,8 @@ public: class ChainImpl : public Chain { +private: + ChainstateManager& chainman() { return *Assert(m_node.chainman); } public: explicit ChainImpl(NodeContext& node) : m_node(node) {} std::optional<int> getHeight() override @@ -450,8 +469,8 @@ public: bool checkFinalTx(const CTransaction& tx) override { LOCK(cs_main); - assert(std::addressof(::ChainActive()) == std::addressof(m_node.chainman->ActiveChain())); - return CheckFinalTx(m_node.chainman->ActiveChain().Tip(), tx); + assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain())); + return CheckFinalTx(chainman().ActiveChain().Tip(), tx); } std::optional<int> findLocatorFork(const CBlockLocator& locator) override { @@ -516,8 +535,8 @@ public: double guessVerificationProgress(const uint256& block_hash) override { LOCK(cs_main); - assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman)); - return GuessVerificationProgress(Params().TxData(), m_node.chainman->m_blockman.LookupBlockIndex(block_hash)); + assert(std::addressof(g_chainman.m_blockman) == std::addressof(chainman().m_blockman)); + return GuessVerificationProgress(Params().TxData(), chainman().m_blockman.LookupBlockIndex(block_hash)); } bool hasBlocks(const uint256& block_hash, int min_height, std::optional<int> max_height) override { @@ -529,8 +548,8 @@ public: // used to limit the range, and passing min_height that's too low or // max_height that's too high will not crash or change the result. LOCK(::cs_main); - assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman)); - if (CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash)) { + assert(std::addressof(g_chainman.m_blockman) == std::addressof(chainman().m_blockman)); + if (CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) { if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height); for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) { // Check pprev to not segfault if min_height is too low @@ -621,8 +640,16 @@ public: } bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); } bool isInitialBlockDownload() override { - assert(std::addressof(::ChainstateActive()) == std::addressof(m_node.chainman->ActiveChainstate())); - return m_node.chainman->ActiveChainstate().IsInitialBlockDownload(); + const CChainState* active_chainstate; + { + // TODO: Temporary scope to check correctness of refactored code. + // Should be removed manually after merge of + // https://github.com/bitcoin/bitcoin/pull/20158 + LOCK(::cs_main); + active_chainstate = &chainman().ActiveChainstate(); + assert(std::addressof(::ChainstateActive()) == std::addressof(*active_chainstate)); + } + return active_chainstate->IsInitialBlockDownload(); } bool shutdownRequested() override { return ShutdownRequested(); } int64_t getAdjustedTime() override { return GetAdjustedTime(); } diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp index f47e85aceb..691b2791d7 100644 --- a/src/node/transaction.cpp +++ b/src/node/transaction.cpp @@ -38,6 +38,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t bool callback_set = false; { // cs_main scope + assert(node.chainman); LOCK(cs_main); assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate())); // If the transaction is already confirmed in the chain, don't do anything diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index fd780ba782..72ad0df199 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -150,7 +150,7 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd && !ShutdownRequested()) { - std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(mempool, Params()).CreateNewBlock(::ChainstateActive(), coinbase_script)); + std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(chainman.ActiveChainstate(), mempool, Params()).CreateNewBlock(coinbase_script)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; @@ -358,7 +358,7 @@ static RPCHelpMan generateblock() LOCK(cs_main); CTxMemPool empty_mempool; - std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(empty_mempool, chainparams).CreateNewBlock(::ChainstateActive(), coinbase_script)); + std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(::ChainstateActive(), empty_mempool, chainparams).CreateNewBlock(coinbase_script)); if (!blocktemplate) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); } @@ -748,7 +748,7 @@ static RPCHelpMan getblocktemplate() // Create new block CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = BlockAssembler(mempool, Params()).CreateNewBlock(::ChainstateActive(), scriptDummy); + pblocktemplate = BlockAssembler(::ChainstateActive(), mempool, Params()).CreateNewBlock(scriptDummy); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index 04da10715f..9903ba75cb 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -62,7 +62,7 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev, const CScript& scriptPubKey) { const CChainParams& chainparams = Params(); - std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(*m_node.mempool, chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey); + std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(::ChainstateActive(), *m_node.mempool, chainparams).CreateNewBlock(scriptPubKey); CBlock& block = pblocktemplate->block; block.hashPrevBlock = prev->GetBlockHash(); block.nTime = prev->nTime + 1; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 9acd17c463..9ba004cc38 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -44,7 +44,7 @@ BlockAssembler MinerTestingSetup::AssemblerForTest(const CChainParams& params) options.nBlockMaxWeight = MAX_BLOCK_WEIGHT; options.blockMinFeeRate = blockMinFeeRate; - return BlockAssembler(*m_node.mempool, params, options); + return BlockAssembler(::ChainstateActive(), *m_node.mempool, params, options); } constexpr static struct { @@ -122,7 +122,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co uint256 hashHighFeeTx = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey); + std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U); BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx); BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx); @@ -143,7 +143,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse; uint256 hashLowFeeTx = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(feeToUse).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); // Verify that the free tx and the low fee tx didn't get selected for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) { BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx); @@ -157,7 +157,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee hashLowFeeTx = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(feeToUse+2).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U); BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx); BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx); @@ -179,7 +179,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse; uint256 hashLowFeeTx2 = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); // Verify that this tx isn't selected. for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) { @@ -192,7 +192,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co tx.vin[0].prevout.n = 1; tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee m_node.mempool->addUnchecked(entry.Fee(10000).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9U); BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2); } @@ -215,7 +215,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) fCheckpointsEnabled = false; // Simple block creation, nothing special yet: - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); // We can't make transactions until we have inputs // Therefore, load 110 blocks :) @@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) LOCK(m_node.mempool->cs); // Just to make sure we can still make simple blocks - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); const CAmount BLOCKSUBSIDY = 50*COIN; const CAmount LOWFEE = CENT; @@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].prevout.hash = hash; } - BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops")); + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops")); m_node.mempool->clear(); tx.vin[0].prevout.hash = txFirst[0]->GetHash(); @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); m_node.mempool->clear(); // block size > limit @@ -311,13 +311,13 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); m_node.mempool->clear(); // orphan in *m_node.mempool, template creation fails hash = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); - BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); m_node.mempool->clear(); // child with higher feerate than parent @@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee hash = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); m_node.mempool->clear(); // coinbase in *m_node.mempool, template creation fails @@ -346,7 +346,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // give it a fee so it'll get mined m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw bad-cb-multiple - BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple")); + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple")); m_node.mempool->clear(); // double spend txn pair in *m_node.mempool, template creation fails @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); m_node.mempool->clear(); // subsidy changing @@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) next->BuildSkip(); ::ChainActive().SetTip(next); } - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); // Extend to a 210000-long block chain. while (::ChainActive().Tip()->nHeight < 210000) { CBlockIndex* prev = ::ChainActive().Tip(); @@ -387,7 +387,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) next->BuildSkip(); ::ChainActive().SetTip(next); } - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); // invalid p2sh txn in *m_node.mempool, template creation fails tx.vin[0].prevout.hash = txFirst[0]->GetHash(); @@ -404,7 +404,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw block-validation-failed - BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("block-validation-failed")); + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed")); m_node.mempool->clear(); // Delete the dummy blocks again. @@ -492,7 +492,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1; BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); // None of the of the absolute height/time locked tx should have made // it into the template because we still check IsFinalTx in CreateNewBlock, @@ -505,7 +505,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) ::ChainActive().Tip()->nHeight++; SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1); - BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)); + BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U); ::ChainActive().Tip()->nHeight--; diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp index ba1edba0ae..3fc3329da2 100644 --- a/src/test/util/mining.cpp +++ b/src/test/util/mining.cpp @@ -41,8 +41,8 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) { auto block = std::make_shared<CBlock>( - BlockAssembler{*Assert(node.mempool), Params()} - .CreateNewBlock(::ChainstateActive(), coinbase_scriptPubKey) + BlockAssembler{::ChainstateActive(), *Assert(node.mempool), Params()} + .CreateNewBlock(coinbase_scriptPubKey) ->block); LOCK(cs_main); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index bfb3466dcf..f7800aefca 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -247,7 +247,7 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransa { const CChainParams& chainparams = Params(); CTxMemPool empty_pool; - CBlock block = BlockAssembler(empty_pool, chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)->block; + CBlock block = BlockAssembler(::ChainstateActive(), empty_pool, chainparams).CreateNewBlock(scriptPubKey)->block; Assert(block.vtx.size() == 1); for (const CMutableTransaction& tx : txns) { diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index f3fc83078f..552be0a2da 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -63,7 +63,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash) static int i = 0; static uint64_t time = Params().GenesisBlock().nTime; - auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(::ChainstateActive(), CScript{} << i++ << OP_TRUE); + auto ptemplate = BlockAssembler(m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(CScript{} << i++ << OP_TRUE); auto pblock = std::make_shared<CBlock>(ptemplate->block); pblock->hashPrevBlock = prev_hash; pblock->nTime = ++time; @@ -325,7 +325,7 @@ BOOST_AUTO_TEST_CASE(witness_commitment_index) { CScript pubKey; pubKey << 1 << OP_TRUE; - auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(::ChainstateActive(), pubKey); + auto ptemplate = BlockAssembler(m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(pubKey); CBlock pblock = ptemplate->block; CTxOut witness; diff --git a/src/validation.cpp b/src/validation.cpp index d1b9efe7ba..b5c19971b4 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -169,7 +169,7 @@ namespace { std::set<int> setDirtyFileInfo; } // anon namespace -CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) +CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const { AssertLockHeld(cs_main); assert(std::addressof(g_chainman.BlockIndex()) == std::addressof(m_block_index)); diff --git a/src/validation.h b/src/validation.h index 2ff5f4ac87..21e63947fa 100644 --- a/src/validation.h +++ b/src/validation.h @@ -457,7 +457,7 @@ public: const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + CBlockIndex* LookupBlockIndex(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main); |