aboutsummaryrefslogtreecommitdiff
path: root/src/net_processing.cpp
diff options
context:
space:
mode:
authorSuhas Daftuar <sdaftuar@gmail.com>2021-06-03 16:38:59 -0400
committerSuhas Daftuar <sdaftuar@gmail.com>2021-06-03 17:15:25 -0400
commit6efbcec4ded6116a42d2783c96c60ef0f255a1b2 (patch)
treeff6beb7807b1c5b1fa976ffc83dc4795ca4d179b /src/net_processing.cpp
parentc7dd9ff71b9c2e62fa7ecfb37ee7a5841ad67ecc (diff)
Protect last outbound HB compact block peer
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.
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r--src/net_processing.cpp15
1 files changed, 15 insertions, 0 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 65224b4259..2f2614a11a 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -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);