Merge 8f604361eb into merged_master (Bitcoin PR #16194)

This commit is contained in:
Andrew Poelstra 2020-11-09 21:20:06 +00:00
commit 1e58aac3d1
8 changed files with 231 additions and 165 deletions

View file

@ -80,7 +80,11 @@ bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIn
return false;
}
static CChainState g_chainstate;
namespace {
BlockManager g_blockman;
} // anon namespace
static CChainState g_chainstate(g_blockman);
CChainState& ChainstateActive() { return g_chainstate; }
@ -98,7 +102,6 @@ CChain& ChainActive() { return g_chainstate.m_chain; }
*/
RecursiveMutex cs_main;
BlockMap& mapBlockIndex = ::ChainstateActive().mapBlockIndex;
CBlockIndex *pindexBestHeader = nullptr;
Mutex g_best_block_mutex;
std::condition_variable g_best_block_cv;
@ -128,12 +131,7 @@ CScript COINBASE_FLAGS;
// Internal stuff
namespace {
CBlockIndex *&pindexBestInvalid = ::ChainstateActive().pindexBestInvalid;
/** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
* Pruned nodes may have entries where B is missing data.
*/
std::multimap<CBlockIndex*, CBlockIndex*>& mapBlocksUnlinked = ::ChainstateActive().mapBlocksUnlinked;
CBlockIndex* pindexBestInvalid = nullptr;
CCriticalSection cs_LastBlockFile;
std::vector<CBlockFileInfo> vinfoBlockFile;
@ -151,6 +149,13 @@ namespace {
std::set<int> setDirtyFileInfo;
} // anon namespace
CBlockIndex* LookupBlockIndex(const uint256& hash)
{
AssertLockHeld(cs_main);
BlockMap::const_iterator it = g_blockman.m_block_index.find(hash);
return it == g_blockman.m_block_index.end() ? nullptr : it->second;
}
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
{
AssertLockHeld(cs_main);
@ -1108,6 +1113,11 @@ bool CChainState::IsInitialBlockDownload() const
static CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr;
BlockMap& BlockIndex()
{
return g_blockman.m_block_index;
}
static void AlertNotify(const std::string& strMessage)
{
uiInterface.NotifyAlertChanged();
@ -1221,7 +1231,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(c
void CChainState::InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
if (state.GetReason() != ValidationInvalidReason::BLOCK_MUTATED) {
pindex->nStatus |= BLOCK_FAILED_VALID;
m_failed_blocks.insert(pindex);
m_blockman.m_failed_blocks.insert(pindex);
setDirtyBlockIndex.insert(pindex);
setBlockIndexCandidates.erase(pindex);
InvalidChainFound(pindex);
@ -1824,8 +1834,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// relative to a piece of software is an objective fact these defaults can be easily reviewed.
// This setting doesn't force the selection of any particular chain but makes validating some faster by
// effectively caching the result of part of the verification.
BlockMap::const_iterator it = mapBlockIndex.find(hashAssumeValid);
if (it != mapBlockIndex.end()) {
BlockMap::const_iterator it = m_blockman.m_block_index.find(hashAssumeValid);
if (it != m_blockman.m_block_index.end()) {
if (it->second->GetAncestor(pindex->nHeight) == pindex &&
pindexBestHeader->GetAncestor(pindex->nHeight) == pindex &&
pindexBestHeader->nChainWork >= nMinimumChainWork) {
@ -2555,10 +2565,11 @@ CBlockIndex* CChainState::FindMostWorkChain() {
if (fFailedChain) {
pindexFailed->nStatus |= BLOCK_FAILED_CHILD;
} else if (fMissingData) {
// If we're missing data, then add back to mapBlocksUnlinked,
// If we're missing data, then add back to m_blocks_unlinked,
// so that if the block arrives in the future we can try adding
// to setBlockIndexCandidates again.
mapBlocksUnlinked.insert(std::make_pair(pindexFailed->pprev, pindexFailed));
m_blockman.m_blocks_unlinked.insert(
std::make_pair(pindexFailed->pprev, pindexFailed));
}
setBlockIndexCandidates.erase(pindexFailed);
pindexFailed = pindexFailed->pprev;
@ -2909,12 +2920,12 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
to_mark_failed->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(to_mark_failed);
setBlockIndexCandidates.erase(to_mark_failed);
m_failed_blocks.insert(to_mark_failed);
m_blockman.m_failed_blocks.insert(to_mark_failed);
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
// add it again.
BlockMap::iterator it = mapBlockIndex.begin();
while (it != mapBlockIndex.end()) {
BlockMap::iterator it = m_blockman.m_block_index.begin();
while (it != m_blockman.m_block_index.end()) {
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(it->second, m_chain.Tip())) {
setBlockIndexCandidates.insert(it->second);
}
@ -2941,8 +2952,8 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
int nHeight = pindex->nHeight;
// Remove the invalidity flag from this block and all its descendants.
BlockMap::iterator it = mapBlockIndex.begin();
while (it != mapBlockIndex.end()) {
BlockMap::iterator it = m_blockman.m_block_index.begin();
while (it != m_blockman.m_block_index.end()) {
if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
it->second->nStatus &= ~BLOCK_FAILED_MASK;
setDirtyBlockIndex.insert(it->second);
@ -2953,7 +2964,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
// Reset invalid block marker if it was pointing to one of those.
pindexBestInvalid = nullptr;
}
m_failed_blocks.erase(it->second);
m_blockman.m_failed_blocks.erase(it->second);
}
it++;
}
@ -2963,7 +2974,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
if (pindex->nStatus & BLOCK_FAILED_MASK) {
pindex->nStatus &= ~BLOCK_FAILED_MASK;
setDirtyBlockIndex.insert(pindex);
m_failed_blocks.erase(pindex);
m_blockman.m_failed_blocks.erase(pindex);
}
pindex = pindex->pprev;
}
@ -2973,14 +2984,14 @@ void ResetBlockFailureFlags(CBlockIndex *pindex) {
return ::ChainstateActive().ResetBlockFailureFlags(pindex);
}
CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block)
CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block)
{
AssertLockHeld(cs_main);
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator it = mapBlockIndex.find(hash);
if (it != mapBlockIndex.end())
BlockMap::iterator it = m_block_index.find(hash);
if (it != m_block_index.end())
return it->second;
// Construct new block index object
@ -2989,10 +3000,10 @@ CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block)
// to avoid miners withholding blocks but broadcasting headers, to get a
// competitive advantage.
pindexNew->nSequenceId = 0;
BlockMap::iterator mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first;
BlockMap::iterator mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (miPrev != mapBlockIndex.end())
BlockMap::iterator miPrev = m_block_index.find(block.hashPrevBlock);
if (miPrev != m_block_index.end())
{
pindexNew->pprev = (*miPrev).second;
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
@ -3041,17 +3052,17 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
if (m_chain.Tip() == nullptr || !setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
setBlockIndexCandidates.insert(pindex);
}
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.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++;
mapBlocksUnlinked.erase(it);
m_blockman.m_blocks_unlinked.erase(it);
}
}
} else {
if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) {
mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
m_blockman.m_blocks_unlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
}
}
}
@ -3387,7 +3398,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta
if (fCheckpointsEnabled) {
// Don't accept any forks from the main chain prior to last checkpoint.
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
// MapBlockIndex.
// g_blockman.m_block_index.
CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
@ -3518,15 +3529,15 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
return true;
}
bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
{
AssertLockHeld(cs_main);
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator miSelf = mapBlockIndex.find(hash);
BlockMap::iterator miSelf = m_block_index.find(hash);
CBlockIndex *pindex = nullptr;
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
if (miSelf != mapBlockIndex.end()) {
if (miSelf != m_block_index.end()) {
// Block header is already known.
pindex = miSelf->second;
if (ppindex)
@ -3541,8 +3552,8 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
// Get prev block index
CBlockIndex* pindexPrev = nullptr;
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
BlockMap::iterator mi = m_block_index.find(block.hashPrevBlock);
if (mi == m_block_index.end())
return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), 0, "prev-blk-not-found");
pindexPrev = (*mi).second;
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
@ -3594,8 +3605,6 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
if (ppindex)
*ppindex = pindex;
CheckBlockIndex(chainparams.GetConsensus());
return true;
}
@ -3607,7 +3616,10 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio
LOCK(cs_main);
for (const CBlockHeader& header : headers) {
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
if (!::ChainstateActive().AcceptBlockHeader(header, state, chainparams, &pindex)) {
bool accepted = g_blockman.AcceptBlockHeader(header, state, chainparams, &pindex);
::ChainstateActive().CheckBlockIndex(chainparams.GetConsensus());
if (!accepted) {
if (first_invalid) *first_invalid = header;
return false;
}
@ -3650,7 +3662,10 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
CBlockIndex *pindexDummy = nullptr;
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
if (!AcceptBlockHeader(block, state, chainparams, &pindex))
bool accepted_header = m_blockman.AcceptBlockHeader(block, state, chainparams, &pindex);
CheckBlockIndex(chainparams.GetConsensus());
if (!accepted_header)
return false;
// Try to process all requested blocks that we don't have, but only
@ -3802,7 +3817,7 @@ void PruneOneBlockFile(const int fileNumber)
{
LOCK(cs_LastBlockFile);
for (const auto& entry : mapBlockIndex) {
for (const auto& entry : g_blockman.m_block_index) {
CBlockIndex* pindex = entry.second;
if (pindex->nFile == fileNumber) {
pindex->nStatus &= ~BLOCK_HAVE_DATA;
@ -3812,16 +3827,16 @@ void PruneOneBlockFile(const int fileNumber)
pindex->nUndoPos = 0;
setDirtyBlockIndex.insert(pindex);
// Prune from mapBlocksUnlinked -- any block we prune would have
// Prune from m_blocks_unlinked -- any block we prune would have
// to be downloaded again in order to consider its chain, at which
// point it would be considered as a candidate for
// mapBlocksUnlinked or setBlockIndexCandidates.
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex->pprev);
// m_blocks_unlinked or setBlockIndexCandidates.
auto range = g_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
while (range.first != range.second) {
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
range.first++;
if (_it->second == pindex) {
mapBlocksUnlinked.erase(_it);
g_blockman.m_blocks_unlinked.erase(_it);
}
}
}
@ -3970,7 +3985,7 @@ fs::path GetBlockPosFilename(const FlatFilePos &pos)
return BlockFileSeq().FileName(pos);
}
CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
CBlockIndex * BlockManager::InsertBlockIndex(const uint256& hash)
{
AssertLockHeld(cs_main);
@ -3978,27 +3993,30 @@ CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
return nullptr;
// Return existing
BlockMap::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
BlockMap::iterator mi = m_block_index.find(hash);
if (mi != m_block_index.end())
return (*mi).second;
// Create new
CBlockIndex* pindexNew = new CBlockIndex();
mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first;
mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
return pindexNew;
}
bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree)
bool BlockManager::LoadBlockIndex(
const Consensus::Params& consensus_params,
CBlockTreeDB& blocktree,
std::set<CBlockIndex*, CBlockIndexWorkComparator>& block_index_candidates)
{
if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }))
return false;
// Calculate nChainWork
std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
vSortedByHeight.reserve(mapBlockIndex.size());
for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
vSortedByHeight.reserve(m_block_index.size());
for (const std::pair<const uint256, CBlockIndex*>& item : m_block_index)
{
CBlockIndex* pindex = item.second;
vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex));
@ -4018,7 +4036,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
} else {
pindex->nChainTx = 0;
mapBlocksUnlinked.insert(std::make_pair(pindex->pprev, pindex));
m_blocks_unlinked.insert(std::make_pair(pindex->pprev, pindex));
}
} else {
pindex->nChainTx = pindex->nTx;
@ -4028,8 +4046,9 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
pindex->nStatus |= BLOCK_FAILED_CHILD;
setDirtyBlockIndex.insert(pindex);
}
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))
setBlockIndexCandidates.insert(pindex);
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->HaveTxsDownloaded() || pindex->pprev == nullptr)) {
block_index_candidates.insert(pindex);
}
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
pindexBestInvalid = pindex;
if (pindex->pprev)
@ -4041,9 +4060,21 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
return true;
}
void BlockManager::Unload() {
m_failed_blocks.clear();
m_blocks_unlinked.clear();
for (const BlockMap::value_type& entry : m_block_index) {
delete entry.second;
}
m_block_index.clear();
}
bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
if (!::ChainstateActive().LoadBlockIndex(chainparams.GetConsensus(), *pblocktree))
if (!g_blockman.LoadBlockIndex(
chainparams.GetConsensus(), *pblocktree, ::ChainstateActive().setBlockIndexCandidates))
return false;
// Load block file info
@ -4066,7 +4097,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
// Check presence of blk files
LogPrintf("Checking all blk files are present...\n");
std::set<int> setBlkDataFiles;
for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
for (const std::pair<const uint256, CBlockIndex*>& item : g_blockman.m_block_index)
{
CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
@ -4265,16 +4296,16 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view)
const CBlockIndex* pindexNew; // New tip during the interrupted flush.
const CBlockIndex* pindexFork = nullptr; // Latest block common to both the old and the new tip.
if (mapBlockIndex.count(hashHeads[0]) == 0) {
if (m_blockman.m_block_index.count(hashHeads[0]) == 0) {
return error("ReplayBlocks(): reorganization to unknown block requested");
}
pindexNew = mapBlockIndex[hashHeads[0]];
pindexNew = m_blockman.m_block_index[hashHeads[0]];
if (!hashHeads[1].IsNull()) { // The old tip is allowed to be 0, indicating it's the first flush.
if (mapBlockIndex.count(hashHeads[1]) == 0) {
if (m_blockman.m_block_index.count(hashHeads[1]) == 0) {
return error("ReplayBlocks(): reorganization from unknown block requested");
}
pindexOld = mapBlockIndex[hashHeads[1]];
pindexOld = m_blockman.m_block_index[hashHeads[1]];
pindexFork = LastCommonAncestor(pindexOld, pindexNew);
assert(pindexFork != nullptr);
}
@ -4340,10 +4371,10 @@ void CChainState::EraseBlockData(CBlockIndex* index)
setDirtyBlockIndex.insert(index);
// Update indexes
setBlockIndexCandidates.erase(index);
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> ret = mapBlocksUnlinked.equal_range(index->pprev);
auto ret = m_blockman.m_blocks_unlinked.equal_range(index->pprev);
while (ret.first != ret.second) {
if (ret.first->second == index) {
mapBlocksUnlinked.erase(ret.first++);
m_blockman.m_blocks_unlinked.erase(ret.first++);
} else {
++ret.first;
}
@ -4363,7 +4394,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// blocks will be dealt with below (releasing cs_main in between).
{
LOCK(cs_main);
for (const auto& entry : mapBlockIndex) {
for (const auto& entry : m_blockman.m_block_index) {
if (IsWitnessEnabled(entry.second->pprev, params.GetConsensus()) && !(entry.second->nStatus & BLOCK_OPT_WITNESS) && !m_chain.Contains(entry.second)) {
EraseBlockData(entry.second);
}
@ -4469,7 +4500,6 @@ bool RewindBlockIndex(const CChainParams& params) {
void CChainState::UnloadBlockIndex() {
nBlockSequenceId = 1;
m_failed_blocks.clear();
setBlockIndexCandidates.clear();
}
@ -4480,10 +4510,10 @@ void UnloadBlockIndex()
{
LOCK(cs_main);
::ChainActive().SetTip(nullptr);
g_blockman.Unload();
pindexBestInvalid = nullptr;
pindexBestHeader = nullptr;
mempool.clear();
mapBlocksUnlinked.clear();
vinfoBlockFile.clear();
nLastBlockFile = 0;
setDirtyBlockIndex.clear();
@ -4492,11 +4522,6 @@ void UnloadBlockIndex()
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
warningcache[b].clear();
}
for (const BlockMap::value_type& entry : mapBlockIndex) {
delete entry.second;
}
mapBlockIndex.clear();
fHavePruned = false;
::ChainstateActive().UnloadBlockIndex();
@ -4509,7 +4534,7 @@ bool LoadBlockIndex(const CChainParams& chainparams)
if (!fReindex) {
bool ret = LoadBlockIndexDB(chainparams);
if (!ret) return false;
needs_init = mapBlockIndex.empty();
needs_init = g_blockman.m_block_index.empty();
}
if (needs_init) {
@ -4529,10 +4554,10 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
LOCK(cs_main);
// Check whether we're already initialized by checking for genesis in
// mapBlockIndex. Note that we can't use m_chain here, since it is
// m_blockman.m_block_index. Note that we can't use m_chain here, since it is
// set based on the coins db, not the block index db, which is the only
// thing loaded at this point.
if (mapBlockIndex.count(chainparams.GenesisBlock().GetHash()))
if (m_blockman.m_block_index.count(chainparams.GenesisBlock().GetHash()))
return true;
try {
@ -4540,7 +4565,7 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr);
if (blockPos.IsNull())
return error("%s: writing genesis block to disk failed", __func__);
CBlockIndex *pindex = AddToBlockIndex(block);
CBlockIndex *pindex = m_blockman.AddToBlockIndex(block);
ReceivedBlockTransactions(block, pindex, blockPos, chainparams.GetConsensus());
} catch (const std::runtime_error& e) {
return error("%s: failed to write genesis block: %s", __func__, e.what());
@ -4685,20 +4710,20 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
LOCK(cs_main);
// During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
// so we have the genesis block in mapBlockIndex but no active chain. (A few of the tests when
// iterating the block tree require that m_chain has been initialized.)
// 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.)
if (m_chain.Height() < 0) {
assert(mapBlockIndex.size() <= 1);
assert(m_blockman.m_block_index.size() <= 1);
return;
}
// Build forward-pointing map of the entire block tree.
std::multimap<CBlockIndex*,CBlockIndex*> forward;
for (const std::pair<const uint256, CBlockIndex*>& entry : mapBlockIndex) {
for (const std::pair<const uint256, CBlockIndex*>& entry : m_blockman.m_block_index) {
forward.insert(std::make_pair(entry.second->pprev, entry.second));
}
assert(forward.size() == mapBlockIndex.size());
assert(forward.size() == m_blockman.m_block_index.size());
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(nullptr);
CBlockIndex *pindex = rangeGenesis.first->second;
@ -4752,7 +4777,7 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
assert(pindex->nHeight == nHeight); // nHeight must be consistent.
assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
assert(pindexFirstNotTreeValid == nullptr); // All mapBlockIndex entries must at least be TREE valid
assert(pindexFirstNotTreeValid == nullptr); // All m_blockman.m_block_index entries must at least be TREE valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE) assert(pindexFirstNotTreeValid == nullptr); // TREE valid implies all parents are TREE valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_CHAIN) assert(pindexFirstNotChainValid == nullptr); // CHAIN valid implies all parents are CHAIN valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_SCRIPTS) assert(pindexFirstNotScriptsValid == nullptr); // SCRIPTS valid implies all parents are SCRIPTS valid
@ -4771,13 +4796,13 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
}
// If some parent is missing, then it could be that this block was in
// setBlockIndexCandidates but had to be removed because of the missing data.
// In this case it must be in mapBlocksUnlinked -- see test below.
// In this case it must be in m_blocks_unlinked -- see test below.
}
} else { // If this block sorts worse than the current tip or some ancestor's block has never been seen, it cannot be in setBlockIndexCandidates.
assert(setBlockIndexCandidates.count(pindex) == 0);
}
// Check whether this block is in mapBlocksUnlinked.
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked = mapBlocksUnlinked.equal_range(pindex->pprev);
// 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);
bool foundInUnlinked = false;
while (rangeUnlinked.first != rangeUnlinked.second) {
assert(rangeUnlinked.first->first == pindex->pprev);
@ -4788,22 +4813,22 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
rangeUnlinked.first++;
}
if (pindex->pprev && (pindex->nStatus & BLOCK_HAVE_DATA) && pindexFirstNeverProcessed != nullptr && pindexFirstInvalid == nullptr) {
// If this block has block data available, some parent was never received, and has no invalid parents, it must be in mapBlocksUnlinked.
// If this block has block data available, some parent was never received, and has no invalid parents, it must be in m_blocks_unlinked.
assert(foundInUnlinked);
}
if (!(pindex->nStatus & BLOCK_HAVE_DATA)) assert(!foundInUnlinked); // Can't be in mapBlocksUnlinked if we don't HAVE_DATA
if (pindexFirstMissing == nullptr) assert(!foundInUnlinked); // We aren't missing data for any parent -- cannot be in mapBlocksUnlinked.
if (!(pindex->nStatus & BLOCK_HAVE_DATA)) assert(!foundInUnlinked); // Can't be in m_blocks_unlinked if we don't HAVE_DATA
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.
assert(fHavePruned); // We must have pruned.
// This block may have entered mapBlocksUnlinked if:
// This block may have entered m_blocks_unlinked if:
// - it has a descendant that at some point had more work than the
// tip, and
// - we tried switching to that descendant but were missing
// data for some intermediate block between m_chain and the
// tip.
// So if this block is itself better than m_chain.Tip() and it wasn't in
// setBlockIndexCandidates, then it must be in mapBlocksUnlinked.
// setBlockIndexCandidates, then it must be in m_blocks_unlinked.
if (!CBlockIndexWorkComparator()(pindex, m_chain.Tip()) && setBlockIndexCandidates.count(pindex) == 0) {
if (pindexFirstInvalid == nullptr) {
assert(foundInUnlinked);
@ -5046,10 +5071,10 @@ public:
CMainCleanup() {}
~CMainCleanup() {
// block headers
BlockMap::iterator it1 = mapBlockIndex.begin();
for (; it1 != mapBlockIndex.end(); it1++)
BlockMap::iterator it1 = g_blockman.m_block_index.begin();
for (; it1 != g_blockman.m_block_index.end(); it1++)
delete (*it1).second;
mapBlockIndex.clear();
g_blockman.m_block_index.clear();
}
};
static CMainCleanup instance_of_cmaincleanup;
@ -5071,8 +5096,8 @@ bool MainchainRPCCheck(const bool init)
std::vector<uint256> vblocksToReconsiderAgain;
for(uint256& blockhash : vblocksToReconsider) {
LOCK(cs_main);
if (mapBlockIndex.count(blockhash)) {
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
if (::BlockIndex().count(blockhash)) {
CBlockIndex* pblockindex = ::BlockIndex()[blockhash];
if ((pblockindex->nStatus & BLOCK_FAILED_MASK)) {
vblocksToReconsiderAgain.push_back(blockhash);
}
@ -5146,9 +5171,9 @@ bool MainchainRPCCheck(const bool init)
for(const uint256& blockhash : vblocksToReconsider) {
{
LOCK(cs_main);
if (mapBlockIndex.count(blockhash) == 0)
if (::BlockIndex().count(blockhash) == 0)
continue;
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
CBlockIndex* pblockindex = ::BlockIndex()[blockhash];
ResetBlockFailureFlags(pblockindex);
}
}
@ -5163,8 +5188,8 @@ bool MainchainRPCCheck(const bool init)
//Now to clear out now-valid blocks
for(const uint256& blockhash : vblocksToReconsider) {
LOCK(cs_main);
if (mapBlockIndex.count(blockhash)) {
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
if (::BlockIndex().count(blockhash)) {
CBlockIndex* pblockindex = ::BlockIndex()[blockhash];
//Marked as invalid still, put back into queue
if((pblockindex->nStatus & BLOCK_FAILED_MASK)) {