Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 24 additions & 23 deletions src/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,33 @@ void CChain::SetTip(CBlockIndex& block)
}
}

CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
int nStep = 1;
std::vector<uint256> vHave;
vHave.reserve(32);

if (!pindex)
pindex = Tip();
while (pindex) {
vHave.push_back(pindex->GetBlockHash());
// Stop when we have added the genesis block.
if (pindex->nHeight == 0)
break;
std::vector<uint256> LocatorEntries(const CBlockIndex* index)
{
int step = 1;
std::vector<uint256> have;
if (index == nullptr) return have;

have.reserve(32);
while (index) {
have.emplace_back(index->GetBlockHash());
if (index->nHeight == 0) break;
// Exponentially larger steps back, plus the genesis block.
int nHeight = std::max(pindex->nHeight - nStep, 0);
if (Contains(pindex)) {
// Use O(1) CChain index if possible.
pindex = (*this)[nHeight];
} else {
// Otherwise, use O(log n) skiplist.
pindex = pindex->GetAncestor(nHeight);
}
if (vHave.size() > 10)
nStep *= 2;
int height = std::max(index->nHeight - step, 0);
// Use skiplist.
index = index->GetAncestor(height);
if (have.size() > 10) step *= 2;
}
return have;
}

return CBlockLocator(vHave);
CBlockLocator GetLocator(const CBlockIndex* index)
{
return CBlockLocator{LocatorEntries(index)};
}

CBlockLocator CChain::GetLocator() const
{
return ::GetLocator(Tip());
}

const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
Expand Down
10 changes: 8 additions & 2 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,8 +478,8 @@ class CChain
/** Set/initialize a chain with a given tip. */
void SetTip(CBlockIndex& block);

/** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
CBlockLocator GetLocator(const CBlockIndex* pindex = nullptr) const;
/** Return a CBlockLocator that refers to the tip in of this chain. */
CBlockLocator GetLocator() const;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore the indexed locator call sites

Removing the CChain::GetLocator(const CBlockIndex*) overload here leaves src/node/interfaces.cpp:1087 still calling active.GetLocator(index), so any build of ChainImpl::findBlock(...FoundBlock().locator(...)) fails with no matching member function instead of using the new free GetLocator(index). The backport guidance specifically warns to resolve these API conflicts rather than only matching upstream shape.

AGENTS.md reference: AGENTS.md:L153-L155

Useful? React with 👍 / 👎.

Comment thread
coderabbitai[bot] marked this conversation as resolved.

/** Find the last common block between this chain and a block index entry. */
const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
Expand All @@ -488,4 +488,10 @@ class CChain
CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
};

/** Get a locator for a block index entry. */
CBlockLocator GetLocator(const CBlockIndex* index);

/** Construct a list of hash entries to put in a locator. */
std::vector<uint256> LocatorEntries(const CBlockIndex* index);

#endif // BITCOIN_CHAIN_H
2 changes: 1 addition & 1 deletion src/index/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ bool BaseIndex::Commit()
CDBBatch batch(GetDB());
ok = CustomCommit(batch);
if (ok) {
GetDB().WriteBestBlock(batch, GetLocator(*m_chain, m_best_block_index.load()->GetBlockHash()));
GetDB().WriteBestBlock(batch, GetLocator(m_best_block_index));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upstream pr doesn't touch this file::

F1 — src/index/base.cpp is out of scope and moves Dash away from upstream ⚠️ should fix
src/index/base.cpp:225

-GetDB().WriteBestBlock(batch, GetLocator(*m_chain, m_best_block_index.load()->GetBlockHash()));
+GetDB().WriteBestBlock(batch, GetLocator(m_best_block_index));
This hunk is not in bitcoin#25717 — upstream 3add234546:src/index/base.cpp:230 still has the *m_chain form, and so does bitcoin/master today (line 297). Dash develop currently matches upstream exactly. The *m_chain form was introduced by bitcoin#25494 (7878f97bf15b, "indexes, refactor: Remove CChainState use in index CommitInternal method"), which is the commit that also added the GetLocator(interfaces::Chain&, uint256) helper.

So this reverts a backported upstream refactor and re-creates divergence — the opposite of the PR's stated purpose, and it will conflict with future src/index/ backports.

Knock-on effects:

src/index/base.cpp:34 CBlockLocator GetLocator(interfaces::Chain&, const uint256&) now has zero callers and no header declaration → dead code (upstream's 7878f97b removed it together with the call-site change; here only half was taken).
Loses assert(found) / assert(!locator.IsNull()) — a real sanity check that the index's best block is still in the block index.
Relies on the implicit std::atomic<const CBlockIndex*>::operator T() load; .load() reads clearer.
Output is behaviorally identical (both paths ultimately call the same new free GetLocator), so this is not a correctness bug — but it's diff-negative for the PR's goal. Recommend dropping the hunk entirely.

ok = GetDB().WriteBatch(batch);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ class Node

//! Register handler for header tip messages.
using NotifyHeaderTipFn =
std::function<void(SynchronizationState, interfaces::BlockTip tip, double verification_progress)>;
std::function<void(SynchronizationState, interfaces::BlockTip tip)>;
virtual std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0;

//! Register handler for InstantSend data messages.
Expand Down
12 changes: 6 additions & 6 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3054,7 +3054,7 @@ void PeerManagerImpl::HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer,
nodestate->nUnconnectingHeaders++;
// Try to fill in the missing headers.
std::string msg_type = UsesCompressedHeaders(peer) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
if (MaybeSendGetHeaders(pfrom, msg_type, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), peer)) {
if (MaybeSendGetHeaders(pfrom, msg_type, GetLocator(m_chainman.m_best_header), peer)) {
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].hashPrevBlock.ToString(),
Expand Down Expand Up @@ -3281,7 +3281,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
const std::string msg_type = uses_compressed ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
if (nCount == GetHeadersLimit(pfrom, uses_compressed)) {
// Headers message had its maximum size; the peer may have more headers.
if (MaybeSendGetHeaders(pfrom, msg_type, WITH_LOCK(m_chainman.GetMutex(), return m_chainman.ActiveChain().GetLocator(pindexLast)), peer)) {
if (MaybeSendGetHeaders(pfrom, msg_type, GetLocator(pindexLast), peer)) {
LogPrint(BCLog::NET, "more %s (%d) to end to peer=%d (startheight:%d)\n",
msg_type, pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
}
Expand Down Expand Up @@ -4451,7 +4451,7 @@ void PeerManagerImpl::ProcessMessage(
CNodeState& state{*Assert(State(pfrom.GetId()))};
if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
std::string msg_type = UsesCompressedHeaders(*peer) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
if (MaybeSendGetHeaders(pfrom, msg_type, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), *peer)) {
if (MaybeSendGetHeaders(pfrom, msg_type, GetLocator(m_chainman.m_best_header), *peer)) {
LogPrint(BCLog::NET, "%s (%d) %s to peer=%d\n",
msg_type, m_chainman.m_best_header->nHeight, best_block->ToString(),
pfrom.GetId());
Expand Down Expand Up @@ -4914,7 +4914,7 @@ void PeerManagerImpl::ProcessMessage(
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
if (!m_chainman.ActiveChainstate().IsInitialBlockDownload()) {
std::string ret_val = UsesCompressedHeaders(*peer) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
MaybeSendGetHeaders(pfrom, ret_val, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), *peer);
MaybeSendGetHeaders(pfrom, ret_val, GetLocator(m_chainman.m_best_header), *peer);
}
return;
}
Expand Down Expand Up @@ -5810,7 +5810,7 @@ void PeerManagerImpl::ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seco
// still respond to us with a sufficiently high work chain tip.
std::string msg_type = UsesCompressedHeaders(peer) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
MaybeSendGetHeaders(pto,
msg_type, m_chainman.ActiveChain().GetLocator(state.m_chain_sync.m_work_header->pprev),
msg_type, GetLocator(state.m_chain_sync.m_work_header->pprev),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the genesis locator in eviction probes

When m_work_header is the genesis block, m_work_header->pprev is null; the old member call treated a null argument as the active tip and sent a genesis locator, but the new free GetLocator(nullptr) serializes an empty locator. Peers in this code handle an empty getheaders locator by looking up only hashStop, and because MaybeSendGetHeaders passes a zero stop hash they return no headers, so an initial-sync eviction probe from a genesis-only node can never elicit the headers needed to prove the peer has caught up.

Useful? React with 👍 / 👎.

peer);
LogPrint(BCLog::NET, "sending %s to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", msg_type, pto.GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString());
state.m_chain_sync.m_sent_getheaders = true;
Expand Down Expand Up @@ -6201,7 +6201,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
std::string msg_type = UsesCompressedHeaders(*peer) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
if (MaybeSendGetHeaders(*pto, msg_type, m_chainman.ActiveChain().GetLocator(pindexStart), *peer)) {
if (MaybeSendGetHeaders(*pto, msg_type, GetLocator(pindexStart), *peer)) {
LogPrint(BCLog::NET, "initial %s (%d) to peer=%d (startheight:%d)\n", msg_type, pindexStart->nHeight, pto->GetId(), peer->m_starting_height);

state.fSyncStarted = true;
Expand Down
2 changes: 1 addition & 1 deletion src/node/interface_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertC
void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); }
void CClientUIInterface::NotifyBlockTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(s, i); }
void CClientUIInterface::NotifyChainLock(const std::string& bestChainLockHash, int bestChainLockHeight) { return g_ui_signals.NotifyChainLock(bestChainLockHash, bestChainLockHeight); }
void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyHeaderTip(s, i); }
void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, int64_t height, int64_t timestamp) { return g_ui_signals.NotifyHeaderTip(s, height, timestamp); }
void CClientUIInterface::NotifyGovernanceChanged() { return g_ui_signals.NotifyGovernanceChanged(); }
void CClientUIInterface::NotifyInstantSendChanged() { return g_ui_signals.NotifyInstantSendChanged(); }
void CClientUIInterface::NotifyMasternodeListChanged(const CDeterministicMNList& list, const CBlockIndex* i) { return g_ui_signals.NotifyMasternodeListChanged(list, i); }
Expand Down
2 changes: 1 addition & 1 deletion src/node/interface_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class CClientUIInterface
ADD_SIGNALS_DECL_WRAPPER(NotifyChainLock, void, const std::string& bestChainLockHash, int bestChainLockHeight);

/** Best header has changed */
ADD_SIGNALS_DECL_WRAPPER(NotifyHeaderTip, void, SynchronizationState, const CBlockIndex*);
ADD_SIGNALS_DECL_WRAPPER(NotifyHeaderTip, void, SynchronizationState, int64_t height, int64_t timestamp);

/** Masternode list has changed */
ADD_SIGNALS_DECL_WRAPPER(NotifyMasternodeListChanged, void, const CDeterministicMNList&, const CBlockIndex*);
Expand Down
10 changes: 4 additions & 6 deletions src/node/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1037,9 +1037,8 @@ class NodeImpl : public Node
std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
{
return MakeHandler(
::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
/* verification progress is unused when a header was received */ 0);
::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, int64_t height, int64_t timestamp) {
fn(sync_state, BlockTip{(int)height, timestamp, uint256{}});
}));
}
std::unique_ptr<Handler> handleNotifyInstantSendChanged(NotifyInstantSendChangedFn fn) override
Expand Down Expand Up @@ -1085,7 +1084,7 @@ bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<Rec
if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
if (block.m_locator) { *block.m_locator = active.GetLocator(index); }
if (block.m_locator) { *block.m_locator = GetLocator(index); }
if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active);
if (block.m_data) {
REVERSE_LOCK(lock);
Expand Down Expand Up @@ -1249,8 +1248,7 @@ class ChainImpl : public Chain
{
LOCK(::cs_main);
const CBlockIndex* index = chainman().m_blockman.LookupBlockIndex(block_hash);
if (!index) return {};
return chainman().ActiveChain().GetLocator(index);
return GetLocator(index);
}
std::optional<int> findLocatorFork(const CBlockLocator& locator) override
{
Expand Down
2 changes: 1 addition & 1 deletion src/primitives/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ struct CBlockLocator

CBlockLocator() {}

explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
explicit CBlockLocator(std::vector<uint256>&& have) : vHave(std::move(have)) {}

SERIALIZE_METHODS(CBlockLocator, obj)
{
Expand Down
2 changes: 2 additions & 0 deletions src/qt/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,15 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
Q_DECLARE_METATYPE(bool*)
Q_DECLARE_METATYPE(CAmount)
Q_DECLARE_METATYPE(SynchronizationState)
Q_DECLARE_METATYPE(SyncType)
Q_DECLARE_METATYPE(uint256)

static void RegisterMetaTypes()
{
// Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection
qRegisterMetaType<bool*>();
qRegisterMetaType<SynchronizationState>();
qRegisterMetaType<SyncType>();
#ifdef ENABLE_WALLET
qRegisterMetaType<WalletModel*>();
#endif
Expand Down
16 changes: 8 additions & 8 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);

modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time));
setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), QString::fromStdString(tip_info->block_hash.ToString()), tip_info->verification_progress, false, SynchronizationState::INIT_DOWNLOAD);
setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), QString::fromStdString(tip_info->block_hash.ToString()), tip_info->verification_progress, SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);

connect(_clientModel, &ClientModel::additionalDataSyncProgressChanged, this, &BitcoinGUI::setAdditionalDataSyncProgress);
Expand Down Expand Up @@ -1399,7 +1399,7 @@ void BitcoinGUI::updateNetworkState()
}

if (fNetworkBecameActive || fNetworkBecameInactive) {
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromSecsSinceEpoch(m_node.getLastBlockTime()), QString::fromStdString(m_node.getLastBlockHash()), m_node.getVerificationProgress(), false, SynchronizationState::INIT_DOWNLOAD);
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromSecsSinceEpoch(m_node.getLastBlockTime()), QString::fromStdString(m_node.getLastBlockHash()), m_node.getVerificationProgress(), SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
}

nCountPrev = count;
Expand Down Expand Up @@ -1589,7 +1589,7 @@ void BitcoinGUI::updateWidth()
resize(std::max(width(), nWidth), height());
}

void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, const QString& blockHash, double nVerificationProgress, bool header, SynchronizationState sync_state)
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, const QString& blockHash, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state)
{
#ifdef Q_OS_MACOS
// Disabling macOS App Nap on initial sync, disk, reindex operations and mixing.
Expand All @@ -1610,7 +1610,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, const QStri

if (modalOverlay)
{
if (header)
if (synctype != SyncType::BLOCK_SYNC)
modalOverlay->setKnownBestHeight(count, blockDate);
else
modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
Expand All @@ -1628,22 +1628,22 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, const QStri
BlockSource blockSource{clientModel->getBlockSource()};
switch (blockSource) {
case BlockSource::NETWORK:
if (header) {
if (synctype == SyncType::HEADER_SYNC) {
updateHeadersSyncProgressLabel();
return;
}
progressBarLabel->setText(tr("Synchronizing with network…"));
updateHeadersSyncProgressLabel();
break;
case BlockSource::DISK:
if (header) {
if (synctype != SyncType::BLOCK_SYNC) {
progressBarLabel->setText(tr("Indexing blocks on disk…"));
} else {
progressBarLabel->setText(tr("Processing blocks on disk…"));
}
break;
case BlockSource::NONE:
if (header) {
if (synctype != SyncType::BLOCK_SYNC) {
return;
}
progressBarLabel->setText(tr("Connecting to peers…"));
Expand Down Expand Up @@ -1710,7 +1710,7 @@ void BitcoinGUI::setAdditionalDataSyncProgress(double nSyncProgress)

// If masternodeSync->Reset() has been called make sure status bar shows the correct information.
if (nSyncProgress == -1) {
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromSecsSinceEpoch(m_node.getLastBlockTime()), QString::fromStdString(m_node.getLastBlockHash()), m_node.getVerificationProgress(), false, SynchronizationState::INIT_DOWNLOAD);
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromSecsSinceEpoch(m_node.getLastBlockTime()), QString::fromStdString(m_node.getLastBlockHash()), m_node.getVerificationProgress(), SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
if (clientModel->getNumConnections()) {
labelBlocksIcon->show();
startSpinner();
Expand Down
4 changes: 2 additions & 2 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#endif

#include <qt/bitcoinunits.h>
#include <qt/clientmodel.h>
#include <qt/optionsdialog.h>

#include <consensus/amount.h>
Expand All @@ -30,7 +31,6 @@
#include <qt/macos_appnap.h>
#endif

class ClientModel;
class NetworkStyle;
class Notificator;
class OptionsModel;
Expand Down Expand Up @@ -297,7 +297,7 @@ public Q_SLOTS:
/** Get restart command-line parameters and request restart */
void handleRestart(QStringList args);
/** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate, const QString& blockHash, double nVerificationProgress, bool headers, SynchronizationState sync_state);
void setNumBlocks(int count, const QDateTime& blockDate, const QString& blockHash, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state);
/** Set additional data sync status shown in the UI */
void setAdditionalDataSyncProgress(double nSyncProgress);

Expand Down
Loading
Loading