Skip to content

Commit 1b313ca

Browse files
author
MarcoFalke
committed
Merge bitcoin#19927: validation: Reduce direct g_chainman usage
72a1d5c validation: Remove review-only comments + assertions (Carl Dong) 3756853 docs: Move FindFilesToPrune{,Manual} doxygen comment (Carl Dong) 485899a style: Make FindFilesToPrune{,Manual} match style guide (Carl Dong) 3f5b5f3 validation: Move FindFilesToPrune{,Manual} to BlockManager (Carl Dong) f8d4975 validation: Move PruneOneBlockFile to BlockManager (Carl Dong) 74f73c7 validation: Pass in chainman to UnloadBlockIndex (Carl Dong) 4668ded validation: Move ~CMainCleanup logic to ~BlockManager (Carl Dong) Pull request description: This PR paves the way for de-globalizing `g_chainman` entirely by removing the usage of `g_chainman` in the following functions/methods: - `~CMainCleanup` - `CChainState::FlushStateToDisk` - `UnloadBlockIndex` The remaining direct uses of `g_chainman` are as follows: 1. In initialization codepaths: - `AppTests` - `AppInitMain` - `TestingSetup::TestingSetup` 2. `::ChainstateActive` 3. `LookupBlockIndex` - Note: `LookupBlockIndex` is used extensively throughout the codebase and require a much larger set of changes, therefore I've left it out of this initial PR ACKs for top commit: MarcoFalke: re-ACK 72a1d5c 👚 jnewbery: utACK 72a1d5c Tree-SHA512: 944a4fa8405eecf39706ff944375d6824373aaeea849d11473f08181eff26b12f70043a8348a5b08e6e9021b243b481842fbdfbc7c3140ca795fce3688b7f5c3
2 parents 43305e9 + 72a1d5c commit 1b313ca

File tree

6 files changed

+72
-69
lines changed

6 files changed

+72
-69
lines changed

src/init.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
15631563
chainman.m_total_coinstip_cache = nCoinCacheUsage;
15641564
chainman.m_total_coinsdb_cache = nCoinDBCache;
15651565

1566-
UnloadBlockIndex(node.mempool.get());
1566+
UnloadBlockIndex(node.mempool.get(), chainman);
15671567

15681568
// new CBlockTreeDB tries to delete the existing file, which
15691569
// fails if it's still open from the previous loop. Close it first:

src/qt/test/apptests.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,11 @@ void AppTests::appTests()
8484
// Reset global state to avoid interfering with later tests.
8585
LogInstance().DisconnectTestLogger();
8686
AbortShutdown();
87-
UnloadBlockIndex(/* mempool */ nullptr);
88-
WITH_LOCK(::cs_main, g_chainman.Reset());
87+
{
88+
LOCK(cs_main);
89+
UnloadBlockIndex(/* mempool */ nullptr, g_chainman);
90+
g_chainman.Reset();
91+
}
8992
}
9093

9194
//! Entry point for BitcoinGUI tests.

src/test/util/setup_common.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ TestingSetup::~TestingSetup()
187187
m_node.connman.reset();
188188
m_node.banman.reset();
189189
m_node.args = nullptr;
190-
UnloadBlockIndex(m_node.mempool.get());
190+
UnloadBlockIndex(m_node.mempool.get(), *m_node.chainman);
191191
m_node.mempool.reset();
192192
m_node.scheduler.reset();
193193
m_node.chainman->Reset();

src/validation.cpp

+29-57
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,6 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
198198

199199
std::unique_ptr<CBlockTreeDB> pblocktree;
200200

201-
// See definition for documentation
202-
static void FindFilesToPruneManual(ChainstateManager& chainman, std::set<int>& setFilesToPrune, int nManualPruneHeight);
203-
static void FindFilesToPrune(ChainstateManager& chainman, std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
204201
bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = nullptr);
205202
static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly = false);
206203
static FlatFileSeq BlockFileSeq();
@@ -2299,11 +2296,11 @@ bool CChainState::FlushStateToDisk(
22992296
if (nManualPruneHeight > 0) {
23002297
LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune (manual)", BCLog::BENCH);
23012298

2302-
FindFilesToPruneManual(g_chainman, setFilesToPrune, nManualPruneHeight);
2299+
m_blockman.FindFilesToPruneManual(setFilesToPrune, nManualPruneHeight, m_chain.Height());
23032300
} else {
23042301
LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune", BCLog::BENCH);
23052302

2306-
FindFilesToPrune(g_chainman, setFilesToPrune, chainparams.PruneAfterHeight());
2303+
m_blockman.FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight(), m_chain.Height(), IsInitialBlockDownload());
23072304
fCheckForPruning = false;
23082305
}
23092306
if (!setFilesToPrune.empty()) {
@@ -3909,12 +3906,12 @@ uint64_t CalculateCurrentUsage()
39093906
return retval;
39103907
}
39113908

3912-
void ChainstateManager::PruneOneBlockFile(const int fileNumber)
3909+
void BlockManager::PruneOneBlockFile(const int fileNumber)
39133910
{
39143911
AssertLockHeld(cs_main);
39153912
LOCK(cs_LastBlockFile);
39163913

3917-
for (const auto& entry : m_blockman.m_block_index) {
3914+
for (const auto& entry : m_block_index) {
39183915
CBlockIndex* pindex = entry.second;
39193916
if (pindex->nFile == fileNumber) {
39203917
pindex->nStatus &= ~BLOCK_HAVE_DATA;
@@ -3928,12 +3925,12 @@ void ChainstateManager::PruneOneBlockFile(const int fileNumber)
39283925
// to be downloaded again in order to consider its chain, at which
39293926
// point it would be considered as a candidate for
39303927
// m_blocks_unlinked or setBlockIndexCandidates.
3931-
auto range = m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
3928+
auto range = m_blocks_unlinked.equal_range(pindex->pprev);
39323929
while (range.first != range.second) {
39333930
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
39343931
range.first++;
39353932
if (_it->second == pindex) {
3936-
m_blockman.m_blocks_unlinked.erase(_it);
3933+
m_blocks_unlinked.erase(_it);
39373934
}
39383935
}
39393936
}
@@ -3954,22 +3951,23 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
39543951
}
39553952
}
39563953

3957-
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
3958-
static void FindFilesToPruneManual(ChainstateManager& chainman, std::set<int>& setFilesToPrune, int nManualPruneHeight)
3954+
void BlockManager::FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight, int chain_tip_height)
39593955
{
39603956
assert(fPruneMode && nManualPruneHeight > 0);
39613957

39623958
LOCK2(cs_main, cs_LastBlockFile);
3963-
if (::ChainActive().Tip() == nullptr)
3959+
if (chain_tip_height < 0) {
39643960
return;
3961+
}
39653962

39663963
// last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip)
3967-
unsigned int nLastBlockWeCanPrune = std::min((unsigned)nManualPruneHeight, ::ChainActive().Tip()->nHeight - MIN_BLOCKS_TO_KEEP);
3968-
int count=0;
3964+
unsigned int nLastBlockWeCanPrune = std::min((unsigned)nManualPruneHeight, chain_tip_height - MIN_BLOCKS_TO_KEEP);
3965+
int count = 0;
39693966
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
3970-
if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
3967+
if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) {
39713968
continue;
3972-
chainman.PruneOneBlockFile(fileNumber);
3969+
}
3970+
PruneOneBlockFile(fileNumber);
39733971
setFilesToPrune.insert(fileNumber);
39743972
count++;
39753973
}
@@ -3987,64 +3985,52 @@ void PruneBlockFilesManual(int nManualPruneHeight)
39873985
}
39883986
}
39893987

3990-
/**
3991-
* Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target.
3992-
* The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new
3993-
* space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex
3994-
* (which in this case means the blockchain must be re-downloaded.)
3995-
*
3996-
* Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set.
3997-
* Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.)
3998-
* Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on regtest).
3999-
* Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip.
4000-
* The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files.
4001-
* A db flag records the fact that at least some block files have been pruned.
4002-
*
4003-
* @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned
4004-
*/
4005-
static void FindFilesToPrune(ChainstateManager& chainman, std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
3988+
void BlockManager::FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight, int chain_tip_height, bool is_ibd)
40063989
{
40073990
LOCK2(cs_main, cs_LastBlockFile);
4008-
if (::ChainActive().Tip() == nullptr || nPruneTarget == 0) {
3991+
if (chain_tip_height < 0 || nPruneTarget == 0) {
40093992
return;
40103993
}
4011-
if ((uint64_t)::ChainActive().Tip()->nHeight <= nPruneAfterHeight) {
3994+
if ((uint64_t)chain_tip_height <= nPruneAfterHeight) {
40123995
return;
40133996
}
40143997

4015-
unsigned int nLastBlockWeCanPrune = ::ChainActive().Tip()->nHeight - MIN_BLOCKS_TO_KEEP;
3998+
unsigned int nLastBlockWeCanPrune = chain_tip_height - MIN_BLOCKS_TO_KEEP;
40163999
uint64_t nCurrentUsage = CalculateCurrentUsage();
40174000
// We don't check to prune until after we've allocated new space for files
40184001
// So we should leave a buffer under our target to account for another allocation
40194002
// before the next pruning.
40204003
uint64_t nBuffer = BLOCKFILE_CHUNK_SIZE + UNDOFILE_CHUNK_SIZE;
40214004
uint64_t nBytesToPrune;
4022-
int count=0;
4005+
int count = 0;
40234006

40244007
if (nCurrentUsage + nBuffer >= nPruneTarget) {
40254008
// On a prune event, the chainstate DB is flushed.
40264009
// To avoid excessive prune events negating the benefit of high dbcache
40274010
// values, we should not prune too rapidly.
40284011
// So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon.
4029-
if (::ChainstateActive().IsInitialBlockDownload()) {
4012+
if (is_ibd) {
40304013
// Since this is only relevant during IBD, we use a fixed 10%
40314014
nBuffer += nPruneTarget / 10;
40324015
}
40334016

40344017
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
40354018
nBytesToPrune = vinfoBlockFile[fileNumber].nSize + vinfoBlockFile[fileNumber].nUndoSize;
40364019

4037-
if (vinfoBlockFile[fileNumber].nSize == 0)
4020+
if (vinfoBlockFile[fileNumber].nSize == 0) {
40384021
continue;
4022+
}
40394023

4040-
if (nCurrentUsage + nBuffer < nPruneTarget) // are we below our target?
4024+
if (nCurrentUsage + nBuffer < nPruneTarget) { // are we below our target?
40414025
break;
4026+
}
40424027

40434028
// don't prune files that could have a block within MIN_BLOCKS_TO_KEEP of the main chain's tip but keep scanning
4044-
if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
4029+
if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) {
40454030
continue;
4031+
}
40464032

4047-
chainman.PruneOneBlockFile(fileNumber);
4033+
PruneOneBlockFile(fileNumber);
40484034
// Queue up the files for removal
40494035
setFilesToPrune.insert(fileNumber);
40504036
nCurrentUsage -= nBytesToPrune;
@@ -4602,10 +4588,10 @@ void CChainState::UnloadBlockIndex() {
46024588
// May NOT be used after any connections are up as much
46034589
// of the peer-processing logic assumes a consistent
46044590
// block index state
4605-
void UnloadBlockIndex(CTxMemPool* mempool)
4591+
void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman)
46064592
{
46074593
LOCK(cs_main);
4608-
g_chainman.Unload();
4594+
chainman.Unload();
46094595
pindexBestInvalid = nullptr;
46104596
pindexBestHeader = nullptr;
46114597
if (mempool) mempool->clear();
@@ -5220,20 +5206,6 @@ double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pin
52205206
return std::min<double>(pindex->nChainTx / fTxTotal, 1.0);
52215207
}
52225208

5223-
class CMainCleanup
5224-
{
5225-
public:
5226-
CMainCleanup() {}
5227-
~CMainCleanup() {
5228-
// block headers
5229-
BlockMap::iterator it1 = g_chainman.BlockIndex().begin();
5230-
for (; it1 != g_chainman.BlockIndex().end(); it1++)
5231-
delete (*it1).second;
5232-
g_chainman.BlockIndex().clear();
5233-
}
5234-
};
5235-
static CMainCleanup instance_of_cmaincleanup;
5236-
52375209
Optional<uint256> ChainstateManager::SnapshotBlockhash() const {
52385210
if (m_active_chainstate != nullptr) {
52395211
// If a snapshot chainstate exists, it will always be our active.

src/validation.h

+33-5
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ void LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi
157157
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
158158
bool LoadGenesisBlock(const CChainParams& chainparams);
159159
/** Unload database information */
160-
void UnloadBlockIndex(CTxMemPool* mempool);
160+
void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman);
161161
/** Run an instance of the script checking thread */
162162
void ThreadScriptCheck(int worker_num);
163163
/**
@@ -352,7 +352,31 @@ struct CBlockIndexWorkComparator
352352
* This data is used mostly in `CChainState` - information about, e.g.,
353353
* candidate tips is not maintained here.
354354
*/
355-
class BlockManager {
355+
class BlockManager
356+
{
357+
friend CChainState;
358+
359+
private:
360+
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
361+
void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight, int chain_tip_height);
362+
363+
/**
364+
* Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target.
365+
* The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new
366+
* space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex
367+
* (which in this case means the blockchain must be re-downloaded.)
368+
*
369+
* Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set.
370+
* Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.)
371+
* Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on regtest).
372+
* Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip.
373+
* The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files.
374+
* A db flag records the fact that at least some block files have been pruned.
375+
*
376+
* @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned
377+
*/
378+
void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight, int chain_tip_height, bool is_ibd);
379+
356380
public:
357381
BlockMap m_block_index GUARDED_BY(cs_main);
358382

@@ -403,6 +427,9 @@ class BlockManager {
403427
/** Create a new block index entry for a given block hash */
404428
CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
405429

430+
//! Mark one block file as pruned (modify associated database entries)
431+
void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
432+
406433
/**
407434
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
408435
* that it doesn't descend from an invalid block, and then add it to m_block_index.
@@ -412,6 +439,10 @@ class BlockManager {
412439
BlockValidationState& state,
413440
const CChainParams& chainparams,
414441
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
442+
443+
~BlockManager() {
444+
Unload();
445+
}
415446
};
416447

417448
/**
@@ -895,9 +926,6 @@ class ChainstateManager
895926
*/
896927
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
897928

898-
//! Mark one block file as pruned (modify associated database entries)
899-
void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
900-
901929
//! Load the block tree and coins database from disk, initializing state if we're running with -reindex
902930
bool LoadBlockIndex(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
903931

src/wallet/test/wallet_tests.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
126126
// Prune the older block file.
127127
{
128128
LOCK(cs_main);
129-
Assert(m_node.chainman)->PruneOneBlockFile(oldTip->GetBlockPos().nFile);
129+
Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(oldTip->GetBlockPos().nFile);
130130
}
131131
UnlinkPrunedFiles({oldTip->GetBlockPos().nFile});
132132

@@ -152,7 +152,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
152152
// Prune the remaining block file.
153153
{
154154
LOCK(cs_main);
155-
Assert(m_node.chainman)->PruneOneBlockFile(newTip->GetBlockPos().nFile);
155+
Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(newTip->GetBlockPos().nFile);
156156
}
157157
UnlinkPrunedFiles({newTip->GetBlockPos().nFile});
158158

@@ -189,7 +189,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
189189
// Prune the older block file.
190190
{
191191
LOCK(cs_main);
192-
Assert(m_node.chainman)->PruneOneBlockFile(oldTip->GetBlockPos().nFile);
192+
Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(oldTip->GetBlockPos().nFile);
193193
}
194194
UnlinkPrunedFiles({oldTip->GetBlockPos().nFile});
195195

0 commit comments

Comments
 (0)