Replace trickle nodes with per-node/message Poisson delays

We used to have a trickle node, a node which was chosen in each iteration of
the send loop that was privileged and allowed to send out queued up non-time
critical messages. Since the removal of the fixed sleeps in the network code,
this resulted in fast and attackable treatment of such broadcasts.

This pull request changes the 3 remaining trickle use cases by random delays:
* Local address broadcast (while also removing the the wiping of the seen filter)
* Address relay
* Inv relay (for transactions; blocks are always relayed immediately)

The code is based on older commits by Patrick Strateman.
This commit is contained in:
Pieter Wuille
2015-04-08 11:20:00 -07:00
parent 9ee02cf564
commit 5400ef6bcb
5 changed files with 47 additions and 36 deletions

View File

@@ -5326,7 +5326,7 @@ bool ProcessMessages(CNode* pfrom)
}
bool SendMessages(CNode* pto, bool fSendTrickle)
bool SendMessages(CNode* pto)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
{
@@ -5368,28 +5368,17 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
return true;
// Address refresh broadcast
static int64_t nLastRebroadcast;
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
// Periodically clear addrKnown to allow refresh broadcasts
if (nLastRebroadcast)
pnode->addrKnown.reset();
// Rebroadcast our address
AdvertizeLocal(pnode);
}
if (!vNodes.empty())
nLastRebroadcast = GetTime();
int64_t nNow = GetTimeMicros();
if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
AdvertizeLocal(pto);
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
//
// Message: addr
//
if (fSendTrickle)
{
if (pto->nNextAddrSend < nNow) {
pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL);
vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size());
BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend)
@@ -5563,8 +5552,13 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
vector<CInv> vInv;
vector<CInv> vInvWait;
{
bool fSendTrickle = pto->fWhitelisted;
if (pto->nNextInvSend < nNow) {
fSendTrickle = true;
pto->nNextInvSend = PoissonNextSend(nNow, AVG_INVENTORY_BROADCAST_INTERVAL);
}
LOCK(pto->cs_inventory);
vInv.reserve(pto->vInventoryToSend.size());
vInv.reserve(std::min<size_t>(1000, pto->vInventoryToSend.size()));
vInvWait.reserve(pto->vInventoryToSend.size());
BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
{
@@ -5604,7 +5598,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pto->PushMessage(NetMsgType::INV, vInv);
// Detect whether we're stalling
int64_t nNow = GetTimeMicros();
nNow = GetTimeMicros();
if (!pto->fDisconnect && state.nStallingSince && state.nStallingSince < nNow - 1000000 * BLOCK_STALLING_TIMEOUT) {
// Stalling only triggers when the block download window cannot move. During normal steady state,
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection