mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
merge bitcoin#24909: Move and rename pindexBestHeader, fHavePruned
This commit is contained in:
parent
70485cb2f5
commit
bcafa282a3
@ -45,7 +45,7 @@ static void BlockToJsonVerbose(benchmark::Bench& bench)
|
|||||||
TestBlockAndIndex data;
|
TestBlockAndIndex data;
|
||||||
const LLMQContext& llmq_ctx = *data.testing_setup->m_node.llmq_ctx;
|
const LLMQContext& llmq_ctx = *data.testing_setup->m_node.llmq_ctx;
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
auto univalue = blockToJSON(data.block, &data.blockindex, &data.blockindex, *llmq_ctx.clhandler, *llmq_ctx.isman, /*verbose*/ true);
|
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, &data.blockindex, &data.blockindex, *llmq_ctx.clhandler, *llmq_ctx.isman, /*verbose*/ true);
|
||||||
ankerl::nanobench::doNotOptimizeAway(univalue);
|
ankerl::nanobench::doNotOptimizeAway(univalue);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ static void BlockToJsonVerboseWrite(benchmark::Bench& bench)
|
|||||||
{
|
{
|
||||||
TestBlockAndIndex data;
|
TestBlockAndIndex data;
|
||||||
const LLMQContext& llmq_ctx = *data.testing_setup->m_node.llmq_ctx;
|
const LLMQContext& llmq_ctx = *data.testing_setup->m_node.llmq_ctx;
|
||||||
auto univalue = blockToJSON(data.block, &data.blockindex, &data.blockindex, *llmq_ctx.clhandler, *llmq_ctx.isman, /*verbose*/ true);
|
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, &data.blockindex, &data.blockindex, *llmq_ctx.clhandler, *llmq_ctx.isman, /*verbose*/ true);
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
auto str = univalue.write();
|
auto str = univalue.write();
|
||||||
ankerl::nanobench::doNotOptimizeAway(str);
|
ankerl::nanobench::doNotOptimizeAway(str);
|
||||||
|
@ -79,7 +79,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
|
|||||||
if (pindexNew == pindexFork) // blocks were disconnected without any new ones
|
if (pindexNew == pindexFork) // blocks were disconnected without any new ones
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_mn_sync.UpdatedBlockTip(pindexNew, fInitialDownload);
|
m_mn_sync.UpdatedBlockTip(m_chainman.m_best_header, pindexNew, fInitialDownload);
|
||||||
|
|
||||||
// Update global DIP0001 activation status
|
// Update global DIP0001 activation status
|
||||||
fDIP0001ActiveAtTip = pindexNew->nHeight >= Params().GetConsensus().DIP0001Height;
|
fDIP0001ActiveAtTip = pindexNew->nHeight >= Params().GetConsensus().DIP0001Height;
|
||||||
|
12
src/init.cpp
12
src/init.cpp
@ -1890,7 +1890,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
|
|
||||||
if (ShutdownRequested()) break;
|
if (ShutdownRequested()) break;
|
||||||
|
|
||||||
// LoadBlockIndex will load fHavePruned if we've ever removed a
|
// LoadBlockIndex will load m_have_pruned if we've ever removed a
|
||||||
// block file from disk.
|
// block file from disk.
|
||||||
// Note that it also sets fReindex based on the disk flag!
|
// Note that it also sets fReindex based on the disk flag!
|
||||||
// From here on out fReindex and fReset mean something different!
|
// From here on out fReindex and fReset mean something different!
|
||||||
@ -1936,7 +1936,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
|
|
||||||
// Check for changed -prune state. What we are concerned about is a user who has pruned blocks
|
// Check for changed -prune state. What we are concerned about is a user who has pruned blocks
|
||||||
// in the past, but is now trying to run unpruned.
|
// in the past, but is now trying to run unpruned.
|
||||||
if (fHavePruned && !fPruneMode) {
|
if (chainman.m_blockman.m_have_pruned && !fPruneMode) {
|
||||||
strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain");
|
strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2022,7 +2022,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
for (CChainState* chainstate : chainman.GetAll()) {
|
for (CChainState* chainstate : chainman.GetAll()) {
|
||||||
if (!is_coinsview_empty(chainstate)) {
|
if (!is_coinsview_empty(chainstate)) {
|
||||||
uiInterface.InitMessage(_("Verifying blocks…").translated);
|
uiInterface.InitMessage(_("Verifying blocks…").translated);
|
||||||
if (fHavePruned && args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
|
if (chainman.m_blockman.m_have_pruned && args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
|
||||||
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
|
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
|
||||||
MIN_BLOCKS_TO_KEEP);
|
MIN_BLOCKS_TO_KEEP);
|
||||||
}
|
}
|
||||||
@ -2328,9 +2328,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
tip_info->block_hash = chainman.ActiveChain().Tip() ? chainman.ActiveChain().Tip()->GetBlockHash() : Params().GenesisBlock().GetHash();
|
tip_info->block_hash = chainman.ActiveChain().Tip() ? chainman.ActiveChain().Tip()->GetBlockHash() : Params().GenesisBlock().GetHash();
|
||||||
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.m_best_header) {
|
||||||
tip_info->header_height = ::pindexBestHeader->nHeight;
|
tip_info->header_height = chainman.m_best_header->nHeight;
|
||||||
tip_info->header_time = ::pindexBestHeader->GetBlockTime();
|
tip_info->header_time = chainman.m_best_header->GetBlockTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogPrintf("nBestHeight = %d\n", chain_active_height);
|
LogPrintf("nBestHeight = %d\n", chain_active_height);
|
||||||
|
@ -329,7 +329,7 @@ void CMasternodeSync::NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitia
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload)
|
void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexTip, const CBlockIndex *pindexNew, bool fInitialDownload)
|
||||||
{
|
{
|
||||||
LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload);
|
LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload);
|
||||||
nTimeLastUpdateBlockTip = GetTime<std::chrono::seconds>().count();
|
nTimeLastUpdateBlockTip = GetTime<std::chrono::seconds>().count();
|
||||||
@ -353,7 +353,6 @@ void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitia
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note: since we sync headers first, it should be ok to use this
|
// Note: since we sync headers first, it should be ok to use this
|
||||||
CBlockIndex* pindexTip = WITH_LOCK(cs_main, return pindexBestHeader);
|
|
||||||
if (pindexTip == nullptr) return;
|
if (pindexTip == nullptr) return;
|
||||||
bool fReachedBestHeaderNew = pindexNew->GetBlockHash() == pindexTip->GetBlockHash();
|
bool fReachedBestHeaderNew = pindexNew->GetBlockHash() == pindexTip->GetBlockHash();
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ public:
|
|||||||
|
|
||||||
void AcceptedBlockHeader(const CBlockIndex *pindexNew);
|
void AcceptedBlockHeader(const CBlockIndex *pindexNew);
|
||||||
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload);
|
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload);
|
||||||
void UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload);
|
void UpdatedBlockTip(const CBlockIndex *pindexTip, const CBlockIndex *pindexNew, bool fInitialDownload);
|
||||||
|
|
||||||
void DoMaintenance();
|
void DoMaintenance();
|
||||||
};
|
};
|
||||||
|
@ -1856,9 +1856,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.m_best_header != nullptr) &&
|
||||||
(pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
|
(m_chainman.m_best_header->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
|
||||||
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT);
|
(GetBlockProofEquivalentTime(*m_chainman.m_best_header, *pindex, *m_chainman.m_best_header, 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)
|
||||||
@ -2434,7 +2434,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.m_best_header != nullptr) && (m_chainman.m_best_header->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());
|
||||||
@ -2824,13 +2824,13 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
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++;
|
||||||
std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
|
std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
|
||||||
m_connman.PushMessage(&pfrom, msgMaker.Make(msg_type, m_chainman.ActiveChain().GetLocator(pindexBestHeader), uint256()));
|
m_connman.PushMessage(&pfrom, msgMaker.Make(msg_type, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), uint256()));
|
||||||
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending %s (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
|
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending %s (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
|
||||||
headers[0].GetHash().ToString(),
|
headers[0].GetHash().ToString(),
|
||||||
headers[0].hashPrevBlock.ToString(),
|
headers[0].hashPrevBlock.ToString(),
|
||||||
msg_type,
|
msg_type,
|
||||||
pindexBestHeader->nHeight,
|
m_chainman.m_best_header->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 -
|
||||||
// we can use this peer to download.
|
// we can use this peer to download.
|
||||||
@ -2887,7 +2887,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.m_best_header, continue
|
||||||
// from there instead.
|
// from there instead.
|
||||||
std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
|
std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
|
||||||
LogPrint(BCLog::NET, "more %s (%d) to end to peer=%d (startheight:%d)\n",
|
LogPrint(BCLog::NET, "more %s (%d) to end to peer=%d (startheight:%d)\n",
|
||||||
@ -3819,7 +3819,7 @@ void PeerManagerImpl::ProcessMessage(
|
|||||||
// Download if this is a nice peer, or we have no nice peers and this one might do.
|
// Download if this is a nice peer, or we have no nice peers and this one might do.
|
||||||
bool fFetch = state->fPreferredDownload || (nPreferredDownload == 0 && !pfrom.IsAddrFetchConn());
|
bool fFetch = state->fPreferredDownload || (nPreferredDownload == 0 && !pfrom.IsAddrFetchConn());
|
||||||
// Only actively request headers from a single peer, unless we're close to end of initial download.
|
// Only actively request headers from a single peer, unless we're close to end of initial download.
|
||||||
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) {
|
if ((nSyncStarted == 0 && fFetch) || m_chainman.m_best_header->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) {
|
||||||
// Make sure to mark this peer as the one we are currently syncing with etc.
|
// Make sure to mark this peer as the one we are currently syncing with etc.
|
||||||
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 +
|
||||||
@ -3827,7 +3827,7 @@ void PeerManagerImpl::ProcessMessage(
|
|||||||
// 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()) / m_chainparams.GetConsensus().nPowTargetSpacing
|
(GetAdjustedTime() - m_chainman.m_best_header->GetBlockTime()) / m_chainparams.GetConsensus().nPowTargetSpacing
|
||||||
);
|
);
|
||||||
nSyncStarted++;
|
nSyncStarted++;
|
||||||
// Headers-first is the primary method of announcement on
|
// Headers-first is the primary method of announcement on
|
||||||
@ -3872,8 +3872,8 @@ void PeerManagerImpl::ProcessMessage(
|
|||||||
}
|
}
|
||||||
if (best_block != nullptr) {
|
if (best_block != nullptr) {
|
||||||
std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
|
std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
|
||||||
m_connman.PushMessage(&pfrom, msgMaker.Make(msg_type, m_chainman.ActiveChain().GetLocator(pindexBestHeader), *best_block));
|
m_connman.PushMessage(&pfrom, msgMaker.Make(msg_type, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), *best_block));
|
||||||
LogPrint(BCLog::NET, "%s (%d) %s to peer=%d\n", msg_type, pindexBestHeader->nHeight, best_block->ToString(), pfrom.GetId());
|
LogPrint(BCLog::NET, "%s (%d) %s to peer=%d\n", msg_type, m_chainman.m_best_header->nHeight, best_block->ToString(), pfrom.GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -4289,7 +4289,7 @@ void PeerManagerImpl::ProcessMessage(
|
|||||||
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((pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexBestHeader), uint256()));
|
m_connman.PushMessage(&pfrom, msgMaker.Make((pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), uint256()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5445,28 +5445,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.m_best_header == nullptr) {
|
||||||
pindexBestHeader = m_chainman.ActiveChain().Tip();
|
m_chainman.m_best_header = 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 && pto->CanRelay()) {
|
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex && pto->CanRelay()) {
|
||||||
// Only actively request headers from a single peer, unless we're close to end of initial download.
|
// Only actively request headers from a single peer, unless we're close to end of initial download.
|
||||||
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) {
|
if ((nSyncStarted == 0 && fFetch) || m_chainman.m_best_header->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) {
|
||||||
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.m_best_header->GetBlockTime()) / consensusParams.nPowTargetSpacing
|
||||||
);
|
);
|
||||||
nSyncStarted++;
|
nSyncStarted++;
|
||||||
const CBlockIndex *pindexStart = pindexBestHeader;
|
const CBlockIndex* pindexStart = m_chainman.m_best_header;
|
||||||
/* 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.m_best_header and
|
||||||
got back an empty response. */
|
got back an empty response. */
|
||||||
if (pindexStart->pprev)
|
if (pindexStart->pprev)
|
||||||
pindexStart = pindexStart->pprev;
|
pindexStart = pindexStart->pprev;
|
||||||
@ -5835,7 +5836,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() - nMaxTipAge) {
|
if (m_chainman.m_best_header->GetBlockTime() <= GetAdjustedTime() - nMaxTipAge) {
|
||||||
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.
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
std::atomic_bool fImporting(false);
|
std::atomic_bool fImporting(false);
|
||||||
std::atomic_bool fReindex(false);
|
std::atomic_bool fReindex(false);
|
||||||
bool fHavePruned = false;
|
|
||||||
bool fPruneMode = false;
|
bool fPruneMode = false;
|
||||||
uint64_t nPruneTarget = 0;
|
uint64_t nPruneTarget = 0;
|
||||||
|
|
||||||
@ -86,7 +85,8 @@ 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, const uint256& hash, enum BlockStatus nStatus)
|
CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block, const uint256& hash, CBlockIndex*& best_header,
|
||||||
|
enum BlockStatus nStatus)
|
||||||
{
|
{
|
||||||
assert(!(nStatus & BLOCK_FAILED_MASK)); // no failed blocks allowed
|
assert(!(nStatus & BLOCK_FAILED_MASK)); // no failed blocks allowed
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
@ -113,8 +113,8 @@ CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block, const uint
|
|||||||
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
|
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
|
||||||
if (nStatus & BLOCK_VALID_MASK) {
|
if (nStatus & BLOCK_VALID_MASK) {
|
||||||
pindexNew->RaiseValidity(nStatus);
|
pindexNew->RaiseValidity(nStatus);
|
||||||
if (pindexBestHeader == nullptr || pindexBestHeader->nChainWork < pindexNew->nChainWork) {
|
if (best_header == nullptr || best_header->nChainWork < pindexNew->nChainWork) {
|
||||||
pindexBestHeader = pindexNew;
|
best_header = pindexNew;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pindexNew->RaiseValidity(BLOCK_VALID_TREE); // required validity level
|
pindexNew->RaiseValidity(BLOCK_VALID_TREE); // required validity level
|
||||||
@ -309,8 +309,6 @@ bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params)
|
|||||||
if (pindex->pprev) {
|
if (pindex->pprev) {
|
||||||
pindex->BuildSkip();
|
pindex->BuildSkip();
|
||||||
}
|
}
|
||||||
if (pindex->IsValid(BLOCK_VALID_TREE) && (pindexBestHeader == nullptr || CBlockIndexWorkComparator()(pindexBestHeader, pindex)))
|
|
||||||
pindexBestHeader = pindex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -327,6 +325,8 @@ void BlockManager::Unload()
|
|||||||
m_last_blockfile = 0;
|
m_last_blockfile = 0;
|
||||||
m_dirty_blockindex.clear();
|
m_dirty_blockindex.clear();
|
||||||
m_dirty_fileinfo.clear();
|
m_dirty_fileinfo.clear();
|
||||||
|
|
||||||
|
m_have_pruned = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockManager::WriteBlockIndexDB()
|
bool BlockManager::WriteBlockIndexDB()
|
||||||
@ -389,8 +389,8 @@ bool BlockManager::LoadBlockIndexDB()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check whether we have ever pruned block & undo files
|
// Check whether we have ever pruned block & undo files
|
||||||
m_block_tree_db->ReadFlag("prunedblockfiles", fHavePruned);
|
m_block_tree_db->ReadFlag("prunedblockfiles", m_have_pruned);
|
||||||
if (fHavePruned) {
|
if (m_have_pruned) {
|
||||||
LogPrintf("LoadBlockIndexDB(): Block files have previously been pruned\n");
|
LogPrintf("LoadBlockIndexDB(): Block files have previously been pruned\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,10 +428,10 @@ const CBlockIndex* BlockManager::GetLastCheckpoint(const CCheckpointData& data)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBlockPruned(const CBlockIndex* pblockindex)
|
bool BlockManager::IsBlockPruned(const CBlockIndex* pblockindex)
|
||||||
{
|
{
|
||||||
AssertLockHeld(::cs_main);
|
AssertLockHeld(::cs_main);
|
||||||
return (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0);
|
return (m_have_pruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're using -prune with -reindex, then delete block files that will be ignored by the
|
// If we're using -prune with -reindex, then delete block files that will be ignored by the
|
||||||
|
@ -49,8 +49,6 @@ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
|
|||||||
extern std::atomic_bool fImporting;
|
extern std::atomic_bool fImporting;
|
||||||
extern std::atomic_bool fReindex;
|
extern std::atomic_bool fReindex;
|
||||||
/** Pruning-related variables and constants */
|
/** Pruning-related variables and constants */
|
||||||
/** True if any block files have ever been pruned. */
|
|
||||||
extern bool fHavePruned;
|
|
||||||
/** True if we're running in -prune mode. */
|
/** True if we're running in -prune mode. */
|
||||||
extern bool fPruneMode;
|
extern bool fPruneMode;
|
||||||
/** Number of bytes of block files that we're trying to stay below. */
|
/** Number of bytes of block files that we're trying to stay below. */
|
||||||
@ -160,7 +158,9 @@ 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, const uint256& hash, enum BlockStatus nStatus = BLOCK_VALID_TREE) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
CBlockIndex* AddToBlockIndex(const CBlockHeader& block, const uint256& hash, CBlockIndex*& best_header,
|
||||||
|
enum BlockStatus nStatus = BLOCK_VALID_TREE)
|
||||||
|
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);
|
||||||
|
|
||||||
@ -184,6 +184,12 @@ public:
|
|||||||
//! Returns last CBlockIndex* that is a checkpoint
|
//! Returns last CBlockIndex* that is a checkpoint
|
||||||
const CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
const CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
|
||||||
|
/** True if any block files have ever been pruned. */
|
||||||
|
bool m_have_pruned = false;
|
||||||
|
|
||||||
|
//! Check whether the block associated with this index entry is pruned or not.
|
||||||
|
bool IsBlockPruned(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the spend height, which is one more than the inputs.GetBestBlock().
|
* Return the spend height, which is one more than the inputs.GetBestBlock().
|
||||||
* While checking, GetBestBlock() refers to the parent block. (protected by cs_main)
|
* While checking, GetBestBlock() refers to the parent block. (protected by cs_main)
|
||||||
@ -197,9 +203,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Check whether the block associated with this index entry is pruned or not.
|
|
||||||
bool IsBlockPruned(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
|
||||||
|
|
||||||
void CleanupBlockRevFiles();
|
void CleanupBlockRevFiles();
|
||||||
|
|
||||||
/** Open a block file (blk?????.dat) */
|
/** Open a block file (blk?????.dat) */
|
||||||
|
@ -419,9 +419,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().m_best_header;
|
||||||
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;
|
||||||
@ -934,7 +935,7 @@ public:
|
|||||||
bool havePruned() override
|
bool havePruned() override
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
return ::fHavePruned;
|
return m_node.chainman->m_blockman.m_have_pruned;
|
||||||
}
|
}
|
||||||
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
|
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
|
||||||
bool isInitialBlockDownload() override {
|
bool isInitialBlockDownload() override {
|
||||||
|
10
src/rest.cpp
10
src/rest.cpp
@ -273,10 +273,10 @@ static bool rest_block(const CoreContext& context,
|
|||||||
CBlock block;
|
CBlock block;
|
||||||
const CBlockIndex* pblockindex = nullptr;
|
const CBlockIndex* pblockindex = nullptr;
|
||||||
const CBlockIndex* tip = nullptr;
|
const CBlockIndex* tip = nullptr;
|
||||||
|
ChainstateManager* maybe_chainman = GetChainman(context, req);
|
||||||
|
if (!maybe_chainman) return false;
|
||||||
|
ChainstateManager& chainman = *maybe_chainman;
|
||||||
{
|
{
|
||||||
ChainstateManager* maybe_chainman = GetChainman(context, req);
|
|
||||||
if (!maybe_chainman) return false;
|
|
||||||
ChainstateManager& chainman = *maybe_chainman;
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
tip = chainman.ActiveChain().Tip();
|
tip = chainman.ActiveChain().Tip();
|
||||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||||
@ -284,7 +284,7 @@ static bool rest_block(const CoreContext& context,
|
|||||||
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
|
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsBlockPruned(pblockindex))
|
if (chainman.m_blockman.IsBlockPruned(pblockindex))
|
||||||
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
|
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
|
||||||
|
|
||||||
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
|
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
|
||||||
@ -311,7 +311,7 @@ static bool rest_block(const CoreContext& context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case RetFormat::JSON: {
|
case RetFormat::JSON: {
|
||||||
UniValue objBlock = blockToJSON(block, tip, pblockindex, *llmq::chainLocksHandler, *llmq::quorumInstantSendManager, showTxDetails);
|
UniValue objBlock = blockToJSON(chainman.m_blockman, block, tip, pblockindex, *llmq::chainLocksHandler, *llmq::quorumInstantSendManager, showTxDetails);
|
||||||
std::string strJSON = objBlock.write() + "\n";
|
std::string strJSON = objBlock.write() + "\n";
|
||||||
req->WriteHeader("Content-Type", "application/json");
|
req->WriteHeader("Content-Type", "application/json");
|
||||||
req->WriteReply(HTTP_OK, strJSON);
|
req->WriteReply(HTTP_OK, strJSON);
|
||||||
|
@ -156,7 +156,7 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, llmq::CChainLocksHandler& clhandler, llmq::CInstantSendManager& isman, bool txDetails)
|
UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, llmq::CChainLocksHandler& clhandler, llmq::CInstantSendManager& isman, bool txDetails)
|
||||||
{
|
{
|
||||||
UniValue result = blockheaderToJSON(tip, blockindex, clhandler, isman);
|
UniValue result = blockheaderToJSON(tip, blockindex, clhandler, isman);
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn
|
|||||||
UniValue txs(UniValue::VARR);
|
UniValue txs(UniValue::VARR);
|
||||||
if (txDetails) {
|
if (txDetails) {
|
||||||
CBlockUndo blockUndo;
|
CBlockUndo blockUndo;
|
||||||
const bool have_undo{WITH_LOCK(::cs_main, return !IsBlockPruned(blockindex) && UndoReadFromDisk(blockUndo, blockindex))};
|
const bool have_undo{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex) && UndoReadFromDisk(blockUndo, blockindex))};
|
||||||
for (size_t i = 0; i < block.vtx.size(); ++i) {
|
for (size_t i = 0; i < block.vtx.size(); ++i) {
|
||||||
const CTransactionRef& tx = block.vtx.at(i);
|
const CTransactionRef& tx = block.vtx.at(i);
|
||||||
// coinbase transaction (i == 0) doesn't have undo data
|
// coinbase transaction (i == 0) doesn't have undo data
|
||||||
@ -1060,11 +1060,11 @@ static RPCHelpMan getblockheaders()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static CBlock GetBlockChecked(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
|
static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
|
||||||
{
|
{
|
||||||
AssertLockHeld(::cs_main);
|
AssertLockHeld(::cs_main);
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (IsBlockPruned(pblockindex)) {
|
if (blockman.IsBlockPruned(pblockindex)) {
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
|
throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1078,11 +1078,11 @@ static CBlock GetBlockChecked(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_RE
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CBlockUndo GetUndoChecked(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
AssertLockHeld(::cs_main);
|
AssertLockHeld(::cs_main);
|
||||||
CBlockUndo blockUndo;
|
CBlockUndo blockUndo;
|
||||||
if (IsBlockPruned(pblockindex)) {
|
if (blockman.IsBlockPruned(pblockindex)) {
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)");
|
throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1137,7 +1137,7 @@ static RPCHelpMan getmerkleblocks()
|
|||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Count is out of range");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Count is out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlock block = GetBlockChecked(pblockindex);
|
CBlock block = GetBlockChecked(chainman.m_blockman, pblockindex);
|
||||||
|
|
||||||
UniValue arrMerkleBlocks(UniValue::VARR);
|
UniValue arrMerkleBlocks(UniValue::VARR);
|
||||||
|
|
||||||
@ -1247,8 +1247,8 @@ static RPCHelpMan getblock()
|
|||||||
CBlock block;
|
CBlock block;
|
||||||
const CBlockIndex* pblockindex;
|
const CBlockIndex* pblockindex;
|
||||||
const CBlockIndex* tip;
|
const CBlockIndex* tip;
|
||||||
|
ChainstateManager& chainman = EnsureChainman(node);
|
||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureChainman(node);
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||||
tip = chainman.ActiveChain().Tip();
|
tip = chainman.ActiveChain().Tip();
|
||||||
@ -1257,7 +1257,7 @@ static RPCHelpMan getblock()
|
|||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
block = GetBlockChecked(pblockindex);
|
block = GetBlockChecked(chainman.m_blockman, pblockindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbosity <= 0)
|
if (verbosity <= 0)
|
||||||
@ -1269,7 +1269,7 @@ static RPCHelpMan getblock()
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLMQContext& llmq_ctx = EnsureLLMQContext(node);
|
LLMQContext& llmq_ctx = EnsureLLMQContext(node);
|
||||||
return blockToJSON(block, tip, pblockindex, *llmq_ctx.clhandler, *llmq_ctx.isman, verbosity >= 2);
|
return blockToJSON(chainman.m_blockman, block, tip, pblockindex, *llmq_ctx.clhandler, *llmq_ctx.isman, verbosity >= 2);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1760,18 +1760,18 @@ RPCHelpMan getblockchaininfo()
|
|||||||
const auto ehfSignals = node.mnhf_manager->GetSignalsStage(tip);
|
const auto ehfSignals = node.mnhf_manager->GetSignalsStage(tip);
|
||||||
|
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.pushKV("chain", strChainName);
|
obj.pushKV("chain", strChainName);
|
||||||
obj.pushKV("blocks", height);
|
obj.pushKV("blocks", height);
|
||||||
obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1);
|
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->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);
|
||||||
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
|
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
|
||||||
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
|
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
|
||||||
obj.pushKV("initialblockdownload", active_chainstate.IsInitialBlockDownload());
|
obj.pushKV("initialblockdownload", active_chainstate.IsInitialBlockDownload());
|
||||||
obj.pushKV("chainwork", tip->nChainWork.GetHex());
|
obj.pushKV("chainwork", tip->nChainWork.GetHex());
|
||||||
obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());
|
obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());
|
||||||
obj.pushKV("pruned", fPruneMode);
|
obj.pushKV("pruned", fPruneMode);
|
||||||
if (fPruneMode) {
|
if (fPruneMode) {
|
||||||
const CBlockIndex* block = tip;
|
const CBlockIndex* block = tip;
|
||||||
CHECK_NONFATAL(block);
|
CHECK_NONFATAL(block);
|
||||||
@ -2358,8 +2358,8 @@ static RPCHelpMan getblockstats()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CBlock block = GetBlockChecked(pindex);
|
const CBlock block = GetBlockChecked(chainman.m_blockman, pindex);
|
||||||
const CBlockUndo blockUndo = GetUndoChecked(pindex);
|
const CBlockUndo blockUndo = GetUndoChecked(chainman.m_blockman, pindex);
|
||||||
|
|
||||||
const bool do_all = stats.size() == 0; // Calculate everything if nothing selected (default)
|
const bool do_all = stats.size() == 0; // Calculate everything if nothing selected (default)
|
||||||
const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0;
|
const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0;
|
||||||
@ -2571,7 +2571,7 @@ static RPCHelpMan getspecialtxes()
|
|||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
const CBlock block = GetBlockChecked(pblockindex);
|
const CBlock block = GetBlockChecked(chainman.m_blockman, pblockindex);
|
||||||
|
|
||||||
int nTxNum = 0;
|
int nTxNum = 0;
|
||||||
UniValue result(UniValue::VARR);
|
UniValue result(UniValue::VARR);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <streams.h>
|
#include <streams.h>
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
|
#include <validation.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -40,7 +41,7 @@ double GetDifficulty(const CBlockIndex* blockindex);
|
|||||||
void RPCNotifyBlockChange(const CBlockIndex*);
|
void RPCNotifyBlockChange(const CBlockIndex*);
|
||||||
|
|
||||||
/** Block description to JSON */
|
/** Block description to JSON */
|
||||||
UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, llmq::CChainLocksHandler& clhandler, llmq::CInstantSendManager& isman, bool txDetails = false) LOCKS_EXCLUDED(cs_main);
|
UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, llmq::CChainLocksHandler& clhandler, llmq::CInstantSendManager& isman, bool txDetails = false) LOCKS_EXCLUDED(cs_main);
|
||||||
|
|
||||||
/** Mempool information to JSON */
|
/** Mempool information to JSON */
|
||||||
UniValue MempoolInfoToJSON(const CTxMemPool& pool, llmq::CInstantSendManager& isman);
|
UniValue MempoolInfoToJSON(const CTxMemPool& pool, llmq::CInstantSendManager& isman);
|
||||||
|
@ -105,7 +105,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;
|
||||||
@ -348,8 +347,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.m_best_header->nHeight - 1) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1296,8 +1296,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.m_best_header != nullptr && m_chainman.m_best_header->GetAncestor(pindexNew->nHeight) == pindexNew) {
|
||||||
pindexBestHeader = m_chain.Tip();
|
m_chainman.m_best_header = 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__,
|
||||||
@ -1888,8 +1888,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.m_best_header->GetAncestor(pindex->nHeight) == pindex &&
|
||||||
pindexBestHeader->nChainWork >= nMinimumChainWork) {
|
m_chainman.m_best_header->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
|
||||||
@ -1904,7 +1904,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.m_best_header, *pindex, *m_chainman.m_best_header, m_params.GetConsensus()) <= 60 * 60 * 24 * 7 * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2348,9 +2348,9 @@ bool CChainState::FlushStateToDisk(
|
|||||||
}
|
}
|
||||||
if (!setFilesToPrune.empty()) {
|
if (!setFilesToPrune.empty()) {
|
||||||
fFlushForPrune = true;
|
fFlushForPrune = true;
|
||||||
if (!fHavePruned) {
|
if (!m_blockman.m_have_pruned) {
|
||||||
m_blockman.m_block_tree_db->WriteFlag("prunedblockfiles", true);
|
m_blockman.m_block_tree_db->WriteFlag("prunedblockfiles", true);
|
||||||
fHavePruned = true;
|
m_blockman.m_have_pruned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2911,7 +2911,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.m_best_header;
|
||||||
|
|
||||||
if (pindexHeader != pindexHeaderOld) {
|
if (pindexHeader != pindexHeaderOld) {
|
||||||
fNotify = true;
|
fNotify = true;
|
||||||
@ -3129,9 +3129,9 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pind
|
|||||||
CBlockIndex *invalid_walk_tip = m_chain.Tip();
|
CBlockIndex *invalid_walk_tip = m_chain.Tip();
|
||||||
const CBlockIndex* pindexOldTip = m_chain.Tip();
|
const CBlockIndex* pindexOldTip = m_chain.Tip();
|
||||||
|
|
||||||
if (pindex == pindexBestHeader) {
|
if (pindex == m_chainman.m_best_header) {
|
||||||
m_chainman.m_best_invalid = pindexBestHeader;
|
m_chainman.m_best_invalid = m_chainman.m_best_header;
|
||||||
pindexBestHeader = pindexBestHeader->pprev;
|
m_chainman.m_best_header = m_chainman.m_best_header->pprev;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActivateBestChain considers blocks already in m_chain
|
// ActivateBestChain considers blocks already in m_chain
|
||||||
@ -3147,9 +3147,9 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pind
|
|||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
assert(invalid_walk_tip->pprev == m_chain.Tip());
|
assert(invalid_walk_tip->pprev == m_chain.Tip());
|
||||||
|
|
||||||
if (pindexOldTip == pindexBestHeader) {
|
if (pindexOldTip == m_chainman.m_best_header) {
|
||||||
m_chainman.m_best_invalid = pindexBestHeader;
|
m_chainman.m_best_invalid = m_chainman.m_best_header;
|
||||||
pindexBestHeader = pindexBestHeader->pprev;
|
m_chainman.m_best_header = m_chainman.m_best_header->pprev;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We immediately mark the disconnected blocks as invalid.
|
// We immediately mark the disconnected blocks as invalid.
|
||||||
@ -3264,8 +3264,8 @@ bool CChainState::MarkConflictingBlock(BlockValidationState& state, CBlockIndex
|
|||||||
bool pindex_was_in_chain = false;
|
bool pindex_was_in_chain = false;
|
||||||
CBlockIndex *conflicting_walk_tip = m_chain.Tip();
|
CBlockIndex *conflicting_walk_tip = m_chain.Tip();
|
||||||
|
|
||||||
if (pindex == pindexBestHeader) {
|
if (pindex == m_chainman.m_best_header) {
|
||||||
pindexBestHeader = pindexBestHeader->pprev;
|
m_chainman.m_best_header = m_chainman.m_best_header->pprev;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -3282,8 +3282,8 @@ bool CChainState::MarkConflictingBlock(BlockValidationState& state, CBlockIndex
|
|||||||
MaybeUpdateMempoolForReorg(disconnectpool, false);
|
MaybeUpdateMempoolForReorg(disconnectpool, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pindexOldTip == pindexBestHeader) {
|
if (pindexOldTip == m_chainman.m_best_header) {
|
||||||
pindexBestHeader = pindexBestHeader->pprev;
|
m_chainman.m_best_header = m_chainman.m_best_header->pprev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3749,13 +3749,13 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
|
|||||||
|
|
||||||
if (llmq::chainLocksHandler->HasConflictingChainLock(pindexPrev->nHeight + 1, hash)) {
|
if (llmq::chainLocksHandler->HasConflictingChainLock(pindexPrev->nHeight + 1, hash)) {
|
||||||
if (miSelf == m_blockman.m_block_index.end()) {
|
if (miSelf == m_blockman.m_block_index.end()) {
|
||||||
m_blockman.AddToBlockIndex(block, hash, BLOCK_CONFLICT_CHAINLOCK);
|
m_blockman.AddToBlockIndex(block, hash, m_best_header, BLOCK_CONFLICT_CHAINLOCK);
|
||||||
}
|
}
|
||||||
LogPrintf("ERROR: %s: header %s conflicts with chainlock\n", __func__, hash.ToString());
|
LogPrintf("ERROR: %s: header %s conflicts with chainlock\n", __func__, hash.ToString());
|
||||||
return state.Invalid(BlockValidationResult::BLOCK_CHAINLOCK, "bad-chainlock");
|
return state.Invalid(BlockValidationResult::BLOCK_CHAINLOCK, "bad-chainlock");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CBlockIndex* pindex{m_blockman.AddToBlockIndex(block, hash)};
|
CBlockIndex* pindex{m_blockman.AddToBlockIndex(block, hash, m_best_header)};
|
||||||
|
|
||||||
if (ppindex)
|
if (ppindex)
|
||||||
*ppindex = pindex;
|
*ppindex = pindex;
|
||||||
@ -4342,13 +4342,11 @@ void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman)
|
|||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
chainman.Unload();
|
chainman.Unload();
|
||||||
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++) {
|
||||||
warningcache[b].clear();
|
warningcache[b].clear();
|
||||||
}
|
}
|
||||||
fHavePruned = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChainstateManager::LoadBlockIndex()
|
bool ChainstateManager::LoadBlockIndex()
|
||||||
@ -4423,6 +4421,8 @@ bool ChainstateManager::LoadBlockIndex()
|
|||||||
if (pindex->nStatus & BLOCK_FAILED_MASK && (!m_best_invalid || pindex->nChainWork > m_best_invalid->nChainWork)) {
|
if (pindex->nStatus & BLOCK_FAILED_MASK && (!m_best_invalid || pindex->nChainWork > m_best_invalid->nChainWork)) {
|
||||||
m_best_invalid = pindex;
|
m_best_invalid = pindex;
|
||||||
}
|
}
|
||||||
|
if (pindex->IsValid(BLOCK_VALID_TREE) && (m_best_header == nullptr || CBlockIndexWorkComparator()(m_best_header, pindex)))
|
||||||
|
m_best_header = pindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
needs_init = m_blockman.m_block_index.empty();
|
needs_init = m_blockman.m_block_index.empty();
|
||||||
@ -4458,7 +4458,7 @@ bool CChainState::AddGenesisBlock(const CBlock& block, BlockValidationState& sta
|
|||||||
if (blockPos.IsNull()) {
|
if (blockPos.IsNull()) {
|
||||||
return error("%s: writing genesis block to disk failed (%s)", __func__, state.ToString());
|
return error("%s: writing genesis block to disk failed (%s)", __func__, state.ToString());
|
||||||
}
|
}
|
||||||
CBlockIndex* pindex = m_blockman.AddToBlockIndex(block, block.GetHash());
|
CBlockIndex* pindex = m_blockman.AddToBlockIndex(block, block.GetHash(), m_chainman.m_best_header);
|
||||||
ReceivedBlockTransactions(block, pindex, blockPos);
|
ReceivedBlockTransactions(block, pindex, blockPos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4700,7 +4700,7 @@ void CChainState::CheckBlockIndex()
|
|||||||
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
|
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
|
||||||
// Unless these indexes are assumed valid and pending block download on a
|
// Unless these indexes are assumed valid and pending block download on a
|
||||||
// background chainstate.
|
// background chainstate.
|
||||||
if (!fHavePruned && !pindex->IsAssumedValid()) {
|
if (!m_blockman.m_have_pruned && !pindex->IsAssumedValid()) {
|
||||||
// If we've never pruned, then HAVE_DATA should be equivalent to nTx > 0
|
// If we've never pruned, then HAVE_DATA should be equivalent to nTx > 0
|
||||||
assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
|
assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
|
||||||
assert(pindexFirstMissing == pindexFirstNeverProcessed);
|
assert(pindexFirstMissing == pindexFirstNeverProcessed);
|
||||||
@ -4778,7 +4778,7 @@ void CChainState::CheckBlockIndex()
|
|||||||
if (pindexFirstMissing == nullptr) assert(!foundInUnlinked); // We aren't missing data for any parent -- cannot be in m_blocks_unlinked.
|
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) {
|
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.
|
// 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.
|
assert(m_blockman.m_have_pruned); // We must have pruned.
|
||||||
// This block may have entered m_blocks_unlinked if:
|
// This block may have entered m_blocks_unlinked if:
|
||||||
// - it has a descendant that at some point had more work than the
|
// - it has a descendant that at some point had more work than the
|
||||||
// tip, and
|
// tip, and
|
||||||
@ -5424,6 +5424,7 @@ void ChainstateManager::Unload()
|
|||||||
|
|
||||||
m_failed_blocks.clear();
|
m_failed_blocks.clear();
|
||||||
m_blockman.Unload();
|
m_blockman.Unload();
|
||||||
|
m_best_header = nullptr;
|
||||||
m_best_invalid = nullptr;
|
m_best_invalid = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,9 +150,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;
|
||||||
|
|
||||||
@ -881,6 +878,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* m_best_header = 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};
|
||||||
|
Loading…
Reference in New Issue
Block a user