move-mostly: Make pindexBestHeader a ChainMan member

[META] In the next commit, we move the clearing of pindexBestHeader to
       ChainstateManager::Unload()
This commit is contained in:
Carl Dong 2020-12-24 16:18:46 -05:00
parent 5d670173a3
commit 0d567daf23
8 changed files with 45 additions and 42 deletions

View File

@ -1664,9 +1664,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
tip_info->block_time = chainman.ActiveChain().Tip() ? chainman.ActiveChain().Tip()->GetBlockTime() : Params().GenesisBlock().GetBlockTime(); tip_info->block_time = chainman.ActiveChain().Tip() ? chainman.ActiveChain().Tip()->GetBlockTime() : Params().GenesisBlock().GetBlockTime();
tip_info->verification_progress = GuessVerificationProgress(Params().TxData(), chainman.ActiveChain().Tip()); tip_info->verification_progress = GuessVerificationProgress(Params().TxData(), chainman.ActiveChain().Tip());
} }
if (tip_info && ::pindexBestHeader) { if (tip_info && chainman.pindexBestHeader) {
tip_info->header_height = ::pindexBestHeader->nHeight; tip_info->header_height = chainman.pindexBestHeader->nHeight;
tip_info->header_time = ::pindexBestHeader->GetBlockTime(); tip_info->header_time = chainman.pindexBestHeader->GetBlockTime();
} }
} }
LogPrintf("nBestHeight = %d\n", chain_active_height); LogPrintf("nBestHeight = %d\n", chain_active_height);

View File

@ -1499,9 +1499,9 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
if (m_chainman.ActiveChain().Contains(pindex)) return true; if (m_chainman.ActiveChain().Contains(pindex)) return true;
return pindex->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != nullptr) && return pindex->IsValid(BLOCK_VALID_SCRIPTS) && (m_chainman.pindexBestHeader != nullptr) &&
(pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) && (m_chainman.pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT); (GetBlockProofEquivalentTime(*m_chainman.pindexBestHeader, *pindex, *m_chainman.pindexBestHeader, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT);
} }
std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBlockIndex& block_index) std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBlockIndex& block_index)
@ -1896,7 +1896,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion()); const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
// disconnect node in case we have reached the outbound limit for serving historical blocks // disconnect node in case we have reached the outbound limit for serving historical blocks
if (m_connman.OutboundTargetReached(true) && if (m_connman.OutboundTargetReached(true) &&
(((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk()) && (((m_chainman.pindexBestHeader != nullptr) && (m_chainman.pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk()) &&
!pfrom.HasPermission(NetPermissionFlags::Download) // nodes with the download permission may exceed target !pfrom.HasPermission(NetPermissionFlags::Download) // nodes with the download permission may exceed target
) { ) {
LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom.GetId()); LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom.GetId());
@ -2173,11 +2173,11 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
// nUnconnectingHeaders gets reset back to 0. // nUnconnectingHeaders gets reset back to 0.
if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) { if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
nodestate->nUnconnectingHeaders++; nodestate->nUnconnectingHeaders++;
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexBestHeader), uint256())); m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.pindexBestHeader), uint256()));
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n", LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
headers[0].GetHash().ToString(), headers[0].GetHash().ToString(),
headers[0].hashPrevBlock.ToString(), headers[0].hashPrevBlock.ToString(),
pindexBestHeader->nHeight, m_chainman.pindexBestHeader->nHeight,
pfrom.GetId(), nodestate->nUnconnectingHeaders); pfrom.GetId(), nodestate->nUnconnectingHeaders);
// Set hashLastUnknownBlock for this peer, so that if we // Set hashLastUnknownBlock for this peer, so that if we
// eventually get the headers - even from a different peer - // eventually get the headers - even from a different peer -
@ -2235,7 +2235,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
if (nCount == MAX_HEADERS_RESULTS) { if (nCount == MAX_HEADERS_RESULTS) {
// Headers message had its maximum size; the peer may have more headers. // Headers message had its maximum size; the peer may have more headers.
// TODO: optimize: if pindexLast is an ancestor of m_chainman.ActiveChain().Tip or pindexBestHeader, continue // TODO: optimize: if pindexLast is an ancestor of m_chainman.ActiveChain().Tip or m_chainman.pindexBestHeader, continue
// from there instead. // from there instead.
LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height); pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
@ -3102,8 +3102,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
} }
if (best_block != nullptr) { if (best_block != nullptr) {
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexBestHeader), *best_block)); m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.pindexBestHeader), *best_block));
LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, best_block->ToString(), pfrom.GetId()); LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", m_chainman.pindexBestHeader->nHeight, best_block->ToString(), pfrom.GetId());
} }
return; return;
@ -3549,7 +3549,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock)) { if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers // Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
if (!m_chainman.ActiveChainstate().IsInitialBlockDownload()) if (!m_chainman.ActiveChainstate().IsInitialBlockDownload())
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexBestHeader), uint256())); m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.pindexBestHeader), uint256()));
return; return;
} }
@ -4670,28 +4670,29 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
CNodeState &state = *State(pto->GetId()); CNodeState &state = *State(pto->GetId());
// Start block sync // Start block sync
if (pindexBestHeader == nullptr) if (m_chainman.pindexBestHeader == nullptr) {
pindexBestHeader = m_chainman.ActiveChain().Tip(); m_chainman.pindexBestHeader = m_chainman.ActiveChain().Tip();
}
bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->IsAddrFetchConn()); // Download if this is a nice peer, or we have no nice peers and this one might do. bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->IsAddrFetchConn()); // Download if this is a nice peer, or we have no nice peers and this one might do.
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) { if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
// Only actively request headers from a single peer, unless we're close to today. // Only actively request headers from a single peer, unless we're close to today.
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) { if ((nSyncStarted == 0 && fFetch) || m_chainman.pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
state.fSyncStarted = true; state.fSyncStarted = true;
state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE + state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
( (
// Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling // Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling
// to maintain precision // to maintain precision
std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} * std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} *
(GetAdjustedTime() - pindexBestHeader->GetBlockTime()) / consensusParams.nPowTargetSpacing (GetAdjustedTime() - m_chainman.pindexBestHeader->GetBlockTime()) / consensusParams.nPowTargetSpacing
); );
nSyncStarted++; nSyncStarted++;
const CBlockIndex *pindexStart = pindexBestHeader; const CBlockIndex* pindexStart = m_chainman.pindexBestHeader;
/* If possible, start at the block preceding the currently /* If possible, start at the block preceding the currently
best known header. This ensures that we always get a best known header. This ensures that we always get a
non-empty list of headers back as long as the peer non-empty list of headers back as long as the peer
is up-to-date. With a non-empty response, we can initialise is up-to-date. With a non-empty response, we can initialise
the peer's known best block. This wouldn't be possible the peer's known best block. This wouldn't be possible
if we requested starting at pindexBestHeader and if we requested starting at m_chainman.pindexBestHeader and
got back an empty response. */ got back an empty response. */
if (pindexStart->pprev) if (pindexStart->pprev)
pindexStart = pindexStart->pprev; pindexStart = pindexStart->pprev;
@ -5016,7 +5017,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Check for headers sync timeouts // Check for headers sync timeouts
if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) { if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) {
// Detect whether this is a stalling initial-headers-sync peer // Detect whether this is a stalling initial-headers-sync peer
if (pindexBestHeader->GetBlockTime() <= GetAdjustedTime() - 24 * 60 * 60) { if (m_chainman.pindexBestHeader->GetBlockTime() <= GetAdjustedTime() - 24 * 60 * 60) {
if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) { if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) {
// Disconnect a peer (without NetPermissionFlags::NoBan permission) if it is our only sync peer, // Disconnect a peer (without NetPermissionFlags::NoBan permission) if it is our only sync peer,
// and we have others we could be using instead. // and we have others we could be using instead.

View File

@ -81,7 +81,7 @@ const CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const
return it == m_block_index.end() ? nullptr : &it->second; return it == m_block_index.end() ? nullptr : &it->second;
} }
CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block) CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block, CBlockIndex*& best_header)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
@ -106,8 +106,9 @@ CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block)
pindexNew->nTimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) : pindexNew->nTime); pindexNew->nTimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) : pindexNew->nTime);
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew); pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
pindexNew->RaiseValidity(BLOCK_VALID_TREE); pindexNew->RaiseValidity(BLOCK_VALID_TREE);
if (pindexBestHeader == nullptr || pindexBestHeader->nChainWork < pindexNew->nChainWork) if (best_header == nullptr || best_header->nChainWork < pindexNew->nChainWork) {
pindexBestHeader = pindexNew; best_header = pindexNew;
}
m_dirty_blockindex.insert(pindexNew); m_dirty_blockindex.insert(pindexNew);

View File

@ -147,7 +147,7 @@ public:
/** Clear all data members. */ /** Clear all data members. */
void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main); void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main); CBlockIndex* AddToBlockIndex(const CBlockHeader& block, CBlockIndex*& best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Create a new block index entry for a given block hash */ /** Create a new block index entry for a given block hash */
CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

View File

@ -212,9 +212,10 @@ public:
bool getHeaderTip(int& height, int64_t& block_time) override bool getHeaderTip(int& height, int64_t& block_time) override
{ {
LOCK(::cs_main); LOCK(::cs_main);
if (::pindexBestHeader) { auto best_header = chainman().pindexBestHeader;
height = ::pindexBestHeader->nHeight; if (best_header) {
block_time = ::pindexBestHeader->GetBlockTime(); height = best_header->nHeight;
block_time = best_header->GetBlockTime();
return true; return true;
} }
return false; return false;

View File

@ -1207,7 +1207,7 @@ RPCHelpMan getblockchaininfo()
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("chain", Params().NetworkIDString()); obj.pushKV("chain", Params().NetworkIDString());
obj.pushKV("blocks", height); obj.pushKV("blocks", height);
obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1); obj.pushKV("headers", chainman.pindexBestHeader ? chainman.pindexBestHeader->nHeight : -1);
obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex()); obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
obj.pushKV("difficulty", (double)GetDifficulty(tip)); obj.pushKV("difficulty", (double)GetDifficulty(tip));
obj.pushKV("time", (int64_t)tip->nTime); obj.pushKV("time", (int64_t)tip->nTime);

View File

@ -120,7 +120,6 @@ const std::vector<std::string> CHECKLEVEL_DOC {
*/ */
RecursiveMutex cs_main; RecursiveMutex cs_main;
CBlockIndex *pindexBestHeader = nullptr;
Mutex g_best_block_mutex; Mutex g_best_block_mutex;
std::condition_variable g_best_block_cv; std::condition_variable g_best_block_cv;
uint256 g_best_block; uint256 g_best_block;
@ -280,8 +279,9 @@ static bool IsCurrentForFeeEstimation(CChainState& active_chainstate) EXCLUSIVE_
return false; return false;
if (active_chainstate.m_chain.Tip()->GetBlockTime() < count_seconds(GetTime<std::chrono::seconds>() - MAX_FEE_ESTIMATION_TIP_AGE)) if (active_chainstate.m_chain.Tip()->GetBlockTime() < count_seconds(GetTime<std::chrono::seconds>() - MAX_FEE_ESTIMATION_TIP_AGE))
return false; return false;
if (active_chainstate.m_chain.Height() < pindexBestHeader->nHeight - 1) if (active_chainstate.m_chain.Height() < active_chainstate.m_chainman.pindexBestHeader->nHeight - 1) {
return false; return false;
}
return true; return true;
} }
@ -1602,8 +1602,8 @@ void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) { if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) {
m_chainman.m_best_invalid = pindexNew; m_chainman.m_best_invalid = pindexNew;
} }
if (pindexBestHeader != nullptr && pindexBestHeader->GetAncestor(pindexNew->nHeight) == pindexNew) { if (m_chainman.pindexBestHeader != nullptr && m_chainman.pindexBestHeader->GetAncestor(pindexNew->nHeight) == pindexNew) {
pindexBestHeader = m_chain.Tip(); m_chainman.pindexBestHeader = m_chain.Tip();
} }
LogPrintf("%s: invalid block=%s height=%d log2_work=%f date=%s\n", __func__, LogPrintf("%s: invalid block=%s height=%d log2_work=%f date=%s\n", __func__,
@ -2029,8 +2029,8 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
BlockMap::const_iterator it = m_blockman.m_block_index.find(hashAssumeValid); BlockMap::const_iterator it = m_blockman.m_block_index.find(hashAssumeValid);
if (it != m_blockman.m_block_index.end()) { if (it != m_blockman.m_block_index.end()) {
if (it->second.GetAncestor(pindex->nHeight) == pindex && if (it->second.GetAncestor(pindex->nHeight) == pindex &&
pindexBestHeader->GetAncestor(pindex->nHeight) == pindex && m_chainman.pindexBestHeader->GetAncestor(pindex->nHeight) == pindex &&
pindexBestHeader->nChainWork >= nMinimumChainWork) { m_chainman.pindexBestHeader->nChainWork >= nMinimumChainWork) {
// This block is a member of the assumed verified chain and an ancestor of the best header. // This block is a member of the assumed verified chain and an ancestor of the best header.
// Script verification is skipped when connecting blocks under the // Script verification is skipped when connecting blocks under the
// assumevalid block. Assuming the assumevalid block is valid this // assumevalid block. Assuming the assumevalid block is valid this
@ -2045,7 +2045,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// artificially set the default assumed verified block further back. // artificially set the default assumed verified block further back.
// The test against nMinimumChainWork prevents the skipping when denied access to any chain at // The test against nMinimumChainWork prevents the skipping when denied access to any chain at
// least as good as the expected chain. // least as good as the expected chain.
fScriptChecks = (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, m_params.GetConsensus()) <= 60 * 60 * 24 * 7 * 2); fScriptChecks = (GetBlockProofEquivalentTime(*m_chainman.pindexBestHeader, *pindex, *m_chainman.pindexBestHeader, m_params.GetConsensus()) <= 60 * 60 * 24 * 7 * 2);
} }
} }
} }
@ -2904,7 +2904,7 @@ static bool NotifyHeaderTip(CChainState& chainstate) LOCKS_EXCLUDED(cs_main) {
CBlockIndex* pindexHeader = nullptr; CBlockIndex* pindexHeader = nullptr;
{ {
LOCK(cs_main); LOCK(cs_main);
pindexHeader = pindexBestHeader; pindexHeader = chainstate.m_chainman.pindexBestHeader;
if (pindexHeader != pindexHeaderOld) { if (pindexHeader != pindexHeaderOld) {
fNotify = true; fNotify = true;
@ -3621,7 +3621,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
} }
} }
} }
CBlockIndex* pindex{m_blockman.AddToBlockIndex(block)}; CBlockIndex* pindex{m_blockman.AddToBlockIndex(block, pindexBestHeader)};
if (ppindex) if (ppindex)
*ppindex = pindex; *ppindex = pindex;
@ -4122,7 +4122,7 @@ void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman)
{ {
AssertLockHeld(::cs_main); AssertLockHeld(::cs_main);
chainman.Unload(); chainman.Unload();
pindexBestHeader = nullptr; chainman.pindexBestHeader = nullptr;
if (mempool) mempool->clear(); if (mempool) mempool->clear();
g_versionbitscache.Clear(); g_versionbitscache.Clear();
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) { for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
@ -4239,7 +4239,7 @@ bool CChainState::LoadGenesisBlock()
if (blockPos.IsNull()) { if (blockPos.IsNull()) {
return error("%s: writing genesis block to disk failed", __func__); return error("%s: writing genesis block to disk failed", __func__);
} }
CBlockIndex *pindex = m_blockman.AddToBlockIndex(block); CBlockIndex* pindex = m_blockman.AddToBlockIndex(block, m_chainman.pindexBestHeader);
ReceivedBlockTransactions(block, pindex, blockPos); ReceivedBlockTransactions(block, pindex, blockPos);
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
return error("%s: failed to write genesis block: %s", __func__, e.what()); return error("%s: failed to write genesis block: %s", __func__, e.what());

View File

@ -131,9 +131,6 @@ extern uint256 hashAssumeValid;
/** Minimum work we will assume exists on some valid chain. */ /** Minimum work we will assume exists on some valid chain. */
extern arith_uint256 nMinimumChainWork; extern arith_uint256 nMinimumChainWork;
/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader;
/** Documentation for argument 'checklevel'. */ /** Documentation for argument 'checklevel'. */
extern const std::vector<std::string> CHECKLEVEL_DOC; extern const std::vector<std::string> CHECKLEVEL_DOC;
@ -883,6 +880,9 @@ public:
*/ */
std::set<CBlockIndex*> m_failed_blocks; std::set<CBlockIndex*> m_failed_blocks;
/** Best header we've seen so far (used for getheaders queries' starting points). */
CBlockIndex* pindexBestHeader = nullptr;
//! The total number of bytes available for us to use across all in-memory //! The total number of bytes available for us to use across all in-memory
//! coins caches. This will be split somehow across chainstates. //! coins caches. This will be split somehow across chainstates.
int64_t m_total_coinstip_cache{0}; int64_t m_total_coinstip_cache{0};