Use 64-bit SipHash of netgroups in eviction

This commit is contained in:
Pieter Wuille 2016-05-25 15:38:32 +02:00
parent 9bf156bb9e
commit c31b24f745
2 changed files with 29 additions and 32 deletions

View file

@ -839,7 +839,7 @@ struct NodeEvictionCandidate
int64_t nTimeConnected; int64_t nTimeConnected;
int64_t nMinPingUsecTime; int64_t nMinPingUsecTime;
CAddress addr; CAddress addr;
std::vector<unsigned char> vchKeyedNetGroup; uint64_t nKeyedNetGroup;
}; };
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
@ -853,7 +853,7 @@ static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, cons
} }
static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) { static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) {
return a.vchKeyedNetGroup < b.vchKeyedNetGroup; return a.nKeyedNetGroup < b.nKeyedNetGroup;
}; };
/** Try to find a connection to evict when the node is full. /** Try to find a connection to evict when the node is full.
@ -876,7 +876,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
continue; continue;
if (node->fDisconnect) if (node->fDisconnect)
continue; continue;
NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr, node->vchKeyedNetGroup}; NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr, node->nKeyedNetGroup};
vEvictionCandidates.push_back(candidate); vEvictionCandidates.push_back(candidate);
} }
} }
@ -908,24 +908,24 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
// Identify the network group with the most connections and youngest member. // Identify the network group with the most connections and youngest member.
// (vEvictionCandidates is already sorted by reverse connect time) // (vEvictionCandidates is already sorted by reverse connect time)
std::vector<unsigned char> naMostConnections; uint64_t naMostConnections;
unsigned int nMostConnections = 0; unsigned int nMostConnections = 0;
int64_t nMostConnectionsTime = 0; int64_t nMostConnectionsTime = 0;
std::map<std::vector<unsigned char>, std::vector<NodeEvictionCandidate> > mapAddrCounts; std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapAddrCounts;
BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) { BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) {
mapAddrCounts[node.addr.GetGroup()].push_back(node); mapAddrCounts[node.nKeyedNetGroup].push_back(node);
int64_t grouptime = mapAddrCounts[node.addr.GetGroup()][0].nTimeConnected; int64_t grouptime = mapAddrCounts[node.nKeyedNetGroup][0].nTimeConnected;
size_t groupsize = mapAddrCounts[node.addr.GetGroup()].size(); size_t groupsize = mapAddrCounts[node.nKeyedNetGroup].size();
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) { if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
nMostConnections = groupsize; nMostConnections = groupsize;
nMostConnectionsTime = grouptime; nMostConnectionsTime = grouptime;
naMostConnections = node.addr.GetGroup(); naMostConnections = node.nKeyedNetGroup;
} }
} }
// Reduce to the network group with the most connections // Reduce to the network group with the most connections
vEvictionCandidates = mapAddrCounts[naMostConnections]; vEvictionCandidates = std::move(mapAddrCounts[naMostConnections]);
// Do not disconnect peers if there is only one unprotected connection from their network group. // Do not disconnect peers if there is only one unprotected connection from their network group.
// This step excessively favors netgroup diversity, and should be removed once more protective criteria are established. // This step excessively favors netgroup diversity, and should be removed once more protective criteria are established.
@ -2318,6 +2318,8 @@ unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", DEFAULT_MAX
CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) :
ssSend(SER_NETWORK, INIT_PROTO_VERSION), ssSend(SER_NETWORK, INIT_PROTO_VERSION),
addr(addrIn),
nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)),
addrKnown(5000, 0.001), addrKnown(5000, 0.001),
filterInventoryKnown(50000, 0.000001) filterInventoryKnown(50000, 0.000001)
{ {
@ -2330,7 +2332,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
nRecvBytes = 0; nRecvBytes = 0;
nTimeConnected = GetTime(); nTimeConnected = GetTime();
nTimeOffset = 0; nTimeOffset = 0;
addr = addrIn;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
nVersion = 0; nVersion = 0;
strSubVer = ""; strSubVer = "";
@ -2365,8 +2366,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
lastSentFeeFilter = 0; lastSentFeeFilter = 0;
nextSendTimeFeeFilter = 0; nextSendTimeFeeFilter = 0;
CalculateKeyedNetGroup();
BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes())
mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[msg] = 0;
mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0;
@ -2599,3 +2598,17 @@ bool CBanDB::Read(banmap_t& banSet)
int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);
} }
/* static */ uint64_t CNode::CalculateKeyedNetGroup(const CAddress& ad)
{
static uint64_t k0 = 0, k1 = 0;
while (k0 == 0 && k1 == 0) {
// Make sure this only runs on the first invocation.
GetRandBytes((unsigned char*)&k0, sizeof(k0));
GetRandBytes((unsigned char*)&k1, sizeof(k1));
}
std::vector<unsigned char> vchNetGroup(ad.GetGroup());
return CSipHasher(k0, k1).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize();
}

View file

@ -9,8 +9,6 @@
#include "amount.h" #include "amount.h"
#include "bloom.h" #include "bloom.h"
#include "compat.h" #include "compat.h"
#include "crypto/common.h"
#include "crypto/sha256.h"
#include "limitedmap.h" #include "limitedmap.h"
#include "netbase.h" #include "netbase.h"
#include "protocol.h" #include "protocol.h"
@ -337,7 +335,7 @@ public:
int64_t nLastRecv; int64_t nLastRecv;
int64_t nTimeConnected; int64_t nTimeConnected;
int64_t nTimeOffset; int64_t nTimeOffset;
CAddress addr; const CAddress addr;
std::string addrName; std::string addrName;
CService addrLocal; CService addrLocal;
int nVersion; int nVersion;
@ -365,7 +363,7 @@ public:
int nRefCount; int nRefCount;
NodeId id; NodeId id;
std::vector<unsigned char> vchKeyedNetGroup; const uint64_t nKeyedNetGroup;
protected: protected:
// Denial-of-service detection/prevention // Denial-of-service detection/prevention
@ -454,22 +452,8 @@ private:
CNode(const CNode&); CNode(const CNode&);
void operator=(const CNode&); void operator=(const CNode&);
void CalculateKeyedNetGroup() { static uint64_t CalculateKeyedNetGroup(const CAddress& ad);
static std::vector<unsigned char> vchSecretKey;
if (vchSecretKey.empty()) {
vchSecretKey.resize(32, 0);
GetRandBytes(vchSecretKey.data(), vchSecretKey.size());
}
std::vector<unsigned char> vchNetGroup(this->addr.GetGroup());
CSHA256 hash;
hash.Write(begin_ptr(vchNetGroup), vchNetGroup.size());
hash.Write(begin_ptr(vchSecretKey), vchSecretKey.size());
vchKeyedNetGroup.resize(32, 0);
hash.Finalize(begin_ptr(vchKeyedNetGroup));
}
public: public:
NodeId GetId() const { NodeId GetId() const {