Skip to content

Commit f63fc53

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#21767: [Bundle 6/n] Prune g_chainman usage in auxiliary modules
7a799c9 index: refactor-only: Reuse CChain ref (Carl Dong) db33cde index: Add chainstate member to BaseIndex (Carl Dong) f4a47a1 bench: Use existing chainman in AssembleBlock (Carl Dong) 91226eb bench: Use existing NodeContext in DuplicateInputs (Carl Dong) e6b4aa6 miner: Pass in chainman to RegenerateCommitments (Carl Dong) 9ecade1 rest: Add GetChainman function and use it (Carl Dong) fc1c282 rpc/blockchain: Use existing blockman in gettxoutsetinfo (Carl Dong) Pull request description: Overall PR: #20158 (tree-wide: De-globalize ChainstateManager) The first 2 commits are fixups addressing review for the last bundle: #21391 NEW note: 1. I have opened #21766 which keeps track of potential improvements where the flaws already existed before the de-globalization work, please post on that issue about these improvements, thanks! Note to reviewers: 1. This bundle may _apparently_ introduce usage of `g_chainman` or `::Chain(state|)Active()` globals, but these are resolved later on in the overall PR. [Commits of overall PR](https://github.com/bitcoin/bitcoin/pull/20158/commits) 2. There may be seemingly obvious local references to `ChainstateManager` or other validation objects which are not being used in callers of the current function in question, this is done intentionally to **_keep each commit centered around one function/method_** to ease review and to make the overall change systematic. We don't assume anything about our callers. Rest assured that once we are considering that particular caller in later commits, we will use the obvious local references. [Commits of overall PR](https://github.com/bitcoin/bitcoin/pull/20158/commits) 3. When changing a function/method that has many callers (e.g. `LookupBlockIndex` with 55 callers), it is sometimes easier (and less error-prone) to use a scripted-diff. When doing so, there will be 3 commits in sequence so that every commit compiles like so: 1. Add `new_function`, make `old_function` a wrapper of `new_function`, divert all calls to `old_function` to `new_function` **in the local module only** 2. Scripted-diff to divert all calls to `old_function` to `new_function` **in the rest of the codebase** 3. Remove `old_function` ACKs for top commit: jarolrod: ACK 7a799c9 ariard: Code Review ACK 7a799c9 fjahr: re-ACK 7a799c9 MarcoFalke: review ACK 7a799c9 🌠 ryanofsky: Code review ACK 7a799c9. Basically no change since last review except fixed rebase conflicts and a new comment about REST Ensure() jamesob: conditional ACK 7a799c9 ([`jamesob/ackr/21767.1.dongcarl.bundle_6_n_prune_g_chai`](https://github.com/jamesob/bitcoin/tree/ackr/21767.1.dongcarl.bundle_6_n_prune_g_chai)) Tree-SHA512: 531c00ddcb318817457db2812d9a9d930bc664e58e6f7f1c746350732b031dd624270bfa6b9f49d8056aeb6321d973f0e38e4ff914acd6768edd8602c017d10e
2 parents c91589d + 7a799c9 commit f63fc53

16 files changed

+82
-40
lines changed

src/bench/block_assemble.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static void AssembleBlock(benchmark::Bench& bench)
3737
LOCK(::cs_main); // Required for ::AcceptToMemoryPool.
3838

3939
for (const auto& txr : txs) {
40-
const MempoolAcceptResult res = ::AcceptToMemoryPool(::ChainstateActive(), *test_setup->m_node.mempool, txr, false /* bypass_limits */);
40+
const MempoolAcceptResult res = ::AcceptToMemoryPool(test_setup->m_node.chainman->ActiveChainstate(), *test_setup->m_node.mempool, txr, false /* bypass_limits */);
4141
assert(res.m_result_type == MempoolAcceptResult::ResultType::VALID);
4242
}
4343
}

src/bench/duplicate_inputs.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ static void DuplicateInputs(benchmark::Bench& bench)
2525
CMutableTransaction naughtyTx{};
2626

2727
LOCK(cs_main);
28-
CBlockIndex* pindexPrev = ::ChainActive().Tip();
28+
assert(std::addressof(::ChainActive()) == std::addressof(testing_setup->m_node.chainman->ActiveChain()));
29+
CBlockIndex* pindexPrev = testing_setup->m_node.chainman->ActiveChain().Tip();
2930
assert(pindexPrev != nullptr);
3031
block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus());
3132
block.nNonce = 0;

src/index/base.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,33 +60,34 @@ bool BaseIndex::Init()
6060
}
6161

6262
LOCK(cs_main);
63+
CChain& active_chain = m_chainstate->m_chain;
6364
if (locator.IsNull()) {
6465
m_best_block_index = nullptr;
6566
} else {
66-
m_best_block_index = g_chainman.m_blockman.FindForkInGlobalIndex(::ChainActive(), locator);
67+
m_best_block_index = m_chainstate->m_blockman.FindForkInGlobalIndex(active_chain, locator);
6768
}
68-
m_synced = m_best_block_index.load() == ::ChainActive().Tip();
69+
m_synced = m_best_block_index.load() == active_chain.Tip();
6970
if (!m_synced) {
7071
bool prune_violation = false;
7172
if (!m_best_block_index) {
7273
// index is not built yet
7374
// make sure we have all block data back to the genesis
74-
const CBlockIndex* block = ::ChainActive().Tip();
75+
const CBlockIndex* block = active_chain.Tip();
7576
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
7677
block = block->pprev;
7778
}
78-
prune_violation = block != ::ChainActive().Genesis();
79+
prune_violation = block != active_chain.Genesis();
7980
}
8081
// in case the index has a best block set and is not fully synced
8182
// check if we have the required blocks to continue building the index
8283
else {
8384
const CBlockIndex* block_to_test = m_best_block_index.load();
84-
if (!ChainActive().Contains(block_to_test)) {
85+
if (!active_chain.Contains(block_to_test)) {
8586
// if the bestblock is not part of the mainchain, find the fork
8687
// and make sure we have all data down to the fork
87-
block_to_test = ::ChainActive().FindFork(block_to_test);
88+
block_to_test = active_chain.FindFork(block_to_test);
8889
}
89-
const CBlockIndex* block = ::ChainActive().Tip();
90+
const CBlockIndex* block = active_chain.Tip();
9091
prune_violation = true;
9192
// check backwards from the tip if we have all block data until we reach the indexes bestblock
9293
while (block_to_test && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
@@ -104,20 +105,20 @@ bool BaseIndex::Init()
104105
return true;
105106
}
106107

107-
static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
108+
static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev, CChain& chain) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
108109
{
109110
AssertLockHeld(cs_main);
110111

111112
if (!pindex_prev) {
112-
return ::ChainActive().Genesis();
113+
return chain.Genesis();
113114
}
114115

115-
const CBlockIndex* pindex = ::ChainActive().Next(pindex_prev);
116+
const CBlockIndex* pindex = chain.Next(pindex_prev);
116117
if (pindex) {
117118
return pindex;
118119
}
119120

120-
return ::ChainActive().Next(::ChainActive().FindFork(pindex_prev));
121+
return chain.Next(chain.FindFork(pindex_prev));
121122
}
122123

123124
void BaseIndex::ThreadSync()
@@ -140,7 +141,7 @@ void BaseIndex::ThreadSync()
140141

141142
{
142143
LOCK(cs_main);
143-
const CBlockIndex* pindex_next = NextSyncBlock(pindex);
144+
const CBlockIndex* pindex_next = NextSyncBlock(pindex, m_chainstate->m_chain);
144145
if (!pindex_next) {
145146
m_best_block_index = pindex;
146147
m_synced = true;
@@ -203,7 +204,7 @@ bool BaseIndex::Commit()
203204
bool BaseIndex::CommitInternal(CDBBatch& batch)
204205
{
205206
LOCK(cs_main);
206-
GetDB().WriteBestBlock(batch, ::ChainActive().GetLocator(m_best_block_index));
207+
GetDB().WriteBestBlock(batch, m_chainstate->m_chain.GetLocator(m_best_block_index));
207208
return true;
208209
}
209210

@@ -279,7 +280,7 @@ void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
279280
const CBlockIndex* locator_tip_index;
280281
{
281282
LOCK(cs_main);
282-
locator_tip_index = g_chainman.m_blockman.LookupBlockIndex(locator_tip_hash);
283+
locator_tip_index = m_chainstate->m_blockman.LookupBlockIndex(locator_tip_hash);
283284
}
284285

285286
if (!locator_tip_index) {
@@ -320,7 +321,7 @@ bool BaseIndex::BlockUntilSyncedToCurrentChain() const
320321
// Skip the queue-draining stuff if we know we're caught up with
321322
// ::ChainActive().Tip().
322323
LOCK(cs_main);
323-
const CBlockIndex* chain_tip = ::ChainActive().Tip();
324+
const CBlockIndex* chain_tip = m_chainstate->m_chain.Tip();
324325
const CBlockIndex* best_block_index = m_best_block_index.load();
325326
if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) {
326327
return true;
@@ -337,8 +338,10 @@ void BaseIndex::Interrupt()
337338
m_interrupt();
338339
}
339340

340-
bool BaseIndex::Start()
341+
bool BaseIndex::Start(CChainState& active_chainstate)
341342
{
343+
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
344+
m_chainstate = &active_chainstate;
342345
// Need to register this ValidationInterface before running Init(), so that
343346
// callbacks are not missed if Init sets m_synced to true.
344347
RegisterValidationInterface(this);

src/index/base.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <validationinterface.h>
1313

1414
class CBlockIndex;
15+
class CChainState;
1516

1617
struct IndexSummary {
1718
std::string name;
@@ -75,8 +76,9 @@ class BaseIndex : public CValidationInterface
7576
/// to a chain reorganization), the index must halt until Commit succeeds or else it could end up
7677
/// getting corrupted.
7778
bool Commit();
78-
7979
protected:
80+
CChainState* m_chainstate{nullptr};
81+
8082
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
8183

8284
void ChainStateFlushed(const CBlockLocator& locator) override;
@@ -117,7 +119,7 @@ class BaseIndex : public CValidationInterface
117119

118120
/// Start initializes the sync state and registers the instance as a
119121
/// ValidationInterface so that it stays in sync with blockchain updates.
120-
[[nodiscard]] bool Start();
122+
[[nodiscard]] bool Start(CChainState& active_chainstate);
121123

122124
/// Stops the instance from staying in sync with blockchain updates.
123125
void Stop();

src/index/coinstatsindex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ bool CoinStatsIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* n
266266

267267
{
268268
LOCK(cs_main);
269-
CBlockIndex* iter_tip{g_chainman.m_blockman.LookupBlockIndex(current_tip->GetBlockHash())};
269+
CBlockIndex* iter_tip{m_chainstate->m_blockman.LookupBlockIndex(current_tip->GetBlockHash())};
270270
const auto& consensus_params{Params().GetConsensus()};
271271

272272
do {

src/index/txindex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ bool TxIndex::Init()
204204
// Attempt to migrate txindex from the old database to the new one. Even if
205205
// chain_tip is null, the node could be reindexing and we still want to
206206
// delete txindex records in the old database.
207-
if (!m_db->MigrateData(*pblocktree, ::ChainActive().GetLocator())) {
207+
if (!m_db->MigrateData(*pblocktree, m_chainstate->m_chain.GetLocator())) {
208208
return false;
209209
}
210210

src/init.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,21 +1549,21 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15491549
// ********************************************************* Step 8: start indexers
15501550
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
15511551
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
1552-
if (!g_txindex->Start()) {
1552+
if (!g_txindex->Start(::ChainstateActive())) {
15531553
return false;
15541554
}
15551555
}
15561556

15571557
for (const auto& filter_type : g_enabled_filter_types) {
15581558
InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
1559-
if (!GetBlockFilterIndex(filter_type)->Start()) {
1559+
if (!GetBlockFilterIndex(filter_type)->Start(::ChainstateActive())) {
15601560
return false;
15611561
}
15621562
}
15631563

15641564
if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
15651565
g_coin_stats_index = std::make_unique<CoinStatsIndex>(/* cache size */ 0, false, fReindex);
1566-
if (!g_coin_stats_index->Start()) {
1566+
if (!g_coin_stats_index->Start(::ChainstateActive())) {
15671567
return false;
15681568
}
15691569
}

src/miner.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,21 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
3939
return nNewTime - nOldTime;
4040
}
4141

42-
void RegenerateCommitments(CBlock& block, CBlockIndex* prev_block)
42+
void RegenerateCommitments(CBlock& block, ChainstateManager& chainman)
4343
{
4444
CMutableTransaction tx{*block.vtx.at(0)};
4545
tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
4646
block.vtx.at(0) = MakeTransactionRef(tx);
4747

48-
WITH_LOCK(::cs_main, assert(g_chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock) == prev_block));
48+
CBlockIndex* prev_block;
49+
{
50+
// TODO: Temporary scope to check correctness of refactored code.
51+
// Should be removed manually after merge of
52+
// https://github.com/bitcoin/bitcoin/pull/20158
53+
LOCK(::cs_main);
54+
assert(std::addressof(g_chainman.m_blockman) == std::addressof(chainman.m_blockman));
55+
prev_block = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
56+
}
4957
GenerateCoinbaseCommitment(block, prev_block, Params().GetConsensus());
5058

5159
block.hashMerkleRoot = BlockMerkleRoot(block);

src/miner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,6 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned
203203
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
204204

205205
/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
206-
void RegenerateCommitments(CBlock& block, CBlockIndex* prev_block);
206+
void RegenerateCommitments(CBlock& block, ChainstateManager& chainman);
207207

208208
#endif // BITCOIN_MINER_H

src/rest.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,27 @@ static CTxMemPool* GetMemPool(const std::any& context, HTTPRequest* req)
107107
return node_context->mempool.get();
108108
}
109109

110+
/**
111+
* Get the node context chainstatemanager.
112+
*
113+
* @param[in] req The HTTP request, whose status code will be set if node
114+
* context chainstatemanager is not found.
115+
* @returns Pointer to the chainstatemanager or nullptr if none found.
116+
*/
117+
static ChainstateManager* GetChainman(const std::any& context, HTTPRequest* req)
118+
{
119+
auto node_context = util::AnyPtr<NodeContext>(context);
120+
if (!node_context || !node_context->chainman) {
121+
RESTERR(req, HTTP_INTERNAL_SERVER_ERROR,
122+
strprintf("%s:%d (%s)\n"
123+
"Internal bug detected: Chainman disabled or instance not found!\n"
124+
"You may report this issue here: %s\n",
125+
__FILE__, __LINE__, __func__, PACKAGE_BUGREPORT));
126+
return nullptr;
127+
}
128+
return node_context->chainman;
129+
}
130+
110131
static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
111132
{
112133
const std::string::size_type pos = strReq.rfind('.');
@@ -181,7 +202,9 @@ static bool rest_headers(const std::any& context,
181202
std::vector<const CBlockIndex *> headers;
182203
headers.reserve(count);
183204
{
184-
ChainstateManager& chainman = EnsureAnyChainman(context);
205+
ChainstateManager* maybe_chainman = GetChainman(context, req);
206+
if (!maybe_chainman) return false;
207+
ChainstateManager& chainman = *maybe_chainman;
185208
LOCK(cs_main);
186209
CChain& active_chain = chainman.ActiveChain();
187210
tip = active_chain.Tip();
@@ -252,7 +275,9 @@ static bool rest_block(const std::any& context,
252275
CBlockIndex* pblockindex = nullptr;
253276
CBlockIndex* tip = nullptr;
254277
{
255-
ChainstateManager& chainman = EnsureAnyChainman(context);
278+
ChainstateManager* maybe_chainman = GetChainman(context, req);
279+
if (!maybe_chainman) return false;
280+
ChainstateManager& chainman = *maybe_chainman;
256281
LOCK(cs_main);
257282
tip = chainman.ActiveChain().Tip();
258283
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
@@ -541,7 +566,9 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
541566
std::string bitmapStringRepresentation;
542567
std::vector<bool> hits;
543568
bitmap.resize((vOutPoints.size() + 7) / 8);
544-
ChainstateManager& chainman = EnsureAnyChainman(context);
569+
ChainstateManager* maybe_chainman = GetChainman(context, req);
570+
if (!maybe_chainman) return false;
571+
ChainstateManager& chainman = *maybe_chainman;
545572
{
546573
auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool& mempool) {
547574
for (const COutPoint& vOutPoint : vOutPoints) {
@@ -644,7 +671,9 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
644671

645672
CBlockIndex* pblockindex = nullptr;
646673
{
647-
ChainstateManager& chainman = EnsureAnyChainman(context);
674+
ChainstateManager* maybe_chainman = GetChainman(context, req);
675+
if (!maybe_chainman) return false;
676+
ChainstateManager& chainman = *maybe_chainman;
648677
LOCK(cs_main);
649678
const CChain& active_chain = chainman.ActiveChain();
650679
if (blockheight > active_chain.Height()) {

0 commit comments

Comments
 (0)