Browse Source

Don't send all transactions all the time - rather select a set of peers

each time.
cl-refactor
Gav Wood 10 years ago
parent
commit
a3a72816af
  1. 55
      libethereum/EthereumHost.cpp
  2. 2
      libethereum/EthereumHost.h

55
libethereum/EthereumHost.cpp

@ -175,18 +175,25 @@ void EthereumHost::doWork()
void EthereumHost::maintainTransactions()
{
// Send any new transactions.
map<std::shared_ptr<EthereumPeer>, 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<EthereumPeer>().get())
if (auto ep = p.first->cap<EthereumPeer>())
{
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<std::shared_ptr<EthereumPeer>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow)
{
std::vector<std::shared_ptr<EthereumPeer>> candidates;
candidates.reserve(peerSessions().size());
for (auto const& j: peerSessions())
{
auto pp = j.first->cap<EthereumPeer>();
if (_allow(pp.get()))
candidates.push_back(pp);
}
std::vector<std::shared_ptr<EthereumPeer>> 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<std::shared_ptr<EthereumPeer>> dispersal;
for (auto const& j: peerSessions())
if (!j.first->cap<EthereumPeer>()->m_knownBlocks.count(_currentHash))
dispersal.push_back(j.first->cap<EthereumPeer>());
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);

2
libethereum/EthereumHost.h

@ -77,6 +77,8 @@ public:
bool isBanned(p2p::NodeId _id) const { return !!m_banned.count(_id); }
private:
std::vector<std::shared_ptr<EthereumPeer>> randomSelection(unsigned _percent = 25, std::function<bool(EthereumPeer*)> const& _allow = [](EthereumPeer const*){ return true; });
/// Session is tell us that we may need (re-)syncing with the peer.
void noteNeedsSyncing(EthereumPeer* _who);

Loading…
Cancel
Save