mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 02:25:40 +01:00
net: Move eviction node selection logic to SelectNodeToEvict(...)
This commit is contained in:
parent
00f4dcd552
commit
ed73f8cee0
101
src/net.cpp
101
src/net.cpp
@ -16,6 +16,7 @@
|
||||
#include <net_permissions.h>
|
||||
#include <netbase.h>
|
||||
#include <node/ui_interface.h>
|
||||
#include <optional.h>
|
||||
#include <protocol.h>
|
||||
#include <random.h>
|
||||
#include <scheduler.h>
|
||||
@ -840,21 +841,6 @@ size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pno
|
||||
return nSentSize;
|
||||
}
|
||||
|
||||
struct NodeEvictionCandidate
|
||||
{
|
||||
NodeId id;
|
||||
int64_t nTimeConnected;
|
||||
int64_t nMinPingUsecTime;
|
||||
int64_t nLastBlockTime;
|
||||
int64_t nLastTXTime;
|
||||
bool fRelevantServices;
|
||||
bool fRelayTxes;
|
||||
bool fBloomFilter;
|
||||
uint64_t nKeyedNetGroup;
|
||||
bool prefer_evict;
|
||||
bool m_is_local;
|
||||
};
|
||||
|
||||
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
|
||||
{
|
||||
return a.nMinPingUsecTime > b.nMinPingUsecTime;
|
||||
@ -910,43 +896,8 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,
|
||||
elements.erase(elements.end() - eraseSize, elements.end());
|
||||
}
|
||||
|
||||
/** Try to find a connection to evict when the node is full.
|
||||
* Extreme care must be taken to avoid opening the node to attacker
|
||||
* triggered network partitioning.
|
||||
* The strategy used here is to protect a small number of peers
|
||||
* for each of several distinct characteristics which are difficult
|
||||
* to forge. In order to partition a node the attacker must be
|
||||
* simultaneously better at all of them than honest peers.
|
||||
*/
|
||||
bool CConnman::AttemptToEvictConnection()
|
||||
[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
|
||||
{
|
||||
std::vector<NodeEvictionCandidate> vEvictionCandidates;
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
|
||||
for (const CNode* node : vNodes) {
|
||||
if (node->HasPermission(PF_NOBAN))
|
||||
continue;
|
||||
if (!node->IsInboundConn())
|
||||
continue;
|
||||
if (node->fDisconnect)
|
||||
continue;
|
||||
bool peer_relay_txes = false;
|
||||
bool peer_filter_not_null = false;
|
||||
if (node->m_tx_relay != nullptr) {
|
||||
LOCK(node->m_tx_relay->cs_filter);
|
||||
peer_relay_txes = node->m_tx_relay->fRelayTxes;
|
||||
peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
|
||||
}
|
||||
NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
|
||||
node->nLastBlockTime, node->nLastTXTime,
|
||||
HasAllDesirableServiceFlags(node->nServices),
|
||||
peer_relay_txes, peer_filter_not_null, node->nKeyedNetGroup,
|
||||
node->m_prefer_evict, node->addr.IsLocal()};
|
||||
vEvictionCandidates.push_back(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Protect connections with certain characteristics
|
||||
|
||||
// Deterministically select 4 peers to protect by netgroup.
|
||||
@ -984,7 +935,7 @@ bool CConnman::AttemptToEvictConnection()
|
||||
total_protect_size -= initial_size - vEvictionCandidates.size();
|
||||
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_size);
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
if (vEvictionCandidates.empty()) return nullopt;
|
||||
|
||||
// If any remaining peers are preferred for eviction consider only them.
|
||||
// This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
|
||||
@ -1016,10 +967,52 @@ bool CConnman::AttemptToEvictConnection()
|
||||
vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
|
||||
|
||||
// Disconnect from the network group with the most connections
|
||||
NodeId evicted = vEvictionCandidates.front().id;
|
||||
return vEvictionCandidates.front().id;
|
||||
}
|
||||
|
||||
/** Try to find a connection to evict when the node is full.
|
||||
* Extreme care must be taken to avoid opening the node to attacker
|
||||
* triggered network partitioning.
|
||||
* The strategy used here is to protect a small number of peers
|
||||
* for each of several distinct characteristics which are difficult
|
||||
* to forge. In order to partition a node the attacker must be
|
||||
* simultaneously better at all of them than honest peers.
|
||||
*/
|
||||
bool CConnman::AttemptToEvictConnection()
|
||||
{
|
||||
std::vector<NodeEvictionCandidate> vEvictionCandidates;
|
||||
{
|
||||
|
||||
LOCK(cs_vNodes);
|
||||
for (const CNode* node : vNodes) {
|
||||
if (node->HasPermission(PF_NOBAN))
|
||||
continue;
|
||||
if (!node->IsInboundConn())
|
||||
continue;
|
||||
if (node->fDisconnect)
|
||||
continue;
|
||||
bool peer_relay_txes = false;
|
||||
bool peer_filter_not_null = false;
|
||||
if (node->m_tx_relay != nullptr) {
|
||||
LOCK(node->m_tx_relay->cs_filter);
|
||||
peer_relay_txes = node->m_tx_relay->fRelayTxes;
|
||||
peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
|
||||
}
|
||||
NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
|
||||
node->nLastBlockTime, node->nLastTXTime,
|
||||
HasAllDesirableServiceFlags(node->nServices),
|
||||
peer_relay_txes, peer_filter_not_null, node->nKeyedNetGroup,
|
||||
node->m_prefer_evict, node->addr.IsLocal()};
|
||||
vEvictionCandidates.push_back(candidate);
|
||||
}
|
||||
}
|
||||
const Optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
|
||||
if (!node_id_to_evict) {
|
||||
return false;
|
||||
}
|
||||
LOCK(cs_vNodes);
|
||||
for (CNode* pnode : vNodes) {
|
||||
if (pnode->GetId() == evicted) {
|
||||
if (pnode->GetId() == *node_id_to_evict) {
|
||||
pnode->fDisconnect = true;
|
||||
return true;
|
||||
}
|
||||
|
18
src/net.h
18
src/net.h
@ -33,6 +33,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
class CScheduler;
|
||||
class CNode;
|
||||
@ -1226,4 +1227,21 @@ inline std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now,
|
||||
return std::chrono::microseconds{PoissonNextSend(now.count(), average_interval.count())};
|
||||
}
|
||||
|
||||
struct NodeEvictionCandidate
|
||||
{
|
||||
NodeId id;
|
||||
int64_t nTimeConnected;
|
||||
int64_t nMinPingUsecTime;
|
||||
int64_t nLastBlockTime;
|
||||
int64_t nLastTXTime;
|
||||
bool fRelevantServices;
|
||||
bool fRelayTxes;
|
||||
bool fBloomFilter;
|
||||
uint64_t nKeyedNetGroup;
|
||||
bool prefer_evict;
|
||||
bool m_is_local;
|
||||
};
|
||||
|
||||
[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates);
|
||||
|
||||
#endif // BITCOIN_NET_H
|
||||
|
Loading…
Reference in New Issue
Block a user