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 <net_permissions.h>
|
||||||
#include <netbase.h>
|
#include <netbase.h>
|
||||||
#include <node/ui_interface.h>
|
#include <node/ui_interface.h>
|
||||||
|
#include <optional.h>
|
||||||
#include <protocol.h>
|
#include <protocol.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
@ -840,21 +841,6 @@ size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pno
|
|||||||
return nSentSize;
|
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)
|
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
|
||||||
{
|
{
|
||||||
return a.nMinPingUsecTime > b.nMinPingUsecTime;
|
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());
|
elements.erase(elements.end() - eraseSize, elements.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Try to find a connection to evict when the node is full.
|
[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protect connections with certain characteristics
|
// Protect connections with certain characteristics
|
||||||
|
|
||||||
// Deterministically select 4 peers to protect by netgroup.
|
// Deterministically select 4 peers to protect by netgroup.
|
||||||
@ -984,7 +935,7 @@ bool CConnman::AttemptToEvictConnection()
|
|||||||
total_protect_size -= initial_size - vEvictionCandidates.size();
|
total_protect_size -= initial_size - vEvictionCandidates.size();
|
||||||
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_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.
|
// 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)
|
// 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]);
|
vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
|
||||||
|
|
||||||
// Disconnect from the network group with the most connections
|
// 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);
|
LOCK(cs_vNodes);
|
||||||
for (CNode* pnode : vNodes) {
|
for (CNode* pnode : vNodes) {
|
||||||
if (pnode->GetId() == evicted) {
|
if (pnode->GetId() == *node_id_to_evict) {
|
||||||
pnode->fDisconnect = true;
|
pnode->fDisconnect = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
18
src/net.h
18
src/net.h
@ -33,6 +33,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class CScheduler;
|
class CScheduler;
|
||||||
class CNode;
|
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())};
|
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
|
#endif // BITCOIN_NET_H
|
||||||
|
Loading…
Reference in New Issue
Block a user