Skip to content

Commit 1e9694d

Browse files
1bf0bf4 merge bitcoin#24515: Only load BlockMan in BlockMan member functions (Kittywhiskers Van Gogh) 5c1eb67 merge bitcoin#24050: Give m_block_index ownership of CBlockIndexes (Kittywhiskers Van Gogh) c440304 merge bitcoin#22932: Add CBlockIndex lock annotations, guard nStatus/nFile/nDataPos/nUndoPos by cs_main (Kittywhiskers Van Gogh) e303a4e merge bitcoin#23974: Make blockstorage globals private members of BlockManager (Kittywhiskers Van Gogh) 301163c merge bitcoin#23581: Move BlockManager to node/blockstorage (Kittywhiskers Van Gogh) 732e871 merge bitcoin#23785: Move stuff to ChainstateManager (Kittywhiskers Van Gogh) b402fd5 merge bitcoin#23174: have LoadBlockIndex account for snapshot use (Kittywhiskers Van Gogh) a08f2f4 merge bitcoin#21526: UpdateTip/CheckBlockIndex assumeutxo support (Kittywhiskers Van Gogh) 472caa0 merge bitcoin#22371: Move pblocktree global to BlockManager (Kittywhiskers Van Gogh) d69ca83 merge bitcoin#21727: Move more stuff to blockstorage (Kittywhiskers Van Gogh) 6df927f chore: exclude underscore placeholder from shadowing linter warnings (Kittywhiskers Van Gogh) Pull request description: ## Additional Information * Dependent on #6078 * Dependent on #6074 * Dependent on #6083 * Dependent on #6119 * Dependency for #6138 * In [bitcoin#24050](bitcoin#24050), `BlockMap` is given ownership of the `CBlockIndex` instance contained within the `unordered_map`. The same has not been done for `PrevBlockMap` as `PrevBlockMap` is populated with `pprev` pointers and doing so seems to break validation logic. * Dash has a specific linter for all Dash-specific code present in Core. The introduction of `util/translation.h` into `validation.h` has caused the linter to trigger shadowing warnings due to a conflict between the common use of `_` as a placeholder/throwaway name ([source](https://github.com/dashpay/dash/blob/37e026a038a60313214e01b6aba029809ea7ad39/src/spork.cpp#L44)) and upstream's usage of it to process translatable strings ([source](https://github.com/dashpay/dash/blob/37e026a038a60313214e01b6aba029809ea7ad39/src/util/translation.h#L55-L62)). Neither C++17 nor C++20 have an _official_ placeholder/throwaway term or annotation for structured bindings (which cannot use `[[maybe_unused]` or `std::ignore`) but [P2169](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2169r4.pdf) is a proposal put forth to make it the official placeholder, in that light, the linter will silence shadowing warnings involving an underscore. ## Breaking Changes None expected ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)** - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation **(note: N/A)** - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK 1bf0bf4 (with one nit) knst: utACK 1bf0bf4 PastaPastaPasta: utACK 1bf0bf4 Tree-SHA512: 875fff34fe91916722f017526135697466e521d7179c473a5c0c444e3aa873369019b804dee9f5f795fc7ebed5c2481b5ce2d895b2950782a37de7b098157ad4
2 parents 5e6c86a + 1bf0bf4 commit 1e9694d

35 files changed

+1657
-1203
lines changed

src/Makefile.test_util.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ EXTRA_LIBRARIES += \
99

1010
TEST_UTIL_H = \
1111
test/util/blockfilter.h \
12+
test/util/chainstate.h \
1213
test/util/index.h \
1314
test/util/logging.h \
1415
test/util/mining.h \

src/chain.h

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <consensus/params.h>
1111
#include <flatfile.h>
1212
#include <primitives/block.h>
13+
#include <sync.h>
1314
#include <uint256.h>
1415

1516
#include <vector>
@@ -34,6 +35,8 @@ static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
3435
*/
3536
static constexpr int64_t MAX_BLOCK_TIME_GAP = 25 * 60;
3637

38+
extern RecursiveMutex cs_main;
39+
3740
class CBlockFileInfo
3841
{
3942
public:
@@ -124,6 +127,14 @@ enum BlockStatus: uint32_t {
124127
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
125128

126129
BLOCK_CONFLICT_CHAINLOCK = 128, //!< conflicts with chainlock system
130+
131+
/**
132+
* If set, this indicates that the block index entry is assumed-valid.
133+
* Certain diagnostics will be skipped in e.g. CheckBlockIndex().
134+
* It almost certainly means that the block's full validation is pending
135+
* on a background chainstate. See `doc/assumeutxo.md`.
136+
*/
137+
BLOCK_ASSUMED_VALID = 256,
127138
};
128139

129140
/** The block chain is a tree shaped structure starting with the
@@ -147,13 +158,13 @@ class CBlockIndex
147158
int nHeight{0};
148159

149160
//! Which # file this block is stored in (blk?????.dat)
150-
int nFile{0};
161+
int nFile GUARDED_BY(::cs_main){0};
151162

152163
//! Byte offset within blk?????.dat where this block's data is stored
153-
unsigned int nDataPos{0};
164+
unsigned int nDataPos GUARDED_BY(::cs_main){0};
154165

155166
//! Byte offset within rev?????.dat where this block's undo data is stored
156-
unsigned int nUndoPos{0};
167+
unsigned int nUndoPos GUARDED_BY(::cs_main){0};
157168

158169
//! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
159170
arith_uint256 nChainWork{};
@@ -181,7 +192,7 @@ class CBlockIndex
181192
//! load to avoid the block index being spuriously rewound.
182193
//! @sa NeedsRedownload
183194
//! @sa ActivateSnapshot
184-
uint32_t nStatus{0};
195+
uint32_t nStatus GUARDED_BY(::cs_main){0};
185196

186197
//! block header
187198
int32_t nVersion{0};
@@ -209,7 +220,9 @@ class CBlockIndex
209220
{
210221
}
211222

212-
FlatFilePos GetBlockPos() const {
223+
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
224+
{
225+
AssertLockHeld(::cs_main);
213226
FlatFilePos ret;
214227
if (nStatus & BLOCK_HAVE_DATA) {
215228
ret.nFile = nFile;
@@ -218,7 +231,9 @@ class CBlockIndex
218231
return ret;
219232
}
220233

221-
FlatFilePos GetUndoPos() const {
234+
FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
235+
{
236+
AssertLockHeld(::cs_main);
222237
FlatFilePos ret;
223238
if (nStatus & BLOCK_HAVE_UNDO) {
224239
ret.nFile = nFile;
@@ -284,21 +299,38 @@ class CBlockIndex
284299

285300
//! Check whether this block index entry is valid up to the passed validity level.
286301
bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
302+
EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
287303
{
304+
AssertLockHeld(::cs_main);
288305
assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
289306
if (nStatus & BLOCK_FAILED_MASK)
290307
return false;
291308
return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
292309
}
293310

311+
//! @returns true if the block is assumed-valid; this means it is queued to be
312+
//! validated by a background chainstate.
313+
bool IsAssumedValid() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
314+
{
315+
AssertLockHeld(::cs_main);
316+
return nStatus & BLOCK_ASSUMED_VALID;
317+
}
318+
294319
//! Raise the validity level of this block index entry.
295320
//! Returns true if the validity was changed.
296-
bool RaiseValidity(enum BlockStatus nUpTo)
321+
bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
297322
{
323+
AssertLockHeld(::cs_main);
298324
assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
299-
if (nStatus & BLOCK_FAILED_MASK)
300-
return false;
325+
if (nStatus & BLOCK_FAILED_MASK) return false;
326+
301327
if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
328+
// If this block had been marked assumed-valid and we're raising
329+
// its validity to a certain point, there is no longer an assumption.
330+
if (nStatus & BLOCK_ASSUMED_VALID && nUpTo >= BLOCK_VALID_SCRIPTS) {
331+
nStatus &= ~BLOCK_ASSUMED_VALID;
332+
}
333+
302334
nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
303335
return true;
304336
}
@@ -339,6 +371,7 @@ class CDiskBlockIndex : public CBlockIndex
339371

340372
SERIALIZE_METHODS(CDiskBlockIndex, obj)
341373
{
374+
LOCK(::cs_main);
342375
int _nVersion = s.GetVersion();
343376
if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
344377

src/index/base.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ bool BaseIndex::Init()
6464
if (locator.IsNull()) {
6565
m_best_block_index = nullptr;
6666
} else {
67-
m_best_block_index = m_chainstate->m_blockman.FindForkInGlobalIndex(active_chain, locator);
67+
m_best_block_index = m_chainstate->FindForkInGlobalIndex(locator);
6868
}
6969

7070
// Note: this will latch to true immediately if the user starts up with an empty

src/index/coinstatsindex.cpp

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

273273
{
274274
LOCK(cs_main);
275-
CBlockIndex* iter_tip{m_chainstate->m_blockman.LookupBlockIndex(current_tip->GetBlockHash())};
275+
const CBlockIndex* iter_tip{m_chainstate->m_blockman.LookupBlockIndex(current_tip->GetBlockHash())};
276276
const auto& consensus_params{Params().GetConsensus()};
277277

278278
do {

src/index/txindex.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <index/disktxpos.h>
66
#include <index/txindex.h>
7+
#include <node/blockstorage.h>
78
#include <node/ui_interface.h>
89
#include <shutdown.h>
910
#include <util/system.h>
@@ -203,7 +204,7 @@ bool TxIndex::Init()
203204
// Attempt to migrate txindex from the old database to the new one. Even if
204205
// chain_tip is null, the node could be reindexing and we still want to
205206
// delete txindex records in the old database.
206-
if (!m_db->MigrateData(*pblocktree, m_chainstate->m_chain.GetLocator())) {
207+
if (!m_db->MigrateData(*m_chainstate->m_blockman.m_block_tree_db, m_chainstate->m_chain.GetLocator())) {
207208
return false;
208209
}
209210

@@ -215,7 +216,9 @@ bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
215216
// Exclude genesis block transaction because outputs are not spendable.
216217
if (pindex->nHeight == 0) return true;
217218

218-
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
219+
CDiskTxPos pos{
220+
WITH_LOCK(::cs_main, return pindex->GetBlockPos()),
221+
GetSizeOfCompactSize(block.vtx.size())};
219222
std::vector<std::pair<uint256, CDiskTxPos>> vPos;
220223
vPos.reserve(block.vtx.size());
221224
for (const auto& tx : block.vtx) {

src/init.cpp

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ void PrepareShutdown(NodeContext& node)
338338
chainstate->ResetCoinsViews();
339339
}
340340
}
341-
pblocktree.reset();
342341
node.chain_helper.reset();
343342
if (node.mnhf_manager) {
344343
node.mnhf_manager->DisconnectManagers();
@@ -831,47 +830,6 @@ static void BlockNotifyGenesisWait(const CBlockIndex* pBlockIndex)
831830
}
832831
}
833832

834-
// If we're using -prune with -reindex, then delete block files that will be ignored by the
835-
// reindex. Since reindexing works by starting at block file 0 and looping until a blockfile
836-
// is missing, do the same here to delete any later block files after a gap. Also delete all
837-
// rev files since they'll be rewritten by the reindex anyway. This ensures that vinfoBlockFile
838-
// is in sync with what's actually on disk by the time we start downloading, so that pruning
839-
// works correctly.
840-
static void CleanupBlockRevFiles()
841-
{
842-
std::map<std::string, fs::path> mapBlockFiles;
843-
844-
// Glob all blk?????.dat and rev?????.dat files from the blocks directory.
845-
// Remove the rev files immediately and insert the blk file paths into an
846-
// ordered map keyed by block file index.
847-
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
848-
fs::path blocksdir = gArgs.GetBlocksDirPath();
849-
for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
850-
if (fs::is_regular_file(*it) &&
851-
it->path().filename().string().length() == 12 &&
852-
it->path().filename().string().substr(8,4) == ".dat")
853-
{
854-
if (it->path().filename().string().substr(0,3) == "blk")
855-
mapBlockFiles[it->path().filename().string().substr(3,5)] = it->path();
856-
else if (it->path().filename().string().substr(0,3) == "rev")
857-
remove(it->path());
858-
}
859-
}
860-
861-
// Remove all block files that aren't part of a contiguous set starting at
862-
// zero by walking the ordered map (keys are block file indices) by
863-
// keeping a separate counter. Once we hit a gap (or if 0 doesn't exist)
864-
// start removing block files.
865-
int nContigCounter = 0;
866-
for (const std::pair<const std::string, fs::path>& item : mapBlockFiles) {
867-
if (LocaleIndependentAtoi<int>(item.first) == nContigCounter) {
868-
nContigCounter++;
869-
continue;
870-
}
871-
remove(item.second);
872-
}
873-
}
874-
875833
#if HAVE_SYSTEM
876834
static void StartupNotify(const ArgsManager& args)
877835
{
@@ -1992,6 +1950,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
19921950

19931951
UnloadBlockIndex(node.mempool.get(), chainman);
19941952

1953+
auto& pblocktree{chainman.m_blockman.m_block_tree_db};
19951954
// new CBlockTreeDB tries to delete the existing file, which
19961955
// fails if it's still open from the previous loop. Close it first:
19971956
pblocktree.reset();

src/llmq/instantsend.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <index/txindex.h>
1717
#include <masternode/sync.h>
1818
#include <net_processing.h>
19+
#include <node/blockstorage.h>
1920
#include <spork.h>
2021
#include <txmempool.h>
2122
#include <util/irange.h>

src/miner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
5757
return nNewTime - nOldTime;
5858
}
5959

60-
BlockAssembler::Options::Options() {
60+
BlockAssembler::Options::Options()
61+
{
6162
blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
6263
nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
6364
}

src/net_processing.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3926,7 +3926,7 @@ void PeerManagerImpl::ProcessMessage(
39263926
LOCK(cs_main);
39273927

39283928
// Find the last block the caller has in the main chain
3929-
const CBlockIndex* pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.ActiveChain(), locator);
3929+
const CBlockIndex* pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
39303930

39313931
// Send the rest of the chain
39323932
if (pindex)
@@ -4046,7 +4046,7 @@ void PeerManagerImpl::ProcessMessage(
40464046
else
40474047
{
40484048
// Find the last block the caller has in the main chain
4049-
pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.ActiveChain(), locator);
4049+
pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
40504050
if (pindex)
40514051
pindex = m_chainman.ActiveChain().Next(pindex);
40524052
}

0 commit comments

Comments
 (0)