@@ -444,6 +444,8 @@ class PeerManagerImpl final : public PeerManager
444444 */
445445 std::map<NodeId, PeerRef> m_peer_map GUARDED_BY (m_peer_mutex);
446446
447+ std::atomic<std::chrono::microseconds> m_next_send_inv_to_incoming{0us};
448+
447449 /* * Number of nodes with fSyncStarted. */
448450 int nSyncStarted GUARDED_BY (cs_main) = 0;
449451
@@ -518,6 +520,15 @@ class PeerManagerImpl final : public PeerManager
518520 Mutex m_recent_confirmed_transactions_mutex;
519521 CRollingBloomFilter m_recent_confirmed_transactions GUARDED_BY (m_recent_confirmed_transactions_mutex){48'000 , 0.000'001 };
520522
523+ /* *
524+ * For sending `inv`s to inbound peers, we use a single (exponentially
525+ * distributed) timer for all peers. If we used a separate timer for each
526+ * peer, a spy node could make multiple inbound connections to us to
527+ * accurately determine when we received the transaction (and potentially
528+ * determine the transaction's origin). */
529+ std::chrono::microseconds PoissonNextSendInbound (std::chrono::microseconds now,
530+ std::chrono::seconds average_interval);
531+
521532 /* * Have we requested this block from a peer */
522533 bool IsBlockRequested (const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
523534
@@ -819,6 +830,18 @@ static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUS
819830 nPreferredDownload += state->fPreferredDownload ;
820831}
821832
833+ std::chrono::microseconds PeerManagerImpl::PoissonNextSendInbound (std::chrono::microseconds now,
834+ std::chrono::seconds average_interval)
835+ {
836+ if (m_next_send_inv_to_incoming.load () < now) {
837+ // If this function were called from multiple threads simultaneously
838+ // it would possible that both update the next send variable, and return a different result to their caller.
839+ // This is not possible in practice as only the net processing thread invokes this function.
840+ m_next_send_inv_to_incoming = GetExponentialRand (now, average_interval);
841+ }
842+ return m_next_send_inv_to_incoming;
843+ }
844+
822845bool PeerManagerImpl::IsBlockRequested (const uint256& hash)
823846{
824847 return mapBlocksInFlight.find (hash) != mapBlocksInFlight.end ();
@@ -4786,7 +4809,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
47864809 if (pto->m_tx_relay ->nNextInvSend < current_time) {
47874810 fSendTrickle = true ;
47884811 if (pto->IsInboundConn ()) {
4789- pto->m_tx_relay ->nNextInvSend = m_connman. PoissonNextSendInbound (current_time, INBOUND_INVENTORY_BROADCAST_INTERVAL);
4812+ pto->m_tx_relay ->nNextInvSend = PoissonNextSendInbound (current_time, INBOUND_INVENTORY_BROADCAST_INTERVAL);
47904813 } else {
47914814 pto->m_tx_relay ->nNextInvSend = GetExponentialRand (current_time, OUTBOUND_INVENTORY_BROADCAST_INTERVAL);
47924815 }
0 commit comments