@@ -5569,18 +5569,11 @@ class CompareInvMempoolOrder
55695569 mp = mempool;
55705570 }
55715571
5572- bool operator ()(const CInv & a, const CInv & b)
5572+ bool operator ()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
55735573 {
5574- if (a.type != MSG_TX && b.type != MSG_TX) {
5575- return false ;
5576- } else {
5577- if (a.type != MSG_TX) {
5578- return true ;
5579- } else if (b.type != MSG_TX) {
5580- return false ;
5581- }
5582- return mp->CompareDepthAndScore (a.hash , b.hash );
5583- }
5574+ /* As std::make_heap produces a max-heap, we want the entries with the
5575+ * fewest ancestors/highest fee to sort later. */
5576+ return mp->CompareDepthAndScore (*b, *a);
55845577 }
55855578};
55865579
@@ -5808,38 +5801,59 @@ bool SendMessages(CNode* pto)
58085801 // Message: inventory
58095802 //
58105803 vector<CInv> vInv;
5811- vector<CInv> vInvWait;
58125804 {
5805+ LOCK (pto->cs_inventory );
5806+ vInv.reserve (std::max<size_t >(pto->vInventoryBlockToSend .size (), INVENTORY_BROADCAST_MAX));
5807+
5808+ // Add blocks
5809+ BOOST_FOREACH (const uint256& hash, pto->vInventoryBlockToSend ) {
5810+ vInv.push_back (CInv (MSG_BLOCK, hash));
5811+ if (vInv.size () == MAX_INV_SZ) {
5812+ pto->PushMessage (NetMsgType::INV, vInv);
5813+ vInv.clear ();
5814+ }
5815+ }
5816+ pto->vInventoryBlockToSend .clear ();
5817+
5818+ // Determine transactions to relay
58135819 bool fSendTrickle = pto->fWhitelisted ;
58145820 if (pto->nNextInvSend < nNow) {
58155821 fSendTrickle = true ;
5816- // Use half the delay for outbound peers, as their is less privacy concern for them.
5822+ // Use half the delay for outbound peers, as there is less privacy concern for them.
58175823 pto->nNextInvSend = PoissonNextSend (nNow, INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound );
58185824 }
5819- LOCK (pto->cs_inventory );
5820- if (fSendTrickle && pto->vInventoryToSend .size () > 1 ) {
5825+ if (fSendTrickle ) {
5826+ // Produce a vector with all candidates for sending
5827+ vector<std::set<uint256>::iterator> vInvTx;
5828+ vInvTx.reserve (pto->setInventoryTxToSend .size ());
5829+ for (std::set<uint256>::iterator it = pto->setInventoryTxToSend .begin (); it != pto->setInventoryTxToSend .end (); it++) {
5830+ vInvTx.push_back (it);
5831+ }
58215832 // Topologically and fee-rate sort the inventory we send for privacy and priority reasons.
5833+ // A heap is used so that not all items need sorting if only a few are being sent.
58225834 CompareInvMempoolOrder compareInvMempoolOrder (&mempool);
5823- std::stable_sort (pto->vInventoryToSend .begin (), pto->vInventoryToSend .end (), compareInvMempoolOrder);
5824- }
5825- vInv.reserve (std::min<size_t >(INVENTORY_BROADCAST_MAX, pto->vInventoryToSend .size ()));
5826- vInvWait.reserve (pto->vInventoryToSend .size ());
5827- BOOST_FOREACH (const CInv& inv, pto->vInventoryToSend )
5828- {
5829- if (inv.type == MSG_TX && pto->filterInventoryKnown .contains (inv.hash ))
5830- continue ;
5835+ std::make_heap (vInvTx.begin (), vInvTx.end (), compareInvMempoolOrder);
58315836 // No reason to drain out at many times the network's capacity,
58325837 // especially since we have many peers and some will draw much shorter delays.
5833- if (vInv.size () >= INVENTORY_BROADCAST_MAX || (inv.type == MSG_TX && !fSendTrickle )) {
5834- vInvWait.push_back (inv);
5835- continue ;
5838+ unsigned int nRelayedTransactions = 0 ;
5839+ while (!vInvTx.empty () && nRelayedTransactions < INVENTORY_BROADCAST_MAX) {
5840+ // Fetch the top element from the heap
5841+ std::pop_heap (vInvTx.begin (), vInvTx.end (), compareInvMempoolOrder);
5842+ std::set<uint256>::iterator it = vInvTx.back ();
5843+ vInvTx.pop_back ();
5844+ uint256 hash = *it;
5845+ // Remove it from the to-be-sent set
5846+ pto->setInventoryTxToSend .erase (it);
5847+ // Check if not in the filter already
5848+ if (pto->filterInventoryKnown .contains (hash)) {
5849+ continue ;
5850+ }
5851+ // Send
5852+ vInv.push_back (CInv (MSG_TX, hash));
5853+ nRelayedTransactions++;
5854+ pto->filterInventoryKnown .insert (hash);
58365855 }
5837-
5838- pto->filterInventoryKnown .insert (inv.hash );
5839-
5840- vInv.push_back (inv);
58415856 }
5842- pto->vInventoryToSend = vInvWait;
58435857 }
58445858 if (!vInv.empty ())
58455859 pto->PushMessage (NetMsgType::INV, vInv);
0 commit comments