Skip to content

Commit 793e0ff

Browse files
author
MarcoFalke
committed
Merge #18698: Make g_chainman internal to validation
fab6b9d validation: Mark g_chainman DEPRECATED (MarcoFalke) fa1d97b validation: Make ProcessNewBlock*() members of ChainstateManager (MarcoFalke) fa24d49 validation: Make PruneOneBlockFile() a member of ChainstateManager (MarcoFalke) fa84b1c validation: Make LoadBlockIndex() a member of ChainstateManager (MarcoFalke) fa05fdf net: Pass chainman into PeerLogicValidation (MarcoFalke) fa7b626 node: Add chainman alias for g_chainman (MarcoFalke) Pull request description: The global `g_chainman` has recently been introduced in #17737. The chainstate manager is primarily needed for the assumeutxo feature, but it can also simplify testing in the future. The goal of this pull is to make the global chainstate manager internal to validation, so that all external code does not depend on globals and that unit or fuzz tests can pass in their (potentially mocked) chainstate manager. I suggest reviewing the pull request commit-by-commit. It should be relatively straightforward refactoring that does not change behavior at all. ACKs for top commit: ryanofsky: Code review ACK fab6b9d. Had to be rebased but still looks good Tree-SHA512: dcbf114aeef4f8320d466369769f22ce4dd8f46a846870354df176c3de9ff17c64630fbd777e7121d7470d7a8564ed8d37b77168746e8df7489c6877e55d7b4f
2 parents 492cdc5 + fab6b9d commit 793e0ff

17 files changed

+161
-134
lines changed

src/init.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,9 @@ void Shutdown(NodeContext& node)
244244
}
245245

246246
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
247-
{
247+
if (node.chainman) {
248248
LOCK(cs_main);
249-
for (CChainState* chainstate : g_chainman.GetAll()) {
249+
for (CChainState* chainstate : node.chainman->GetAll()) {
250250
if (chainstate->CanFlushToDisk()) {
251251
chainstate->ForceFlushStateToDisk();
252252
}
@@ -271,9 +271,9 @@ void Shutdown(NodeContext& node)
271271
// up with our current chain to avoid any strange pruning edge cases and make
272272
// next startup faster by avoiding rescan.
273273

274-
{
274+
if (node.chainman) {
275275
LOCK(cs_main);
276-
for (CChainState* chainstate : g_chainman.GetAll()) {
276+
for (CChainState* chainstate : node.chainman->GetAll()) {
277277
if (chainstate->CanFlushToDisk()) {
278278
chainstate->ForceFlushStateToDisk();
279279
chainstate->ResetCoinsViews();
@@ -299,7 +299,8 @@ void Shutdown(NodeContext& node)
299299
globalVerifyHandle.reset();
300300
ECC_Stop();
301301
node.args = nullptr;
302-
if (node.mempool) node.mempool = nullptr;
302+
node.mempool = nullptr;
303+
node.chainman = nullptr;
303304
node.scheduler.reset();
304305

305306
try {
@@ -689,7 +690,7 @@ static void CleanupBlockRevFiles()
689690
}
690691
}
691692

692-
static void ThreadImport(std::vector<fs::path> vImportFiles)
693+
static void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles)
693694
{
694695
const CChainParams& chainparams = Params();
695696
util::ThreadRename("loadblk");
@@ -741,9 +742,9 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
741742
// scan for better chains in the block chain database, that are not yet connected in the active best chain
742743

743744
// We can't hold cs_main during ActivateBestChain even though we're accessing
744-
// the g_chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
745+
// the chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
745746
// the relevant pointers before the ABC call.
746-
for (CChainState* chainstate : WITH_LOCK(::cs_main, return g_chainman.GetAll())) {
747+
for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
747748
BlockValidationState state;
748749
if (!chainstate->ActivateBestChain(state, chainparams, nullptr)) {
749750
LogPrintf("Failed to connect best block (%s)\n", state.ToString());
@@ -1377,8 +1378,11 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
13771378
// which are all started after this, may use it from the node context.
13781379
assert(!node.mempool);
13791380
node.mempool = &::mempool;
1381+
assert(!node.chainman);
1382+
node.chainman = &g_chainman;
1383+
ChainstateManager& chainman = EnsureChainman(node);
13801384

1381-
node.peer_logic.reset(new PeerLogicValidation(node.connman.get(), node.banman.get(), *node.scheduler, *node.mempool));
1385+
node.peer_logic.reset(new PeerLogicValidation(node.connman.get(), node.banman.get(), *node.scheduler, *node.chainman, *node.mempool));
13821386
RegisterValidationInterface(node.peer_logic.get());
13831387

13841388
// sanitize comments per BIP-0014, format user agent and check total size
@@ -1557,7 +1561,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
15571561
const int64_t load_block_index_start_time = GetTimeMillis();
15581562
try {
15591563
LOCK(cs_main);
1560-
g_chainman.InitializeChainstate();
1564+
chainman.InitializeChainstate();
15611565
UnloadBlockIndex();
15621566

15631567
// new CBlockTreeDB tries to delete the existing file, which
@@ -1578,7 +1582,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
15781582
// block file from disk.
15791583
// Note that it also sets fReindex based on the disk flag!
15801584
// From here on out fReindex and fReset mean something different!
1581-
if (!LoadBlockIndex(chainparams)) {
1585+
if (!chainman.LoadBlockIndex(chainparams)) {
15821586
if (ShutdownRequested()) break;
15831587
strLoadError = _("Error loading block database");
15841588
break;
@@ -1612,7 +1616,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
16121616

16131617
bool failed_chainstate_init = false;
16141618

1615-
for (CChainState* chainstate : g_chainman.GetAll()) {
1619+
for (CChainState* chainstate : chainman.GetAll()) {
16161620
LogPrintf("Initializing chainstate %s\n", chainstate->ToString());
16171621
chainstate->InitCoinsDB(
16181622
/* cache_size_bytes */ nCoinDBCache,
@@ -1667,7 +1671,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
16671671
bool failed_rewind{false};
16681672
// Can't hold cs_main while calling RewindBlockIndex, so retrieve the relevant
16691673
// chainstates beforehand.
1670-
for (CChainState* chainstate : WITH_LOCK(::cs_main, return g_chainman.GetAll())) {
1674+
for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
16711675
if (!fReset) {
16721676
// Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
16731677
// It both disconnects blocks based on the chainstate, and drops block data in
@@ -1692,7 +1696,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
16921696
try {
16931697
LOCK(cs_main);
16941698

1695-
for (CChainState* chainstate : g_chainman.GetAll()) {
1699+
for (CChainState* chainstate : chainman.GetAll()) {
16961700
if (!is_coinsview_empty(chainstate)) {
16971701
uiInterface.InitMessage(_("Verifying blocks...").translated);
16981702
if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
@@ -1798,7 +1802,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
17981802
nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
17991803
if (!fReindex) {
18001804
LOCK(cs_main);
1801-
for (CChainState* chainstate : g_chainman.GetAll()) {
1805+
for (CChainState* chainstate : chainman.GetAll()) {
18021806
uiInterface.InitMessage(_("Pruning blockstore...").translated);
18031807
chainstate->PruneAndFlush();
18041808
}
@@ -1841,7 +1845,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
18411845
vImportFiles.push_back(strFile);
18421846
}
18431847

1844-
threadGroup.create_thread(std::bind(&ThreadImport, vImportFiles));
1848+
threadGroup.create_thread([=, &chainman] { ThreadImport(chainman, vImportFiles); });
18451849

18461850
// Wait for genesis block to be processed
18471851
{

src/net_processing.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,9 +1153,10 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para
11531153
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
11541154
}
11551155

1156-
PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler& scheduler, CTxMemPool& pool)
1156+
PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool)
11571157
: connman(connmanIn),
11581158
m_banman(banman),
1159+
m_chainman(chainman),
11591160
m_mempool(pool),
11601161
m_stale_tip_check_time(0)
11611162
{
@@ -1738,7 +1739,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
17381739
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
17391740
}
17401741

1741-
bool static ProcessHeadersMessage(CNode* pfrom, CConnman* connman, CTxMemPool& mempool, const std::vector<CBlockHeader>& headers, const CChainParams& chainparams, bool via_compact_block)
1742+
bool static ProcessHeadersMessage(CNode* pfrom, CConnman* connman, ChainstateManager& chainman, CTxMemPool& mempool, const std::vector<CBlockHeader>& headers, const CChainParams& chainparams, bool via_compact_block)
17421743
{
17431744
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
17441745
size_t nCount = headers.size();
@@ -1798,7 +1799,7 @@ bool static ProcessHeadersMessage(CNode* pfrom, CConnman* connman, CTxMemPool& m
17981799
}
17991800

18001801
BlockValidationState state;
1801-
if (!ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast)) {
1802+
if (!chainman.ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast)) {
18021803
if (state.IsInvalid()) {
18031804
MaybePunishNodeForBlock(pfrom->GetId(), state, via_compact_block, "invalid header received");
18041805
return false;
@@ -2081,7 +2082,7 @@ static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainPa
20812082
connman->PushMessage(pfrom, std::move(msg));
20822083
}
20832084

2084-
bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc)
2085+
bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, ChainstateManager& chainman, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc)
20852086
{
20862087
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom->GetId());
20872088
if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0)
@@ -2848,7 +2849,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
28482849

28492850
const CBlockIndex *pindex = nullptr;
28502851
BlockValidationState state;
2851-
if (!ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) {
2852+
if (!chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) {
28522853
if (state.IsInvalid()) {
28532854
MaybePunishNodeForBlock(pfrom->GetId(), state, /*via_compact_block*/ true, "invalid header via cmpctblock");
28542855
return true;
@@ -2992,15 +2993,15 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
29922993
} // cs_main
29932994

29942995
if (fProcessBLOCKTXN)
2995-
return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, mempool, connman, banman, interruptMsgProc);
2996+
return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, chainman, mempool, connman, banman, interruptMsgProc);
29962997

29972998
if (fRevertToHeaderProcessing) {
29982999
// Headers received from HB compact block peers are permitted to be
29993000
// relayed before full validation (see BIP 152), so we don't want to disconnect
30003001
// the peer if the header turns out to be for an invalid block.
30013002
// Note that if a peer tries to build on an invalid chain, that
30023003
// will be detected and the peer will be banned.
3003-
return ProcessHeadersMessage(pfrom, connman, mempool, {cmpctblock.header}, chainparams, /*via_compact_block=*/true);
3004+
return ProcessHeadersMessage(pfrom, connman, chainman, mempool, {cmpctblock.header}, chainparams, /*via_compact_block=*/true);
30043005
}
30053006

30063007
if (fBlockReconstructed) {
@@ -3020,7 +3021,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
30203021
// we have a chain with at least nMinimumChainWork), and we ignore
30213022
// compact blocks with less work than our tip, it is safe to treat
30223023
// reconstructed compact blocks as having been requested.
3023-
ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock);
3024+
chainman.ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock);
30243025
if (fNewBlock) {
30253026
pfrom->nLastBlockTime = GetTime();
30263027
} else {
@@ -3110,7 +3111,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
31103111
// disk-space attacks), but this should be safe due to the
31113112
// protections in the compact block handler -- see related comment
31123113
// in compact block optimistic reconstruction handling.
3113-
ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock);
3114+
chainman.ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock);
31143115
if (fNewBlock) {
31153116
pfrom->nLastBlockTime = GetTime();
31163117
} else {
@@ -3144,7 +3145,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
31443145
ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
31453146
}
31463147

3147-
return ProcessHeadersMessage(pfrom, connman, mempool, headers, chainparams, /*via_compact_block=*/false);
3148+
return ProcessHeadersMessage(pfrom, connman, chainman, mempool, headers, chainparams, /*via_compact_block=*/false);
31483149
}
31493150

31503151
if (msg_type == NetMsgType::BLOCK)
@@ -3173,7 +3174,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
31733174
mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true));
31743175
}
31753176
bool fNewBlock = false;
3176-
ProcessNewBlock(chainparams, pblock, forceProcessing, &fNewBlock);
3177+
chainman.ProcessNewBlock(chainparams, pblock, forceProcessing, &fNewBlock);
31773178
if (fNewBlock) {
31783179
pfrom->nLastBlockTime = GetTime();
31793180
} else {
@@ -3534,7 +3535,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
35343535
bool fRet = false;
35353536
try
35363537
{
3537-
fRet = ProcessMessage(pfrom, msg_type, vRecv, msg.m_time, chainparams, m_mempool, connman, m_banman, interruptMsgProc);
3538+
fRet = ProcessMessage(pfrom, msg_type, vRecv, msg.m_time, chainparams, m_chainman, m_mempool, connman, m_banman, interruptMsgProc);
35383539
if (interruptMsgProc)
35393540
return false;
35403541
if (!pfrom->vRecvGetData.empty())

src/net_processing.h

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

1414
class CTxMemPool;
15+
class ChainstateManager;
1516

1617
extern RecursiveMutex cs_main;
1718
extern RecursiveMutex g_cs_orphans;
@@ -27,12 +28,13 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI
2728
private:
2829
CConnman* const connman;
2930
BanMan* const m_banman;
31+
ChainstateManager& m_chainman;
3032
CTxMemPool& m_mempool;
3133

3234
bool CheckIfBanned(CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
3335

3436
public:
35-
PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler& scheduler, CTxMemPool& pool);
37+
PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool);
3638

3739
/**
3840
* Overridden from CValidationInterface.

src/node/context.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef BITCOIN_NODE_CONTEXT_H
66
#define BITCOIN_NODE_CONTEXT_H
77

8+
#include <cassert>
89
#include <memory>
910
#include <vector>
1011

@@ -13,6 +14,7 @@ class BanMan;
1314
class CConnman;
1415
class CScheduler;
1516
class CTxMemPool;
17+
class ChainstateManager;
1618
class PeerLogicValidation;
1719
namespace interfaces {
1820
class Chain;
@@ -33,6 +35,7 @@ struct NodeContext {
3335
std::unique_ptr<CConnman> connman;
3436
CTxMemPool* mempool{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
3537
std::unique_ptr<PeerLogicValidation> peer_logic;
38+
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
3639
std::unique_ptr<BanMan> banman;
3740
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
3841
std::unique_ptr<interfaces::Chain> chain;
@@ -46,4 +49,10 @@ struct NodeContext {
4649
~NodeContext();
4750
};
4851

52+
inline ChainstateManager& EnsureChainman(const NodeContext& node)
53+
{
54+
assert(node.chainman);
55+
return *node.chainman;
56+
}
57+
4958
#endif // BITCOIN_NODE_CONTEXT_H

src/rpc/blockchain.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ CTxMemPool& EnsureMemPool(const util::Ref& context)
7171
return *node.mempool;
7272
}
7373

74+
ChainstateManager& EnsureChainman(const util::Ref& context)
75+
{
76+
NodeContext& node = EnsureNodeContext(context);
77+
return EnsureChainman(node);
78+
}
79+
7480
/* Calculate the difficulty for a given block index.
7581
*/
7682
double GetDifficulty(const CBlockIndex* blockindex)

src/rpc/blockchain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern RecursiveMutex cs_main;
1616
class CBlock;
1717
class CBlockIndex;
1818
class CTxMemPool;
19+
class ChainstateManager;
1920
class UniValue;
2021
struct NodeContext;
2122
namespace util {
@@ -52,5 +53,6 @@ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES],
5253

5354
NodeContext& EnsureNodeContext(const util::Ref& context);
5455
CTxMemPool& EnsureMemPool(const util::Ref& context);
56+
ChainstateManager& EnsureChainman(const util::Ref& context);
5557

5658
#endif

0 commit comments

Comments
 (0)