Skip to content

Commit

Permalink
Protect last outbound HB compact block peer
Browse files Browse the repository at this point in the history
If all our high-bandwidth compact block serving peers (BIP 152) stall block
download, then we can be denied a block for (potentially) a long time. As
inbound connections are much more likely to be adversarial than outbound
connections, mitigate this risk by never removing our last outbound HB peer if
it would be replaced by an inbound.
  • Loading branch information
sdaftuar committed Jun 3, 2021
1 parent c7dd9ff commit 6efbcec
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/net_processing.cpp
Expand Up @@ -825,12 +825,27 @@ void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
return;
}
if (nodestate->fProvidesHeaderAndIDs) {
int num_outbound_hb_peers = 0;
for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
if (*it == nodeid) {
lNodesAnnouncingHeaderAndIDs.erase(it);
lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
return;
}
CNodeState *state = State(*it);
if (state != nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
}
if (nodestate->m_is_inbound) {
// If we're adding an inbound HB peer, make sure we're not removing
// our last outbound HB peer in the process.
if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
CNodeState *remove_node = State(lNodesAnnouncingHeaderAndIDs.front());
if (remove_node != nullptr && !remove_node->m_is_inbound) {
// Put the HB outbound peer in the second slot, so that it
// doesn't get removed.
std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
}
}
}
m_connman.ForNode(nodeid, [this](CNode* pfrom) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
AssertLockHeld(::cs_main);
Expand Down

0 comments on commit 6efbcec

Please sign in to comment.