Move handling of unconnecting headers into own function
This commit is contained in:
1 parent
2111f32f2a
commit
7f2450871b
1 file changed
+63
-28
+63
-28
@@ -560,6 +560,11 @@ private:
|
|||||||
const std::vector<CBlockHeader>& headers,
|
const std::vector<CBlockHeader>& headers,
|
||||||
bool via_compact_block)
|
bool via_compact_block)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
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);
|
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));
|
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,
|
void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
|
||||||
const std::vector<CBlockHeader>& headers,
|
const std::vector<CBlockHeader>& headers,
|
||||||
bool via_compact_block)
|
bool via_compact_block)
|
||||||
@@ -2208,36 +2255,24 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
|
|||||||
|
|
||||||
bool received_new_header = false;
|
bool received_new_header = false;
|
||||||
const CBlockIndex *pindexLast = nullptr;
|
const CBlockIndex *pindexLast = nullptr;
|
||||||
|
|
||||||
|
// 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);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 hashLastBlock;
|
uint256 hashLastBlock;
|
||||||
for (const CBlockHeader& header : headers) {
|
for (const CBlockHeader& header : headers) {
|
||||||
|
|||||||
Reference in new issue
Block a user