Skip to content

Commit 9eb67f5

Browse files
committed
Ensure we meet the BIP 152 old-relay-types response requirements
In order to do this, we must call ActivateBestChain prior to responding getdata requests for blocks which we announced using compact blocks. For getheaders responses we dont need code changes, but do note that we must reset the bestHeaderSent so that the SendMessages call re-announces the header in question. While we could do something smarter for getblocks, calling ActivateBestChain is simple and more obviously correct, instead of doing something more similar to getheaders. See-also the BIP clarifications at bitcoin/bips#486
1 parent 5749a85 commit 9eb67f5

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

src/net_processing.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
957957
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
958958
if (mi != mapBlockIndex.end())
959959
{
960+
if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) &&
961+
mi->second->IsValid(BLOCK_VALID_TREE)) {
962+
// If we have the block and all of its parents, but have not yet validated it,
963+
// we might be in the middle of connecting it (ie in the unlock of cs_main
964+
// before ActivateBestChain but after AcceptBlock).
965+
// In this case, we need to run ActivateBestChain prior to checking the relay
966+
// conditions below.
967+
CValidationState dummy;
968+
ActivateBestChain(dummy, Params());
969+
}
960970
if (chainActive.Contains(mi->second)) {
961971
send = true;
962972
} else {
@@ -1517,6 +1527,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
15171527

15181528
LOCK(cs_main);
15191529

1530+
// We might have announced the currently-being-connected tip using a
1531+
// compact block, which resulted in the peer sending a getblocks
1532+
// request, which we would otherwise respond to without the new block.
1533+
// To avoid this situation we simply verify that we are on our best
1534+
// known chain now. This is super overkill, but we handle it better
1535+
// for getheaders requests, and there are no known nodes which support
1536+
// compact blocks but still use getblocks to request blocks.
1537+
{
1538+
CValidationState dummy;
1539+
ActivateBestChain(dummy, Params());
1540+
}
1541+
15201542
// Find the last block the caller has in the main chain
15211543
const CBlockIndex* pindex = FindForkInGlobalIndex(chainActive, locator);
15221544

@@ -1647,6 +1669,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
16471669
// if our peer has chainActive.Tip() (and thus we are sending an empty
16481670
// headers message). In both cases it's safe to update
16491671
// pindexBestHeaderSent to be our tip.
1672+
//
1673+
// It is important that we simply reset the BestHeaderSent value here,
1674+
// and not max(BestHeaderSent, newHeaderSent). We might have announced
1675+
// the currently-being-connected tip using a compact block, which
1676+
// resulted in the peer sending a headers request, which we respond to
1677+
// without the new block. By resetting the BestHeaderSent, we ensure we
1678+
// will re-announce the new block via headers (or compact blocks again)
1679+
// in the SendMessages logic.
16501680
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
16511681
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
16521682
}

0 commit comments

Comments
 (0)