|
|
@ -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); |
|
|
|
|
|
|
|