From a3a72816af7c5985398390cc5397a507a8235de2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Apr 2015 00:37:10 +0200 Subject: [PATCH] Don't send all transactions all the time - rather select a set of peers each time. --- libethereum/EthereumHost.cpp | 55 ++++++++++++++++++++++++------------ libethereum/EthereumHost.h | 2 ++ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index de85d94bb..cb29980fd 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -175,18 +175,25 @@ void EthereumHost::doWork() void EthereumHost::maintainTransactions() { // Send any new transactions. + map, h256s> peerTransactions; + auto ts = m_tq.transactions(); + for (auto const& i: ts) + { + bool unsent = !m_transactionsSent.count(i.first); + for (auto const& p: randomSelection(25, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); })) + peerTransactions[p].push_back(i.first); + } for (auto p: peerSessions()) - if (auto ep = p.first->cap().get()) + if (auto ep = p.first->cap()) { bytes b; unsigned n = 0; - for (auto const& i: m_tq.transactions()) - if (ep->m_requireTransactions || (!m_transactionsSent.count(i.first) && !ep->m_knownTransactions.count(i.first))) - { - b += i.second.rlp(); - ++n; - m_transactionsSent.insert(i.first); - } + for (auto const& h: peerTransactions[ep]) + { + b += ts[h].rlp(); + ++n; + m_transactionsSent.insert(h); + } ep->clearKnownTransactions(); if (n || ep->m_requireTransactions) @@ -199,6 +206,27 @@ void EthereumHost::maintainTransactions() } } +std::vector> EthereumHost::randomSelection(unsigned _percent, std::function const& _allow) +{ + std::vector> candidates; + candidates.reserve(peerSessions().size()); + for (auto const& j: peerSessions()) + { + auto pp = j.first->cap(); + if (_allow(pp.get())) + candidates.push_back(pp); + } + + std::vector> ret; + for (unsigned i = (peerSessions().size() * _percent + 99) / 100; i-- && candidates.size();) + { + unsigned n = rand() % candidates.size(); + ret.push_back(std::move(candidates[n])); + candidates.erase(candidates.begin() + n); + } + return ret; +} + void EthereumHost::maintainBlocks(h256 _currentHash) { // Send any new blocks. @@ -206,17 +234,8 @@ void EthereumHost::maintainBlocks(h256 _currentHash) { clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; - std::vector> dispersal; - for (auto const& j: peerSessions()) - if (!j.first->cap()->m_knownBlocks.count(_currentHash)) - dispersal.push_back(j.first->cap()); - - for (unsigned i = (dispersal.size() + 3) / 4; i--;) + for (auto const& p: randomSelection(25, [&](EthereumPeer* p){return !p->m_knownBlocks.count(_currentHash); })) { - unsigned n = rand() % dispersal.size(); - auto p = std::move(dispersal[n]); - dispersal.erase(dispersal.begin() + n); - RLPStream ts; p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(), 1).append(m_chain.details().totalDifficulty); diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 06575092c..fad0b8edd 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -77,6 +77,8 @@ public: bool isBanned(p2p::NodeId _id) const { return !!m_banned.count(_id); } private: + std::vector> randomSelection(unsigned _percent = 25, std::function const& _allow = [](EthereumPeer const*){ return true; }); + /// Session is tell us that we may need (re-)syncing with the peer. void noteNeedsSyncing(EthereumPeer* _who);