Skip to content

Instantly share code, notes, and snippets.

@jamesob
Created July 3, 2023 20:24
Show Gist options
  • Save jamesob/8535a4b81fc29e890ce2eff9a0fb2f1d to your computer and use it in GitHub Desktop.
Save jamesob/8535a4b81fc29e890ce2eff9a0fb2f1d to your computer and use it in GitHub Desktop.
--- /home/james/.ackr/by-date/2023-06-21.27746.sdaftuar.rework_validation_logic.1/base.diff 2023-06-21 11:17:23.507892496 -0400
+++ /home/james/.ackr/by-date/2023-07-03.27746.sdaftuar.rework_validation_logic.3/base.diff 2023-07-03 13:52:58.475417323 -0400
@@ -76,23 +76,10 @@
BLOCK_ASSUMED_VALID = 256,
};
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
-index 1368ae6f6d..b68bbf98c3 100644
+index 1368ae6f6d..09368968b2 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
-@@ -249,6 +249,12 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
- return pindex;
- }
-
-+void BlockManager::AddDirty(CBlockIndex *pindex)
-+{
-+ AssertLockHeld(cs_main);
-+ m_dirty_blockindex.insert(pindex);
-+}
-+
- bool BlockManager::LoadBlockIndex()
- {
- if (!m_block_tree_db->LoadBlockIndexGuts(GetConsensus(), [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) {
-@@ -604,7 +610,7 @@ fs::path BlockManager::GetBlockPosFilename(const FlatFilePos& pos) const
+@@ -604,7 +604,7 @@ fs::path BlockManager::GetBlockPosFilename(const FlatFilePos& pos) const
return BlockFileSeq().FileName(pos);
}
@@ -101,7 +88,7 @@
{
LOCK(cs_LastBlockFile);
-@@ -630,7 +636,7 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
+@@ -630,7 +630,7 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
// when the undo file is keeping up with the block file, we want to flush it explicitly
// when it is lagging behind (more blocks arrive than are being connected), we let the
// undo block write case handle it
@@ -110,7 +97,7 @@
nFile++;
if (m_blockfile_info.size() <= nFile) {
m_blockfile_info.resize(nFile + 1);
-@@ -646,6 +652,7 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
+@@ -646,6 +646,7 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
}
FlushBlockFile(!fKnown, finalize_undo);
m_last_blockfile = nFile;
@@ -118,7 +105,7 @@
}
m_blockfile_info[nFile].AddBlock(nHeight, nTime);
-@@ -734,8 +741,9 @@ bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValid
+@@ -734,8 +735,9 @@ bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValid
// the FindBlockPos function
if (_pos.nFile < m_last_blockfile && static_cast<uint32_t>(block.nHeight) == m_blockfile_info[_pos.nFile].nHeightLast) {
FlushUndoFile(_pos.nFile, true);
@@ -129,7 +116,7 @@
// update nUndoPos in block index
block.nUndoPos = _pos.nPos;
block.nStatus |= BLOCK_HAVE_UNDO;
-@@ -824,7 +832,7 @@ bool BlockManager::ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatF
+@@ -824,7 +826,7 @@ bool BlockManager::ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatF
return true;
}
@@ -138,7 +125,7 @@
{
unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
FlatFilePos blockPos;
-@@ -837,7 +845,7 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CCha
+@@ -837,7 +839,7 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CCha
// we add BLOCK_SERIALIZATION_HEADER_SIZE only for new blocks since they will have the serialization header added when written to disk.
nBlockSize += static_cast<unsigned int>(BLOCK_SERIALIZATION_HEADER_SIZE);
}
@@ -147,7 +134,7 @@
error("%s: FindBlockPos failed", __func__);
return FlatFilePos();
}
-@@ -891,7 +899,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
+@@ -891,7 +893,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
break; // This error is logged in OpenBlockFile
}
LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
@@ -156,7 +143,7 @@
if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exit %s\n", __func__);
return;
-@@ -910,7 +918,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
+@@ -910,7 +912,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
FILE* file = fsbridge::fopen(path, "rb");
if (file) {
LogPrintf("Importing blocks file %s...\n", fs::PathToString(path));
@@ -166,7 +153,7 @@
LogPrintf("Shutdown requested. Exit %s\n", __func__);
return;
diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h
-index a1ebb0df0a..b77ebf354c 100644
+index a1ebb0df0a..e97603e64f 100644
--- a/src/node/blockstorage.h
+++ b/src/node/blockstorage.h
@@ -24,7 +24,6 @@ class BlockValidationState;
@@ -195,7 +182,7 @@
+ // data has been written. Block data is written to block files in download
+ // order, but is written to undo files in validation order, which is
+ // usually in order by height. To avoid wasting disk space, undo files will
-+ // be will trimmed whenever the corresponding block file is finalized and
++ // be trimmed whenever the corresponding block file is finalized and
+ // the height of the highest block written to the block file equals the
+ // height of the highest block written to the undo file. This is a
+ // heuristic and can sometimes preemptively trim undo files that will write
@@ -206,17 +193,7 @@
/** Global flag to indicate we should check to see if there are
* block/undo files that should be deleted. Set on startup
* or if we allocate more file space when we're in prune mode
-@@ -185,6 +197,9 @@ public:
- /** Create a new block index entry for a given block hash */
- CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-
-+ /** Add a block index to dirty list */
-+ void AddDirty(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-+
- //! Mark one block file as pruned (modify associated database entries)
- void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-
-@@ -198,7 +213,7 @@ public:
+@@ -198,7 +210,7 @@ public:
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** Store block on disk. If dbp is not nullptr, then it provides the known position of the block within a block file on disk. */
@@ -269,7 +246,7 @@
}
diff --git a/src/test/coinstatsindex_tests.cpp b/src/test/coinstatsindex_tests.cpp
-index 503a58076b..b268698495 100644
+index 503a58076b..8fc136d1e5 100644
--- a/src/test/coinstatsindex_tests.cpp
+++ b/src/test/coinstatsindex_tests.cpp
@@ -109,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
@@ -277,7 +254,7 @@
BlockValidationState state;
BOOST_CHECK(CheckBlock(block, state, params.GetConsensus()));
- BOOST_CHECK(chainstate.AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr, true));
-+ BOOST_CHECK(AcceptBlock(new_block, *m_node.chainman, state, &new_block_index, true, nullptr, nullptr, true));
++ BOOST_CHECK(m_node.chainman->AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr, true));
CCoinsViewCache view(&chainstate.CoinsTip());
BOOST_CHECK(chainstate.ConnectBlock(block, state, new_block_index, view));
}
@@ -329,14 +306,14 @@
BlockValidationState state;
if (!node.chainman->ActiveChainstate().ActivateBestChain(state)) {
diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp
-index 2078fcd8f8..d55cc09eef 100644
+index 2078fcd8f8..fe2d2ba592 100644
--- a/src/test/validation_chainstate_tests.cpp
+++ b/src/test/validation_chainstate_tests.cpp
@@ -77,6 +77,13 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
// After adding some blocks to the tip, best block should have changed.
BOOST_CHECK(::g_best_block != curr_tip);
-+ // Grab block 1 from disk; we'll add it back to the background chain later.
++ // Grab block 1 from disk; we'll add it to the background chain later.
+ std::shared_ptr<CBlock> pblockone = std::make_shared<CBlock>();
+ {
+ LOCK(::cs_main);
@@ -368,8 +345,8 @@
BOOST_CHECK(checked);
- bool accepted = background_cs.AcceptBlock(
- pblock, state, &pindex, true, nullptr, &newblock, true);
-+ bool accepted = AcceptBlock(
-+ pblockone, chainman, state, &pindex, true, nullptr, &newblock, true);
++ bool accepted = chainman.AcceptBlock(
++ pblockone, state, &pindex, true, nullptr, &newblock, true);
BOOST_CHECK(accepted);
}
+
@@ -562,10 +539,24 @@
//! Ensure that snapshot chainstates initialize properly when found on disk.
diff --git a/src/validation.cpp b/src/validation.cpp
-index d9a0fce34f..504c547ab3 100644
+index d9a0fce34f..df0f8d0bc9 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
-@@ -3188,7 +3188,8 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
+@@ -1579,6 +1579,13 @@ Chainstate::Chainstate(
+ m_chainman(chainman),
+ m_from_snapshot_blockhash(from_snapshot_blockhash) {}
+
++const CBlockIndex* Chainstate::SnapshotBase()
++{
++ if (!m_from_snapshot_blockhash) return nullptr;
++ if (!m_cached_snapshot_base) m_cached_snapshot_base = Assert(m_chainman.m_blockman.LookupBlockIndex(*m_from_snapshot_blockhash));
++ return m_cached_snapshot_base;
++}
++
+ void Chainstate::InitCoinsDB(
+ size_t cache_size_bytes,
+ bool in_memory,
+@@ -3188,7 +3195,8 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
// that the best block hash is non-null.
if (ShutdownRequested()) break;
} while (pindexNewTip != pindexMostWork);
@@ -575,7 +566,7 @@
// Write changes periodically to disk, after relay.
if (!FlushStateToDisk(state, FlushStateMode::PERIODIC)) {
-@@ -3208,17 +3209,17 @@ bool Chainstate::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
+@@ -3208,17 +3216,17 @@ bool Chainstate::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
// Nothing to do, this block is not at the tip.
return true;
}
@@ -599,7 +590,7 @@
}
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->HaveTxsDownloaded()) {
setBlockIndexCandidates.insert(pindex);
-@@ -3334,7 +3335,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
+@@ -3334,7 +3342,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
to_mark_failed = invalid_walk_tip;
}
@@ -608,250 +599,137 @@
{
LOCK(cs_main);
-@@ -3404,8 +3405,31 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
+@@ -3404,8 +3412,32 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
}
}
+void Chainstate::TryAddBlockIndexCandidate(CBlockIndex* pindex)
+{
+ AssertLockHeld(cs_main);
-+ // If the block has more work than our tip, then it should be a candidate for most-work-chain.
-+ if (m_chain.Tip() == nullptr || !setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
-+ bool is_bg_chainstate = m_chainman.IsSnapshotActive() && m_chainman.IsBackgroundChainstate(this) && !m_disabled;
-+ if (!is_bg_chainstate) {
-+ // The active chainstate should always add entries that have more
-+ // work than the tip.
++ // The block only is a candidate for the most-work-chain if it has more work than our current tip.
++ if (m_chain.Tip() != nullptr && setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
++ return;
++ }
++
++ bool is_active_chainstate = this == &m_chainman.ActiveChainstate();
++ if (is_active_chainstate) {
++ // The active chainstate should always add entries that have more
++ // work than the tip.
++ setBlockIndexCandidates.insert(pindex);
++ } else if (!m_disabled) {
++ // For the background chainstate, we only consider connecting blocks
++ // towards the snapshot base (which can't be nullptr or else we'll
++ // never make progress).
++ const CBlockIndex* snapshot_base{Assert(m_chainman.ActiveSnapshotBase())};
++ if (snapshot_base->GetAncestor(pindex->nHeight) == pindex) {
+ setBlockIndexCandidates.insert(pindex);
-+ } else {
-+ // For the background chainstate, we only consider connecting blocks
-+ // towards the snapshot base (which can't be nullptr or else we'll
-+ // never make progress).
-+ const CBlockIndex* snapshot_entry = m_chainman.GetSnapshotBaseBlock();
-+ assert(snapshot_entry != nullptr);
-+ if (snapshot_entry->GetAncestor(pindex->nHeight) == pindex) {
-+ setBlockIndexCandidates.insert(pindex);
-+ }
+ }
+ }
+}
+
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
-void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
-+void ReceivedBlockTransactions(const CBlock& block, ChainstateManager& chainman, CBlockIndex* pindexNew, const FlatFilePos& pos)
++void ChainstateManager::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
{
AssertLockHeld(cs_main);
pindexNew->nTx = block.vtx.size();
-@@ -3414,11 +3438,11 @@ void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pin
+@@ -3414,7 +3446,7 @@ void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pin
pindexNew->nDataPos = pos.nPos;
pindexNew->nUndoPos = 0;
pindexNew->nStatus |= BLOCK_HAVE_DATA;
- if (DeploymentActiveAt(*pindexNew, m_chainman, Consensus::DEPLOYMENT_SEGWIT)) {
-+ if (DeploymentActiveAt(*pindexNew, chainman, Consensus::DEPLOYMENT_SEGWIT)) {
++ if (DeploymentActiveAt(*pindexNew, *this, Consensus::DEPLOYMENT_SEGWIT)) {
pindexNew->nStatus |= BLOCK_OPT_WITNESS;
}
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
-- m_blockman.m_dirty_blockindex.insert(pindexNew);
-+ chainman.m_blockman.AddDirty(pindexNew);
-
- if (pindexNew->pprev == nullptr || pindexNew->pprev->HaveTxsDownloaded()) {
- // If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
-@@ -3430,21 +3454,21 @@ void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pin
- CBlockIndex *pindex = queue.front();
+@@ -3431,8 +3463,8 @@ void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pin
queue.pop_front();
pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
-- pindex->nSequenceId = nBlockSequenceId++;
+ pindex->nSequenceId = nBlockSequenceId++;
- if (m_chain.Tip() == nullptr || !setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
-- setBlockIndexCandidates.insert(pindex);
-+ pindex->nSequenceId = chainman.nBlockSequenceId++;
-+ for (Chainstate *c : chainman.GetAll()) {
+- setBlockIndexCandidates.insert(pindex);
++ for (Chainstate *c : GetAll()) {
+ c->TryAddBlockIndexCandidate(pindex);
}
-- std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = m_blockman.m_blocks_unlinked.equal_range(pindex);
-+ std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = chainman.m_blockman.m_blocks_unlinked.equal_range(pindex);
+ std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = m_blockman.m_blocks_unlinked.equal_range(pindex);
while (range.first != range.second) {
- std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
- queue.push_back(it->second);
- range.first++;
-- m_blockman.m_blocks_unlinked.erase(it);
-+ chainman.m_blockman.m_blocks_unlinked.erase(it);
- }
- }
- } else {
- if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) {
-- m_blockman.m_blocks_unlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
-+ chainman.m_blockman.m_blocks_unlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
- }
- }
- }
-@@ -3727,15 +3751,15 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
- return true;
- }
-
--bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, CBlockIndex** ppindex, bool min_pow_checked)
-+bool AcceptBlockHeader(const CBlockHeader& block, ChainstateManager& chainman, BlockValidationState& state, CBlockIndex** ppindex, bool min_pow_checked)
- {
- AssertLockHeld(cs_main);
-
- // Check for duplicate
- uint256 hash = block.GetHash();
-- BlockMap::iterator miSelf{m_blockman.m_block_index.find(hash)};
-- if (hash != GetConsensus().hashGenesisBlock) {
-- if (miSelf != m_blockman.m_block_index.end()) {
-+ BlockMap::iterator miSelf{chainman.m_blockman.m_block_index.find(hash)};
-+ if (hash != chainman.GetConsensus().hashGenesisBlock) {
-+ if (miSelf != chainman.m_blockman.m_block_index.end()) {
- // Block header is already known.
- CBlockIndex* pindex = &(miSelf->second);
- if (ppindex)
-@@ -3747,15 +3771,15 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
- return true;
- }
-
-- if (!CheckBlockHeader(block, state, GetConsensus())) {
-+ if (!CheckBlockHeader(block, state, chainman.GetConsensus())) {
- LogPrint(BCLog::VALIDATION, "%s: Consensus::CheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString());
- return false;
- }
-
- // Get prev block index
- CBlockIndex* pindexPrev = nullptr;
-- BlockMap::iterator mi{m_blockman.m_block_index.find(block.hashPrevBlock)};
-- if (mi == m_blockman.m_block_index.end()) {
-+ BlockMap::iterator mi{chainman.m_blockman.m_block_index.find(block.hashPrevBlock)};
-+ if (mi == chainman.m_blockman.m_block_index.end()) {
- LogPrint(BCLog::VALIDATION, "header %s has prev block not found: %s\n", hash.ToString(), block.hashPrevBlock.ToString());
- return state.Invalid(BlockValidationResult::BLOCK_MISSING_PREV, "prev-blk-not-found");
- }
-@@ -3764,7 +3788,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
- LogPrint(BCLog::VALIDATION, "header %s has prev block invalid: %s\n", hash.ToString(), block.hashPrevBlock.ToString());
- return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
- }
-- if (!ContextualCheckBlockHeader(block, state, m_blockman, *this, pindexPrev, m_options.adjusted_time_callback())) {
-+ if (!ContextualCheckBlockHeader(block, state, chainman.m_blockman, chainman, pindexPrev, chainman.m_options.adjusted_time_callback())) {
- LogPrint(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString());
- return false;
- }
-@@ -3793,13 +3817,13 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
- // hasn't been validated up to BLOCK_VALID_SCRIPTS. This is a performance
- // optimization, in the common case of adding a new block to the tip,
- // we don't need to iterate over the failed blocks list.
-- for (const CBlockIndex* failedit : m_failed_blocks) {
-+ for (const CBlockIndex* failedit : chainman.m_failed_blocks) {
- if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) {
- assert(failedit->nStatus & BLOCK_FAILED_VALID);
- CBlockIndex* invalid_walk = pindexPrev;
- while (invalid_walk != failedit) {
- invalid_walk->nStatus |= BLOCK_FAILED_CHILD;
-- m_blockman.m_dirty_blockindex.insert(invalid_walk);
-+ chainman.m_blockman.AddDirty(invalid_walk);
- invalid_walk = invalid_walk->pprev;
- }
- LogPrint(BCLog::VALIDATION, "header %s has prev block invalid: %s\n", hash.ToString(), block.hashPrevBlock.ToString());
-@@ -3812,7 +3836,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
- LogPrint(BCLog::VALIDATION, "%s: not adding new block header %s, missing anti-dos proof-of-work validation\n", __func__, hash.ToString());
- return state.Invalid(BlockValidationResult::BLOCK_HEADER_LOW_WORK, "too-little-chainwork");
- }
-- CBlockIndex* pindex{m_blockman.AddToBlockIndex(block, m_best_header)};
-+ CBlockIndex* pindex{chainman.m_blockman.AddToBlockIndex(block, chainman.m_best_header)};
-
- if (ppindex)
- *ppindex = pindex;
-@@ -3828,7 +3852,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
- const auto msg = strprintf(
- "Saw new header hash=%s height=%d", hash.ToString(), pindex->nHeight);
-
-- if (ActiveChainstate().IsInitialBlockDownload()) {
-+ if (chainman.ActiveChainstate().IsInitialBlockDownload()) {
- LogPrintLevel(BCLog::VALIDATION, BCLog::Level::Debug, "%s\n", msg);
- } else {
- LogPrintf("%s\n", msg);
-@@ -3845,8 +3869,8 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>&
- LOCK(cs_main);
+@@ -3846,7 +3878,7 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>&
for (const CBlockHeader& header : headers) {
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
-- bool accepted{AcceptBlockHeader(header, state, &pindex, min_pow_checked)};
+ bool accepted{AcceptBlockHeader(header, state, &pindex, min_pow_checked)};
- ActiveChainstate().CheckBlockIndex();
-+ bool accepted{AcceptBlockHeader(header, *this, state, &pindex, min_pow_checked)};
+ CheckBlockIndex();
if (!accepted) {
return false;
-@@ -3893,7 +3917,7 @@ void ChainstateManager::ReportHeadersPresync(const arith_uint256& work, int64_t
+@@ -3893,7 +3925,7 @@ void ChainstateManager::ReportHeadersPresync(const arith_uint256& work, int64_t
}
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
-bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked)
-+bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, ChainstateManager& chainman, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked)
++bool ChainstateManager::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked)
{
const CBlock& block = *pblock;
-@@ -3903,8 +3927,8 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
+@@ -3903,7 +3935,7 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
CBlockIndex *pindexDummy = nullptr;
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
- bool accepted_header{m_chainman.AcceptBlockHeader(block, state, &pindex, min_pow_checked)};
-- CheckBlockIndex();
-+ bool accepted_header{AcceptBlockHeader(block, chainman, state, &pindex, min_pow_checked)};
-+ chainman.CheckBlockIndex();
++ bool accepted_header{AcceptBlockHeader(block, state, &pindex, min_pow_checked)};
+ CheckBlockIndex();
if (!accepted_header)
- return false;
-@@ -3913,13 +3937,13 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
+@@ -3913,13 +3945,13 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
// process an unrequested block if it's new and has enough work to
// advance our tip, and isn't too many blocks ahead.
bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA;
- bool fHasMoreOrSameWork = (m_chain.Tip() ? pindex->nChainWork >= m_chain.Tip()->nChainWork : true);
-+ bool fHasMoreOrSameWork = (chainman.ActiveChain().Tip() ? pindex->nChainWork >= chainman.ActiveChain().Tip()->nChainWork : true);
++ bool fHasMoreOrSameWork = (ActiveTip() ? pindex->nChainWork >= ActiveTip()->nChainWork : true);
// Blocks that are too out-of-order needlessly limit the effectiveness of
// pruning, because pruning will not delete block files that contain any
// blocks which are too close in height to the tip. Apply this test
// regardless of whether pruning is enabled; it should generally be safe to
// not process unrequested blocks.
- bool fTooFarAhead{pindex->nHeight > m_chain.Height() + int(MIN_BLOCKS_TO_KEEP)};
-+ bool fTooFarAhead{pindex->nHeight > chainman.ActiveChain().Height() + int(MIN_BLOCKS_TO_KEEP)};
++ bool fTooFarAhead{pindex->nHeight > ActiveHeight() + int(MIN_BLOCKS_TO_KEEP)};
// TODO: Decouple this function from the block download logic by removing fRequested
// This requires some new chain data structure to efficiently look up if a
-@@ -3939,41 +3963,48 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
+@@ -3939,13 +3971,13 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
// If our tip is behind, a peer could try to send us
// low-work blocks on a fake chain that we would never
// request; don't process these.
- if (pindex->nChainWork < m_chainman.MinimumChainWork()) return true;
-+ if (pindex->nChainWork < chainman.MinimumChainWork()) return true;
++ if (pindex->nChainWork < MinimumChainWork()) return true;
}
- const CChainParams& params{m_chainman.GetParams()};
-+ const CChainParams& params{chainman.GetParams()};
++ const CChainParams& params{GetParams()};
if (!CheckBlock(block, state, params.GetConsensus()) ||
- !ContextualCheckBlock(block, state, m_chainman, pindex->pprev)) {
-+ !ContextualCheckBlock(block, state, chainman, pindex->pprev)) {
++ !ContextualCheckBlock(block, state, *this, pindex->pprev)) {
if (state.IsInvalid() && state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
pindex->nStatus |= BLOCK_FAILED_VALID;
-- m_blockman.m_dirty_blockindex.insert(pindex);
-+ chainman.m_blockman.AddDirty(pindex);
- }
- return error("%s: %s", __func__, state.ToString());
- }
+ m_blockman.m_dirty_blockindex.insert(pindex);
+@@ -3955,13 +3987,13 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW
// (but if it does not build on our best tip, let the SendMessages loop relay it)
- if (!IsInitialBlockDownload() && m_chain.Tip() == pindex->pprev)
-+ if (!chainman.ActiveChainstate().IsInitialBlockDownload() && chainman.ActiveChain().Tip() == pindex->pprev)
++ if (!ActiveChainstate().IsInitialBlockDownload() && ActiveTip() == pindex->pprev)
GetMainSignals().NewPoWValidBlock(pindex, pblock);
// Write block to history file
if (fNewBlock) *fNewBlock = true;
try {
- FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, pindex->nHeight, m_chain, dbp)};
-+ FlatFilePos blockPos{chainman.m_blockman.SaveBlockToDisk(block, pindex->nHeight, dbp)};
++ FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, pindex->nHeight, dbp)};
if (blockPos.IsNull()) {
state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__));
return false;
- }
-- ReceivedBlockTransactions(block, pindex, blockPos);
-+ ReceivedBlockTransactions(block, chainman, pindex, blockPos);
- } catch (const std::runtime_error& e) {
+@@ -3971,7 +4003,14 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
return AbortNode(state, std::string("System error: ") + e.what());
}
@@ -863,23 +741,20 @@
+ // the block files may be pruned, so we can just call this on one
+ // chainstate (particularly if we haven't implemented pruning with
+ // background validation yet).
-+ chainman.ActiveChainstate().FlushStateToDisk(state, FlushStateMode::NONE);
++ ActiveChainstate().FlushStateToDisk(state, FlushStateMode::NONE);
-- CheckBlockIndex();
-+ chainman.CheckBlockIndex();
+ CheckBlockIndex();
- return true;
- }
-@@ -3999,7 +4030,7 @@ bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& blo
+@@ -3999,7 +4038,7 @@ bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& blo
bool ret = CheckBlock(*block, state, GetConsensus());
if (ret) {
// Store to disk
- ret = ActiveChainstate().AcceptBlock(block, state, &pindex, force_processing, nullptr, new_block, min_pow_checked);
-+ ret = AcceptBlock(block, *this, state, &pindex, force_processing, nullptr, new_block, min_pow_checked);
++ ret = AcceptBlock(block, state, &pindex, force_processing, nullptr, new_block, min_pow_checked);
}
if (!ret) {
GetMainSignals().BlockChecked(*block, state);
-@@ -4367,10 +4398,9 @@ bool Chainstate::NeedsRedownload() const
+@@ -4367,10 +4406,9 @@ bool Chainstate::NeedsRedownload() const
return false;
}
@@ -891,7 +766,7 @@
setBlockIndexCandidates.clear();
}
-@@ -4389,62 +4419,14 @@ bool ChainstateManager::LoadBlockIndex()
+@@ -4389,62 +4427,14 @@ bool ChainstateManager::LoadBlockIndex()
std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
CBlockIndexHeightOnlyComparator());
@@ -956,7 +831,7 @@
}
}
if (pindex->nStatus & BLOCK_FAILED_MASK && (!m_best_invalid || pindex->nChainWork > m_best_invalid->nChainWork)) {
-@@ -4484,12 +4466,12 @@ bool Chainstate::LoadGenesisBlock()
+@@ -4484,12 +4474,12 @@ bool Chainstate::LoadGenesisBlock()
try {
const CBlock& block = params.GenesisBlock();
@@ -967,11 +842,11 @@
}
CBlockIndex* pindex = m_blockman.AddToBlockIndex(block, m_chainman.m_best_header);
- ReceivedBlockTransactions(block, pindex, blockPos);
-+ ReceivedBlockTransactions(block, m_chainman, pindex, blockPos);
++ m_chainman.ReceivedBlockTransactions(block, pindex, blockPos);
} catch (const std::runtime_error& e) {
return error("%s: failed to write genesis block: %s", __func__, e.what());
}
-@@ -4497,18 +4479,16 @@ bool Chainstate::LoadGenesisBlock()
+@@ -4497,18 +4487,16 @@ bool Chainstate::LoadGenesisBlock()
return true;
}
@@ -992,16 +867,7 @@
int nLoaded = 0;
try {
-@@ -4580,7 +4560,7 @@ void Chainstate::LoadExternalBlockFile(
- nRewind = blkdat.GetPos();
-
- BlockValidationState state;
-- if (AcceptBlock(pblock, state, nullptr, true, dbp, nullptr, true)) {
-+ if (AcceptBlock(pblock, *this, state, nullptr, true, dbp, nullptr, true)) {
- nLoaded++;
- }
- if (state.IsError()) {
-@@ -4594,7 +4574,14 @@ void Chainstate::LoadExternalBlockFile(
+@@ -4594,7 +4582,14 @@ void Chainstate::LoadExternalBlockFile(
// Activate the genesis block so normal node progress can continue
if (hash == params.GetConsensus().hashGenesisBlock) {
BlockValidationState state;
@@ -1017,7 +883,7 @@
break;
}
}
-@@ -4608,13 +4595,13 @@ void Chainstate::LoadExternalBlockFile(
+@@ -4608,13 +4603,13 @@ void Chainstate::LoadExternalBlockFile(
// called by concurrent network message processing. but, that is not
// reliable for the purpose of pruning while importing.
BlockValidationState state;
@@ -1033,15 +899,7 @@
if (!blocks_with_unknown_parent) continue;
-@@ -4633,14 +4620,14 @@ void Chainstate::LoadExternalBlockFile(
- head.ToString());
- LOCK(cs_main);
- BlockValidationState dummy;
-- if (AcceptBlock(pblockrecursive, dummy, nullptr, true, &it->second, nullptr, true)) {
-+ if (AcceptBlock(pblockrecursive, *this, dummy, nullptr, true, &it->second, nullptr, true)) {
- nLoaded++;
- queue.push_back(pblockrecursive->GetHash());
- }
+@@ -4640,7 +4635,7 @@ void Chainstate::LoadExternalBlockFile(
}
range.first++;
blocks_with_unknown_parent->erase(it);
@@ -1050,7 +908,7 @@
}
}
} catch (const std::exception& e) {
-@@ -4664,9 +4651,9 @@ void Chainstate::LoadExternalBlockFile(
+@@ -4664,9 +4659,9 @@ void Chainstate::LoadExternalBlockFile(
LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
}
@@ -1062,7 +920,7 @@
return;
}
-@@ -4675,7 +4662,7 @@ void Chainstate::CheckBlockIndex()
+@@ -4675,7 +4670,7 @@ void Chainstate::CheckBlockIndex()
// During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
// so we have the genesis block in m_blockman.m_block_index but no active chain. (A few of the
// tests when iterating the block tree require that m_chain has been initialized.)
@@ -1071,7 +929,7 @@
assert(m_blockman.m_block_index.size() <= 1);
return;
}
-@@ -4705,12 +4692,12 @@ void Chainstate::CheckBlockIndex()
+@@ -4705,12 +4700,12 @@ void Chainstate::CheckBlockIndex()
CBlockIndex* pindexFirstNotTransactionsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not).
CBlockIndex* pindexFirstNotChainValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
CBlockIndex* pindexFirstNotScriptsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
@@ -1087,7 +945,7 @@
pindexFirstMissing = pindex;
}
if (pindexFirstNeverProcessed == nullptr && pindex->nTx == 0) pindexFirstNeverProcessed = pindex;
-@@ -4739,8 +4726,8 @@ void Chainstate::CheckBlockIndex()
+@@ -4739,8 +4734,8 @@ void Chainstate::CheckBlockIndex()
// Begin: actual consistency checks.
if (pindex->pprev == nullptr) {
// Genesis block checks.
@@ -1098,7 +956,7 @@
}
if (!pindex->HaveTxsDownloaded()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
-@@ -4750,7 +4737,13 @@ void Chainstate::CheckBlockIndex()
+@@ -4750,7 +4745,13 @@ void Chainstate::CheckBlockIndex()
if (!m_blockman.m_have_pruned && !pindex->IsAssumedValid()) {
// If we've never pruned, then HAVE_DATA should be equivalent to nTx > 0
assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
@@ -1113,7 +971,7 @@
} else {
// If we have pruned, then we can only say that HAVE_DATA implies nTx > 0
if (pindex->nStatus & BLOCK_HAVE_DATA) assert(pindex->nTx > 0);
-@@ -4780,27 +4773,32 @@ void Chainstate::CheckBlockIndex()
+@@ -4780,27 +4781,32 @@ void Chainstate::CheckBlockIndex()
// Checks for not-invalid blocks.
assert((pindex->nStatus & BLOCK_FAILED_MASK) == 0); // The failed mask cannot be set for blocks without invalid parents.
}
@@ -1165,7 +1023,7 @@
}
// Check whether this block is in m_blocks_unlinked.
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked = m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
-@@ -4821,18 +4819,23 @@ void Chainstate::CheckBlockIndex()
+@@ -4821,18 +4827,23 @@ void Chainstate::CheckBlockIndex()
if (pindexFirstMissing == nullptr) assert(!foundInUnlinked); // We aren't missing data for any parent -- cannot be in m_blocks_unlinked.
if (pindex->pprev && (pindex->nStatus & BLOCK_HAVE_DATA) && pindexFirstNeverProcessed == nullptr && pindexFirstMissing != nullptr) {
// We HAVE_DATA for this block, have received data for all parents at some point, but we're currently missing data for some parent.
@@ -1194,7 +1052,7 @@
}
}
}
-@@ -4859,6 +4862,7 @@ void Chainstate::CheckBlockIndex()
+@@ -4859,6 +4870,7 @@ void Chainstate::CheckBlockIndex()
if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid = nullptr;
if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid = nullptr;
if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid = nullptr;
@@ -1203,58 +1061,10 @@
CBlockIndex* pindexPar = pindex->pprev;
// Find which child we just visited.
diff --git a/src/validation.h b/src/validation.h
-index cb5b291dab..6df13fdd29 100644
+index cb5b291dab..911d6ef178 100644
--- a/src/validation.h
+++ b/src/validation.h
-@@ -337,9 +337,46 @@ public:
- /** Context-independent validity checks */
- bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
-
-+/**
-+ * If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
-+ * that it doesn't descend from an invalid block, and then add it to m_block_index.
-+ * Caller must set min_pow_checked=true in order to add a new header to the
-+ * block index (permanent memory storage), indicating that the header is
-+ * known to be part of a sufficiently high-work chain (anti-dos check).
-+ */
-+bool AcceptBlockHeader(
-+ const CBlockHeader& block,
-+ ChainstateManager& chaiman,
-+ BlockValidationState& state,
-+ CBlockIndex** ppindex,
-+ bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-+
-+/**
-+ * Sufficiently validate a block for disk storage (and store on disk).
-+ *
-+ * @param[in] pblock The block we want to process.
-+ * @param[in] fRequested Whether we requested this block from a
-+ * peer.
-+ * @param[in] dbp The location on disk, if we are importing
-+ * this block from prior storage.
-+ * @param[in] min_pow_checked True if proof-of-work anti-DoS checks have
-+ * been done by caller for headers chain
-+ *
-+ * @param[out] state The state of the block validation.
-+ * @param[out] ppindex Optional return parameter to get the
-+ * CBlockIndex pointer for this block.
-+ * @param[out] fNewBlock Optional return parameter to indicate if the
-+ * block is new to our storage.
-+ *
-+ * @returns False if the block or header is invalid, or if saving to disk fails (likely a fatal error); true otherwise.
-+ */
-+bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, ChainstateManager& chainman, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-+
-+void ReceivedBlockTransactions(const CBlock& block, ChainstateManager& chainman, CBlockIndex* pindexNew, const FlatFilePos& pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-+
- /** Check a block is completely valid from start to finish (only works on top of our current best block) */
- bool TestBlockValidity(BlockValidationState& state,
-- const CChainParams& chainparams,
-+ const CChainParams& chainparams,
- Chainstate& chainstate,
- const CBlock& block,
- CBlockIndex* pindexPrev,
-@@ -456,17 +493,6 @@ enum class CoinsCacheSizeState
+@@ -456,17 +456,6 @@ enum class CoinsCacheSizeState
class Chainstate
{
protected:
@@ -1272,7 +1082,31 @@
/**
* The ChainState Mutex
* A lock that must be held when modifying this ChainState - held in ActivateBestChain() and
-@@ -611,37 +637,6 @@ public:
+@@ -502,6 +491,9 @@ protected:
+ //! is set to true on the snapshot chainstate.
+ bool m_disabled GUARDED_BY(::cs_main) {false};
+
++ //! Cached result of LookupBlockIndex(*m_from_snapshot_blockhash)
++ const CBlockIndex* m_cached_snapshot_base GUARDED_BY(::cs_main) {nullptr};
++
+ public:
+ //! Reference to a BlockManager instance which itself is shared across all
+ //! Chainstate instances.
+@@ -553,6 +545,13 @@ public:
+ */
+ const std::optional<uint256> m_from_snapshot_blockhash;
+
++ /**
++ * The base of the snapshot this chainstate was created from.
++ *
++ * nullptr if this chainstate was not created from a snapshot.
++ */
++ const CBlockIndex* SnapshotBase() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
++
+ //! Return true if this chainstate relies on blocks that are assumed-valid. In
+ //! practice this means it was created based on a UTXO snapshot.
+ bool reliesOnAssumedValid() { return m_from_snapshot_blockhash.has_value(); }
+@@ -611,37 +610,6 @@ public:
bool ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
@@ -1310,16 +1144,16 @@
/**
* Update the on-disk chain state.
-@@ -693,8 +688,6 @@ public:
+@@ -693,8 +661,6 @@ public:
EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
LOCKS_EXCLUDED(::cs_main);
-- bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
--
+- bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+-
// Block (dis)connection on a given view:
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
-@@ -729,9 +722,11 @@ public:
+@@ -729,9 +695,11 @@ public:
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
bool LoadGenesisBlock();
@@ -1332,7 +1166,7 @@
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload() const;
-@@ -739,13 +734,6 @@ public:
+@@ -739,13 +707,6 @@ public:
/** Find the last common block of this chain and a locator. */
const CBlockIndex* FindForkInGlobalIndex(const CBlockLocator& locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -1346,34 +1180,15 @@
/** Load the persisted mempool from disk */
void LoadMempool(const fs::path& load_path, fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen);
-@@ -775,7 +763,6 @@ private:
+@@ -775,7 +736,6 @@ private:
void InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-- void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+- void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-@@ -914,18 +901,6 @@ private:
- AutoFile& coins_file,
- const node::SnapshotMetadata& metadata);
-
-- /**
-- * If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
-- * that it doesn't descend from an invalid block, and then add it to m_block_index.
-- * Caller must set min_pow_checked=true in order to add a new header to the
-- * block index (permanent memory storage), indicating that the header is
-- * known to be part of a sufficiently high-work chain (anti-dos check).
-- */
-- bool AcceptBlockHeader(
-- const CBlockHeader& block,
-- BlockValidationState& state,
-- CBlockIndex** ppindex,
-- bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- friend Chainstate;
-
- /** Most recent headers presync progress update, for rate-limiting. */
-@@ -962,6 +937,13 @@ public:
+@@ -962,6 +922,13 @@ public:
kernel::Notifications& GetNotifications() const { return m_options.notifications; };
int StopAtHeight() const { return m_options.stop_at_height; };
@@ -1387,7 +1202,7 @@
/**
* Alias for ::cs_main.
* Should be used in new code to make it easier to make ::cs_main a member
-@@ -981,6 +963,25 @@ public:
+@@ -981,6 +948,25 @@ public:
//! chainstate to avoid duplicating block metadata.
node::BlockManager m_blockman;
@@ -1413,23 +1228,15 @@
/**
* In order to efficiently track invalidity of headers, we keep the set of
* blocks which we tried to connect and found to be invalid here (ie which
-@@ -1071,6 +1072,12 @@ public:
- //! that a background validation chainstate is also in use.
- bool IsSnapshotActive() const;
+@@ -1079,6 +1065,42 @@ public:
+ return m_snapshot_chainstate && m_ibd_chainstate && m_ibd_chainstate->m_disabled;
+ }
-+ //! @returns true if the chainstate is the background chainstate
-+ bool IsBackgroundChainstate(const Chainstate *chainstate) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
++ const CBlockIndex* ActiveSnapshotBase() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
+ {
-+ return chainstate == m_ibd_chainstate.get();
++ return m_active_chainstate ? m_active_chainstate->SnapshotBase() : nullptr;
+ }
+
- std::optional<uint256> SnapshotBlockhash() const;
-
- //! Is there a snapshot in use and has it been fully validated?
-@@ -1079,6 +1086,37 @@ public:
- return m_snapshot_chainstate && m_ibd_chainstate && m_ibd_chainstate->m_disabled;
- }
-
+ /**
+ * Import blocks from an external file
+ *
@@ -1463,4 +1270,34 @@
+
/**
* Process an incoming block. This only returns after the best known valid
- * block is made active. Note that it does not, however, guarantee that the
\ No newline at end of file
+ * block is made active. Note that it does not, however, guarantee that the
+@@ -1118,6 +1140,29 @@ public:
+ */
+ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
+
++ /**
++ * Sufficiently validate a block for disk storage (and store on disk).
++ *
++ * @param[in] pblock The block we want to process.
++ * @param[in] fRequested Whether we requested this block from a
++ * peer.
++ * @param[in] dbp The location on disk, if we are importing
++ * this block from prior storage.
++ * @param[in] min_pow_checked True if proof-of-work anti-DoS checks have
++ * been done by caller for headers chain
++ *
++ * @param[out] state The state of the block validation.
++ * @param[out] ppindex Optional return parameter to get the
++ * CBlockIndex pointer for this block.
++ * @param[out] fNewBlock Optional return parameter to indicate if the
++ * block is new to our storage.
++ *
++ * @returns False if the block or header is invalid, or if saving to disk fails (likely a fatal error); true otherwise.
++ */
++ bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
++
++ void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
++
+ /**
+ * Try to add a transaction to the memory pool.
+ *
\ No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment