Skip to content

Commit

Permalink
Merge bitcoin#17243: p2p: add PoissonNextSend method that returns moc…
Browse files Browse the repository at this point in the history
…kable time

1a8f0d5 [tools] update nNextInvSend to use mockable time (Amiti Uttarwar)
4de6303 [tools] add PoissonNextSend method that returns mockable time (Amiti Uttarwar)

Pull request description:

  Introduce a Poisson helper method that wraps the existing method to return `std::chrono::duration` type, which is mockable.

  Needed for bitcoin#16698.

ACKs for top commit:
  ajtowns:
    ACK 1a8f0d5
  MarcoFalke:
    re-ACK 1a8f0d5
  naumenkogs:
    ACK 1a8f0d5, and let's merge it and come back to it later.

Tree-SHA512: 7e2325d7c55fc0b4357cb86b83e0c218ba269f678c1786342d8bc380bfd9696373bc24ff124b9ff17a6e761c62b2b44ff5247c3911e2afdc7cc5c20417e8290b
  • Loading branch information
MarcoFalke authored and codablock committed Apr 9, 2020
1 parent 950e7ce commit 1cd6797
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 7 deletions.
10 changes: 7 additions & 3 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ class CNode
// List of non-tx/non-block inventory items
std::vector<CInv> vInventoryOtherToSend;
CCriticalSection cs_inventory;
int64_t nNextInvSend;
std::chrono::microseconds nNextInvSend{0};
// Used for headers announcements - unfiltered blocks to relay
// Also protected by cs_inventory
std::vector<uint256> vBlockHashesToAnnounce;
Expand Down Expand Up @@ -1061,9 +1061,13 @@ class CExplicitNetCleanup
static void callCleanup();
};



/** Return a timestamp in the future (in microseconds) for exponentially distributed events. */
int64_t PoissonNextSend(int64_t now, int average_interval_seconds);

/** Wrapper to return mockable type */
inline std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval)
{
return std::chrono::microseconds{PoissonNextSend(now.count(), average_interval.count())};
}

#endif // BITCOIN_NET_H
10 changes: 6 additions & 4 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3849,6 +3849,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptM

// Address refresh broadcast
int64_t nNow = GetTimeMicros();
auto current_time = GetTime<std::chrono::microseconds>();

if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
AdvertiseLocal(pto);
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
Expand Down Expand Up @@ -4085,14 +4087,14 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptM
// Note: If this node is running in a Masternode mode, it makes no sense to delay outgoing txes
// because we never produce any txes ourselves i.e. no privacy is lost in this case.
bool fSendTrickle = pto->fWhitelisted || fMasternodeMode;
if (pto->nNextInvSend < nNow) {
if (pto->nNextInvSend < current_time) {
fSendTrickle = true;
if (pto->fInbound) {
pto->nNextInvSend = connman->PoissonNextSendInbound(nNow, INVENTORY_BROADCAST_INTERVAL);
pto->nNextInvSend = std::chrono::microseconds{connman->PoissonNextSendInbound(nNow, INVENTORY_BROADCAST_INTERVAL)};
} else {
// Use half the delay for regular outbound peers, as there is less privacy concern for them.
// and quarter the delay for Masternode outbound peers, as there is even less privacy concern in this case.
pto->nNextInvSend = PoissonNextSend(nNow, INVENTORY_BROADCAST_INTERVAL >> 1 >> !pto->verifiedProRegTxHash.IsNull());
pto->nNextInvSend = PoissonNextSend(current_time, std::chrono::seconds{INVENTORY_BROADCAST_INTERVAL >> 1});
}
}

Expand Down Expand Up @@ -4226,7 +4228,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptM
connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));

// Detect whether we're stalling
const auto current_time = GetTime<std::chrono::microseconds>();
current_time = GetTime<std::chrono::microseconds>();
// nNow is the current system time (GetTimeMicros is not mockable) and
// should be replaced by the mockable current_time eventually
nNow = GetTimeMicros();
Expand Down
14 changes: 14 additions & 0 deletions src/test/net_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,18 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK(pnode2->fFeeler == false);
}

BOOST_AUTO_TEST_CASE(PoissonNextSend)
{
g_mock_deterministic_tests = true;
int64_t now = 5000;
int average_interval_seconds = 600;

auto poisson = ::PoissonNextSend(now, average_interval_seconds);
std::chrono::microseconds poisson_chrono = ::PoissonNextSend(std::chrono::microseconds{now}, std::chrono::seconds{average_interval_seconds});

BOOST_CHECK_EQUAL(poisson, poisson_chrono.count());

g_mock_deterministic_tests = false;
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 1cd6797

Please sign in to comment.