|
@ -120,7 +120,7 @@ void EthereumHost::maintainTransactions() |
|
|
for (auto const& i: ts) |
|
|
for (auto const& i: ts) |
|
|
{ |
|
|
{ |
|
|
bool unsent = !m_transactionsSent.count(i.first); |
|
|
bool unsent = !m_transactionsSent.count(i.first); |
|
|
for (auto const& p: randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); }).second) |
|
|
for (auto const& p: get<1>(randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); }))) |
|
|
peerTransactions[p].push_back(i.first); |
|
|
peerTransactions[p].push_back(i.first); |
|
|
} |
|
|
} |
|
|
for (auto const& t: ts) |
|
|
for (auto const& t: ts) |
|
@ -165,24 +165,32 @@ void EthereumHost::forEachPeerPtr(std::function<void(std::shared_ptr<EthereumPee |
|
|
_f(s.first->cap<EthereumPeer>(c_oldProtocolVersion)); |
|
|
_f(s.first->cap<EthereumPeer>(c_oldProtocolVersion)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pair<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow) |
|
|
tuple<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<Session>>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow) |
|
|
{ |
|
|
{ |
|
|
pair<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>> ret; |
|
|
vector<shared_ptr<EthereumPeer>> chosen; |
|
|
forEachPeerPtr([&](shared_ptr<EthereumPeer> _p) |
|
|
vector<shared_ptr<EthereumPeer>> allowed; |
|
|
|
|
|
vector<shared_ptr<Session>> sessions; |
|
|
|
|
|
|
|
|
|
|
|
auto const& ps = peerSessions(); |
|
|
|
|
|
allowed.reserve(ps.size()); |
|
|
|
|
|
for (auto const& j: ps) |
|
|
{ |
|
|
{ |
|
|
if (_p && _allow(_p.get())) |
|
|
auto pp = j.first->cap<EthereumPeer>(); |
|
|
ret.second.push_back(_p); |
|
|
if (_allow(pp.get())) |
|
|
}); |
|
|
{ |
|
|
|
|
|
allowed.push_back(move(pp)); |
|
|
|
|
|
sessions.push_back(move(j.first)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
size_t size = (ret.second.size() * _percent + 99) / 100; |
|
|
chosen.reserve((ps.size() * _percent + 99) / 100); |
|
|
ret.second.reserve(size); |
|
|
for (unsigned i = (ps.size() * _percent + 99) / 100; i-- && allowed.size();) |
|
|
for (unsigned i = size; i-- && ret.second.size();) |
|
|
|
|
|
{ |
|
|
{ |
|
|
unsigned n = rand() % ret.second.size(); |
|
|
unsigned n = rand() % allowed.size(); |
|
|
ret.first.push_back(std::move(ret.second[n])); |
|
|
chosen.push_back(std::move(allowed[n])); |
|
|
ret.second.erase(ret.second.begin() + n); |
|
|
allowed.erase(allowed.begin() + n); |
|
|
} |
|
|
} |
|
|
return ret; |
|
|
return make_tuple(move(chosen), move(allowed), move(sessions)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void EthereumHost::maintainBlocks(h256 const& _currentHash) |
|
|
void EthereumHost::maintainBlocks(h256 const& _currentHash) |
|
@ -200,7 +208,7 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash) |
|
|
h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true)); |
|
|
h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true)); |
|
|
|
|
|
|
|
|
auto s = randomSelection(25, [&](EthereumPeer* p){ DEV_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; }); |
|
|
auto s = randomSelection(25, [&](EthereumPeer* p){ DEV_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; }); |
|
|
for (shared_ptr<EthereumPeer> const& p: s.first) |
|
|
for (shared_ptr<EthereumPeer> const& p: get<0>(s)) |
|
|
for (auto const& b: blocks) |
|
|
for (auto const& b: blocks) |
|
|
{ |
|
|
{ |
|
|
RLPStream ts; |
|
|
RLPStream ts; |
|
@ -210,7 +218,7 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash) |
|
|
p->sealAndSend(ts); |
|
|
p->sealAndSend(ts); |
|
|
p->m_knownBlocks.clear(); |
|
|
p->m_knownBlocks.clear(); |
|
|
} |
|
|
} |
|
|
for (shared_ptr<EthereumPeer> const& p: s.second) |
|
|
for (shared_ptr<EthereumPeer> const& p: get<1>(s)) |
|
|
{ |
|
|
{ |
|
|
RLPStream ts; |
|
|
RLPStream ts; |
|
|
p->prep(ts, NewBlockHashesPacket, blocks.size()); |
|
|
p->prep(ts, NewBlockHashesPacket, blocks.size()); |
|
|