From a33b1691f11316f839ddfdf51e1950acf0bc08aa Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 9 Sep 2016 13:56:03 +0200 Subject: [PATCH] Do not fully sort all nodes for addr relay As we only need 1 or 2, explicitly keep track of the best ones. --- src/main.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 44031e69e7..f5e94d8ec7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4804,26 +4804,35 @@ static void RelayTransaction(const CTransaction& tx, CConnman& connman) static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connman) { - int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) + unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) // Relay to a limited number of other nodes // Use deterministic randomness to send to the same nodes for 24 hours // at a time so the addrKnowns of the chosen nodes prevent repeats uint64_t hashAddr = addr.GetHash(); - std::multimap mapMix; const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); FastRandomContext insecure_rand; - auto sortfunc = [&mapMix, &hasher](CNode* pnode) { + std::array,2> best{{{0, nullptr}, {0, nullptr}}}; + assert(nRelayNodes <= best.size()); + + auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) { if (pnode->nVersion >= CADDR_TIME_VERSION) { uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize(); - mapMix.emplace(hashKey, pnode); + for (unsigned int i = 0; i < nRelayNodes; i++) { + if (hashKey > best[i].first) { + std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1); + best[i] = std::make_pair(hashKey, pnode); + break; + } + } } }; - auto pushfunc = [&addr, &mapMix, &nRelayNodes, &insecure_rand] { - for (auto mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) - mi->second->PushAddress(addr, insecure_rand); + auto pushfunc = [&addr, &best, nRelayNodes, &insecure_rand] { + for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) { + best[i].second->PushAddress(addr, insecure_rand); + } }; connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));