aboutsummaryrefslogtreecommitdiff
path: root/src/net_processing.cpp
diff options
context:
space:
mode:
authorSuhas Daftuar <sdaftuar@gmail.com>2022-02-08 17:02:55 -0500
committerSuhas Daftuar <sdaftuar@gmail.com>2022-06-28 15:53:25 -0400
commit7f2450871b3ea0b4d02d56bd2ca365fcc25cf90e (patch)
tree3146cd6799d122677dec4c43d7f8512563430e35 /src/net_processing.cpp
parent2111f32f2a6998531871e7792b5208992868ba7f (diff)
downloadbitcoin-7f2450871b3ea0b4d02d56bd2ca365fcc25cf90e.tar.xz
Move handling of unconnecting headers into own function
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r--src/net_processing.cpp91
1 files changed, 63 insertions, 28 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index a556180721..6965695ad9 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -560,6 +560,11 @@ private:
const std::vector<CBlockHeader>& headers,
bool via_compact_block)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+ /** Various helpers for headers processing, invoked by ProcessHeadersMessage() */
+ /** Deal with state tracking and headers sync for peers that send the
+ * occasional non-connecting header (this can happen due to BIP 130 headers
+ * announcements for blocks interacting with the 2hr (MAX_FUTURE_BLOCK_TIME) rule). */
+ void HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer, const std::vector<CBlockHeader>& headers);
void SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req);
@@ -2194,6 +2199,48 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlo
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCKTXN, resp));
}
+/**
+ * Special handling for unconnecting headers that might be part of a block
+ * announcement.
+ *
+ * We'll send a getheaders message in response to try to connect the chain.
+ *
+ * The peer can send up to MAX_UNCONNECTING_HEADERS in a row that
+ * don't connect before given DoS points.
+ *
+ * Once a headers message is received that is valid and does connect,
+ * nUnconnectingHeaders gets reset back to 0.
+ */
+void PeerManagerImpl::HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer,
+ const std::vector<CBlockHeader>& headers)
+{
+ const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
+
+ LOCK(cs_main);
+ CNodeState *nodestate = State(pfrom.GetId());
+
+ nodestate->nUnconnectingHeaders++;
+
+ // Try to fill in the missing headers.
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), uint256()));
+ 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].hashPrevBlock.ToString(),
+ m_chainman.m_best_header->nHeight,
+ pfrom.GetId(), nodestate->nUnconnectingHeaders);
+
+ // Set hashLastUnknownBlock for this peer, so that if we
+ // eventually get the headers - even from a different peer -
+ // we can use this peer to download.
+ UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash());
+
+ // The peer may just be broken, so periodically assign DoS points if this
+ // condition persists.
+ if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
+ Misbehaving(peer, 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
+ }
+}
+
void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
const std::vector<CBlockHeader>& headers,
bool via_compact_block)
@@ -2208,36 +2255,24 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
bool received_new_header = false;
const CBlockIndex *pindexLast = nullptr;
- {
- LOCK(cs_main);
- CNodeState *nodestate = State(pfrom.GetId());
- // If this looks like it could be a block announcement (nCount <=
- // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that
- // don't connect:
- // - Send a getheaders message in response to try to connect the chain.
- // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that
- // don't connect before giving DoS points
- // - Once a headers message is received that is valid and does connect,
- // nUnconnectingHeaders gets reset back to 0.
- if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount <= MAX_BLOCKS_TO_ANNOUNCE) {
- nodestate->nUnconnectingHeaders++;
- m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), uint256()));
- 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].hashPrevBlock.ToString(),
- m_chainman.m_best_header->nHeight,
- pfrom.GetId(), nodestate->nUnconnectingHeaders);
- // Set hashLastUnknownBlock for this peer, so that if we
- // eventually get the headers - even from a different peer -
- // we can use this peer to download.
- UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash());
-
- if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
- Misbehaving(peer, 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
- }
- return;
+ // Do these headers connect to something in our block index?
+ bool headers_connect_blockindex{WITH_LOCK(::cs_main, return m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) != nullptr)};
+
+ if (!headers_connect_blockindex) {
+ if (nCount <= MAX_BLOCKS_TO_ANNOUNCE) {
+ // If this looks like it could be a BIP 130 block announcement, use
+ // special logic for handling headers that don't connect, as this
+ // could be benign.
+ HandleFewUnconnectingHeaders(pfrom, peer, headers);
+ } else {
+ Misbehaving(peer, 10, "invalid header received");
}
+ return;
+ }
+
+ {
+ LOCK(cs_main);
uint256 hashLastBlock;
for (const CBlockHeader& header : headers) {