diff options
author | Suhas Daftuar <sdaftuar@gmail.com> | 2021-06-03 16:38:59 -0400 |
---|---|---|
committer | Suhas Daftuar <sdaftuar@gmail.com> | 2021-06-03 17:15:25 -0400 |
commit | 6efbcec4ded6116a42d2783c96c60ef0f255a1b2 (patch) | |
tree | ff6beb7807b1c5b1fa976ffc83dc4795ca4d179b /src/net_processing.cpp | |
parent | c7dd9ff71b9c2e62fa7ecfb37ee7a5841ad67ecc (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.cpp | 15 |
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); |