@@ -72,6 +72,365 @@ static bool EqualTxns(const std::set<CTransactionRef>& set_txns, const std::vect
72
72
return true ;
73
73
}
74
74
75
+ unsigned int CheckNumEvictions (node::TxOrphanage& orphanage)
76
+ {
77
+ const auto original_total_count{orphanage.CountAnnouncements ()};
78
+ orphanage.LimitOrphans ();
79
+ assert (orphanage.TotalLatencyScore () <= orphanage.MaxGlobalLatencyScore ());
80
+ assert (orphanage.TotalOrphanUsage () <= orphanage.MaxGlobalUsage ());
81
+ return original_total_count - orphanage.CountAnnouncements ();
82
+ }
83
+
84
+ BOOST_AUTO_TEST_CASE (peer_dos_limits)
85
+ {
86
+ FastRandomContext det_rand{true };
87
+
88
+ // Construct transactions to use. They must all be the same size.
89
+ static constexpr unsigned int NUM_TXNS_CREATED = 100 ;
90
+ static constexpr int64_t TX_SIZE{469 };
91
+ static constexpr int64_t TOTAL_SIZE = NUM_TXNS_CREATED * TX_SIZE;
92
+
93
+ std::vector<CTransactionRef> txns;
94
+ txns.reserve (NUM_TXNS_CREATED);
95
+ // All transactions are the same size.
96
+ for (unsigned int i{0 }; i < NUM_TXNS_CREATED; ++i) {
97
+ auto ptx = MakeTransactionSpending ({}, det_rand);
98
+ txns.emplace_back (ptx);
99
+ BOOST_CHECK_EQUAL (TX_SIZE, GetTransactionWeight (*ptx));
100
+ }
101
+
102
+ // Single peer: eviction is triggered if either limit is hit
103
+ {
104
+ // Test announcement limits
105
+ NodeId peer{8 };
106
+ auto orphanage_low_ann = node::MakeTxOrphanage (/* max_global_ann=*/ 1 , /* reserved_peer_usage=*/ TX_SIZE * 10 );
107
+ auto orphanage_low_mem = node::MakeTxOrphanage (/* max_global_ann=*/ 10 , /* reserved_peer_usage=*/ TX_SIZE);
108
+
109
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage_low_mem), 0 );
110
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage_low_ann), 0 );
111
+
112
+ // Add the first transaction
113
+ orphanage_low_ann->AddTx (txns.at (0 ), peer);
114
+ orphanage_low_mem->AddTx (txns.at (0 ), peer);
115
+
116
+ // Add more. One of the limits is exceeded, so LimitOrphans evicts 1.
117
+ orphanage_low_ann->AddTx (txns.at (1 ), peer);
118
+ BOOST_CHECK (orphanage_low_ann->TotalLatencyScore () > orphanage_low_ann->MaxGlobalLatencyScore ());
119
+ BOOST_CHECK (orphanage_low_ann->TotalOrphanUsage () <= orphanage_low_ann->MaxGlobalUsage ());
120
+
121
+ orphanage_low_mem->AddTx (txns.at (1 ), peer);
122
+ BOOST_CHECK (orphanage_low_mem->TotalLatencyScore () <= orphanage_low_mem->MaxGlobalLatencyScore ());
123
+ BOOST_CHECK (orphanage_low_mem->TotalOrphanUsage () > orphanage_low_mem->MaxGlobalUsage ());
124
+
125
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage_low_mem), 1 );
126
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage_low_ann), 1 );
127
+
128
+ // The older transaction is evicted.
129
+ BOOST_CHECK (!orphanage_low_ann->HaveTx (txns.at (0 )->GetWitnessHash ()));
130
+ BOOST_CHECK (!orphanage_low_mem->HaveTx (txns.at (0 )->GetWitnessHash ()));
131
+ BOOST_CHECK (orphanage_low_ann->HaveTx (txns.at (1 )->GetWitnessHash ()));
132
+ BOOST_CHECK (orphanage_low_mem->HaveTx (txns.at (1 )->GetWitnessHash ()));
133
+ }
134
+
135
+ // Single peer: latency score includes inputs
136
+ {
137
+ // Test latency score limits
138
+ NodeId peer{10 };
139
+ auto orphanage_low_ann = node::MakeTxOrphanage (/* max_global_ann=*/ 5 , /* reserved_peer_usage=*/ TX_SIZE * 1000 );
140
+
141
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage_low_ann), 0 );
142
+
143
+ // Add the first transaction
144
+ orphanage_low_ann->AddTx (txns.at (0 ), peer);
145
+
146
+ // Add 1 more transaction with 45 inputs. Even though there are only 2 announcements, this pushes the orphanage above its maximum latency score.
147
+ std::vector<COutPoint> outpoints_45;
148
+ for (unsigned int j{0 }; j < 45 ; ++j) {
149
+ outpoints_45.emplace_back (Txid::FromUint256 (det_rand.rand256 ()), j);
150
+ }
151
+ auto ptx = MakeTransactionSpending (outpoints_45, det_rand);
152
+ orphanage_low_ann->AddTx (ptx, peer);
153
+
154
+ BOOST_CHECK (orphanage_low_ann->TotalLatencyScore () > orphanage_low_ann->MaxGlobalLatencyScore ());
155
+ BOOST_CHECK (orphanage_low_ann->LatencyScoreFromPeer (peer) > orphanage_low_ann->MaxPeerLatencyScore ());
156
+
157
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage_low_ann), 1 );
158
+
159
+ // The older transaction is evicted.
160
+ BOOST_CHECK (!orphanage_low_ann->HaveTx (txns.at (0 )->GetWitnessHash ()));
161
+ BOOST_CHECK (orphanage_low_ann->HaveTx (ptx->GetWitnessHash ()));
162
+ }
163
+
164
+ // Single peer: eviction order is FIFO on non-reconsiderable, then reconsiderable orphans.
165
+ {
166
+ // Construct parent + child pairs
167
+ std::vector<CTransactionRef> parents;
168
+ std::vector<CTransactionRef> children;
169
+ for (unsigned int i{0 }; i < 10 ; ++i) {
170
+ CTransactionRef parent = MakeTransactionSpending ({}, det_rand);
171
+ CTransactionRef child = MakeTransactionSpending ({{parent->GetHash (), 0 }}, det_rand);
172
+ parents.emplace_back (parent);
173
+ children.emplace_back (child);
174
+ }
175
+
176
+ // Test announcement limits
177
+ NodeId peer{9 };
178
+ auto orphanage = node::MakeTxOrphanage (/* max_global_ann=*/ 3 , /* reserved_peer_usage=*/ TX_SIZE * 10 );
179
+
180
+ // First add a tx which will be made reconsiderable.
181
+ orphanage->AddTx (children.at (0 ), peer);
182
+
183
+ // Then add 2 more orphans... not oversize yet.
184
+ orphanage->AddTx (children.at (1 ), peer);
185
+ orphanage->AddTx (children.at (2 ), peer);
186
+
187
+ // Make child0 ready to reconsider
188
+ orphanage->AddChildrenToWorkSet (*parents.at (0 ), det_rand);
189
+ BOOST_CHECK (orphanage->HaveTxToReconsider (peer));
190
+
191
+ // Add 1 more orphan, causing the orphanage to be oversize. child1 is evicted.
192
+ orphanage->AddTx (children.at (3 ), peer);
193
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 1 );
194
+ BOOST_CHECK (orphanage->HaveTx (children.at (0 )->GetWitnessHash ()));
195
+ BOOST_CHECK (!orphanage->HaveTx (children.at (1 )->GetWitnessHash ()));
196
+ BOOST_CHECK (orphanage->HaveTx (children.at (2 )->GetWitnessHash ()));
197
+ BOOST_CHECK (orphanage->HaveTx (children.at (3 )->GetWitnessHash ()));
198
+
199
+ // Add 1 more... child2 is evicted.
200
+ orphanage->AddTx (children.at (4 ), peer);
201
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 1 );
202
+ BOOST_CHECK (orphanage->HaveTx (children.at (0 )->GetWitnessHash ()));
203
+ BOOST_CHECK (!orphanage->HaveTx (children.at (2 )->GetWitnessHash ()));
204
+ BOOST_CHECK (orphanage->HaveTx (children.at (3 )->GetWitnessHash ()));
205
+ BOOST_CHECK (orphanage->HaveTx (children.at (4 )->GetWitnessHash ()));
206
+
207
+ // Eviction order is FIFO within the orphans that are ready to be reconsidered.
208
+ orphanage->AddChildrenToWorkSet (*parents.at (4 ), det_rand);
209
+ orphanage->AddChildrenToWorkSet (*parents.at (3 ), det_rand);
210
+
211
+ // child5 is evicted immediately because it is the only non-reconsiderable orphan.
212
+ orphanage->AddTx (children.at (5 ), peer);
213
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 1 );
214
+ BOOST_CHECK (orphanage->HaveTx (children.at (0 )->GetWitnessHash ()));
215
+ BOOST_CHECK (orphanage->HaveTx (children.at (3 )->GetWitnessHash ()));
216
+ BOOST_CHECK (orphanage->HaveTx (children.at (4 )->GetWitnessHash ()));
217
+ BOOST_CHECK (!orphanage->HaveTx (children.at (5 )->GetWitnessHash ()));
218
+
219
+ // Transactions are marked non-reconsiderable again when returned through GetTxToReconsider
220
+ BOOST_CHECK_EQUAL (orphanage->GetTxToReconsider (peer), children.at (0 ));
221
+ orphanage->AddTx (children.at (6 ), peer);
222
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 1 );
223
+ BOOST_CHECK (!orphanage->HaveTx (children.at (0 )->GetWitnessHash ()));
224
+ BOOST_CHECK (orphanage->HaveTx (children.at (3 )->GetWitnessHash ()));
225
+ BOOST_CHECK (orphanage->HaveTx (children.at (4 )->GetWitnessHash ()));
226
+ BOOST_CHECK (orphanage->HaveTx (children.at (6 )->GetWitnessHash ()));
227
+
228
+ // The first transaction returned from GetTxToReconsider is the older one, not the one that was marked for
229
+ // reconsideration earlier.
230
+ BOOST_CHECK_EQUAL (orphanage->GetTxToReconsider (peer), children.at (3 ));
231
+ BOOST_CHECK_EQUAL (orphanage->GetTxToReconsider (peer), children.at (4 ));
232
+ }
233
+
234
+ // Multiple peers: when limit is exceeded, we choose the DoSiest peer and evict their oldest transaction.
235
+ {
236
+ NodeId peer_dosy{0 };
237
+ NodeId peer1{1 };
238
+ NodeId peer2{2 };
239
+
240
+ unsigned int max_announcements = 60 ;
241
+ // Set a high per-peer reservation so announcement limit is always hit first.
242
+ auto orphanage = node::MakeTxOrphanage (max_announcements, TOTAL_SIZE * 10 );
243
+
244
+ // No evictions happen before the global limit is reached.
245
+ for (unsigned int i{0 }; i < max_announcements; ++i) {
246
+ orphanage->AddTx (txns.at (i), peer_dosy);
247
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 0 );
248
+ }
249
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer_dosy), max_announcements);
250
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer1), 0 );
251
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer2), 0 );
252
+
253
+ // Add 10 unique transactions from peer1.
254
+ // LimitOrphans should evict from peer_dosy, because that's the one exceeding announcement limits.
255
+ unsigned int num_from_peer1 = 10 ;
256
+ for (unsigned int i{0 }; i < num_from_peer1; ++i) {
257
+ orphanage->AddTx (txns.at (max_announcements + i), peer1);
258
+ // The announcement limit per peer has halved, but LimitOrphans does not evict beyond what is necessary to
259
+ // bring the total announcements within its global limit.
260
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 1 );
261
+ BOOST_CHECK (orphanage->AnnouncementsFromPeer (peer_dosy) > orphanage->MaxPeerLatencyScore ());
262
+
263
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer1), i + 1 );
264
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer_dosy), max_announcements - i - 1 );
265
+
266
+ // Evictions are FIFO within a peer, so the ith transaction sent by peer_dosy is the one that was evicted.
267
+ BOOST_CHECK (!orphanage->HaveTx (txns.at (i)->GetWitnessHash ()));
268
+ }
269
+ // Add 10 transactions that are duplicates of the ones sent by peer_dosy. We need to add 10 because the first 10
270
+ // were just evicted in the previous block additions.
271
+ for (unsigned int i{num_from_peer1}; i < num_from_peer1 + 10 ; ++i) {
272
+ // Tx has already been sent by peer_dosy
273
+ BOOST_CHECK (orphanage->HaveTxFromPeer (txns.at (i)->GetWitnessHash (), peer_dosy));
274
+ orphanage->AddTx (txns.at (i), peer2);
275
+
276
+ // Announcement limit is by entry, not by unique orphans
277
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 1 );
278
+
279
+ // peer_dosy is still the only one getting evicted
280
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer_dosy), max_announcements - i - 1 );
281
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer1), num_from_peer1);
282
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer2), i + 1 - num_from_peer1);
283
+
284
+ // Evictions are FIFO within a peer, so the ith transaction sent by peer_dosy is the one that was evicted.
285
+ BOOST_CHECK (!orphanage->HaveTxFromPeer (txns.at (i)->GetWitnessHash (), peer_dosy));
286
+ BOOST_CHECK (orphanage->HaveTx (txns.at (i)->GetWitnessHash ()));
287
+ }
288
+
289
+ // With 6 peers, each can add 10, and still only peer_dosy's orphans are evicted.
290
+ const unsigned int max_per_peer{max_announcements / 6 };
291
+ for (NodeId peer{3 }; peer < 6 ; ++peer) {
292
+ for (unsigned int i{0 }; i < max_per_peer; ++i) {
293
+ orphanage->AddTx (txns.at (peer * max_per_peer + i), peer);
294
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 1 );
295
+ }
296
+ }
297
+ for (NodeId peer{0 }; peer < 6 ; ++peer) {
298
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer), max_per_peer);
299
+ }
300
+ }
301
+
302
+ // Limits change as more peers are added.
303
+ {
304
+ auto orphanage{node::MakeTxOrphanage ()};
305
+ // These stay the same regardless of number of peers
306
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
307
+ BOOST_CHECK_EQUAL (orphanage->ReservedPeerUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
308
+
309
+ // These change with number of peers
310
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
311
+ BOOST_CHECK_EQUAL (orphanage->MaxPeerLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
312
+
313
+ // Number of peers = 1
314
+ orphanage->AddTx (txns.at (0 ), 0 );
315
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
316
+ BOOST_CHECK_EQUAL (orphanage->ReservedPeerUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
317
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
318
+ BOOST_CHECK_EQUAL (orphanage->MaxPeerLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
319
+
320
+ // Number of peers = 2
321
+ orphanage->AddTx (txns.at (1 ), 1 );
322
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
323
+ BOOST_CHECK_EQUAL (orphanage->ReservedPeerUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
324
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 2 );
325
+ BOOST_CHECK_EQUAL (orphanage->MaxPeerLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 2 );
326
+
327
+ // Number of peers = 3
328
+ orphanage->AddTx (txns.at (2 ), 2 );
329
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
330
+ BOOST_CHECK_EQUAL (orphanage->ReservedPeerUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
331
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 3 );
332
+ BOOST_CHECK_EQUAL (orphanage->MaxPeerLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 3 );
333
+
334
+ // Number of peers didn't change.
335
+ orphanage->AddTx (txns.at (3 ), 2 );
336
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
337
+ BOOST_CHECK_EQUAL (orphanage->ReservedPeerUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
338
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 3 );
339
+ BOOST_CHECK_EQUAL (orphanage->MaxPeerLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 3 );
340
+
341
+ // Once a peer has no orphans, it is not considered in the limits.
342
+ // Number of peers = 2
343
+ orphanage->EraseForPeer (2 );
344
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
345
+ BOOST_CHECK_EQUAL (orphanage->ReservedPeerUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
346
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 2 );
347
+ BOOST_CHECK_EQUAL (orphanage->MaxPeerLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 2 );
348
+
349
+ // Number of peers = 1
350
+ orphanage->EraseTx (txns.at (0 )->GetWitnessHash ());
351
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
352
+ BOOST_CHECK_EQUAL (orphanage->ReservedPeerUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
353
+ BOOST_CHECK_EQUAL (orphanage->MaxGlobalUsage (), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
354
+ BOOST_CHECK_EQUAL (orphanage->MaxPeerLatencyScore (), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
355
+ }
356
+
357
+ // Test eviction of multiple transactions at a time
358
+ {
359
+ // Create a large transaction that is 10 times larger than the normal size transaction.
360
+ CMutableTransaction tx_large;
361
+ tx_large.vin .resize (1 );
362
+ BulkTransaction (tx_large, 10 * TX_SIZE);
363
+ auto ptx_large = MakeTransactionRef (tx_large);
364
+
365
+ const auto large_tx_size = GetTransactionWeight (*ptx_large);
366
+ BOOST_CHECK (large_tx_size > 10 * TX_SIZE);
367
+ BOOST_CHECK (large_tx_size < 11 * TX_SIZE);
368
+
369
+ auto orphanage = node::MakeTxOrphanage (20 , large_tx_size);
370
+ // One peer sends 10 normal size transactions. The other peer sends 10 normal transactions and 1 very large one
371
+ NodeId peer_normal{0 };
372
+ NodeId peer_large{1 };
373
+ for (unsigned int i = 0 ; i < 20 ; i++) {
374
+ orphanage->AddTx (txns.at (i), i < 10 ? peer_normal : peer_large);
375
+ }
376
+ BOOST_CHECK (orphanage->TotalLatencyScore () <= orphanage->MaxGlobalLatencyScore ());
377
+ BOOST_CHECK (orphanage->TotalOrphanUsage () <= orphanage->MaxGlobalUsage ());
378
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 0 );
379
+
380
+ // Add the large transaction. This should cause evictions of all the previous 10 transactions from that peer.
381
+ orphanage->AddTx (ptx_large, peer_large);
382
+ BOOST_CHECK_EQUAL (CheckNumEvictions (*orphanage), 10 );
383
+
384
+ // peer_normal should still have 10 transactions, and peer_large should have 1.
385
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer_normal), 10 );
386
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (peer_large), 1 );
387
+ BOOST_CHECK (orphanage->HaveTxFromPeer (ptx_large->GetWitnessHash (), peer_large));
388
+ BOOST_CHECK_EQUAL (orphanage->CountAnnouncements (), 11 );
389
+ }
390
+
391
+ // Test that latency score includes number of inputs.
392
+ {
393
+ auto orphanage = node::MakeTxOrphanage ();
394
+
395
+ // Add 10 transactions with 9 inputs each.
396
+ std::vector<COutPoint> outpoints_9;
397
+ for (unsigned int j{0 }; j < 9 ; ++j) {
398
+ outpoints_9.emplace_back (Txid::FromUint256 (m_rng.rand256 ()), j);
399
+ }
400
+ for (unsigned int i{0 }; i < 10 ; ++i) {
401
+ auto ptx = MakeTransactionSpending (outpoints_9, m_rng);
402
+ orphanage->AddTx (ptx, 0 );
403
+ }
404
+ BOOST_CHECK_EQUAL (orphanage->CountAnnouncements (), 10 );
405
+ BOOST_CHECK_EQUAL (orphanage->TotalLatencyScore (), 10 );
406
+
407
+ // Add 10 transactions with 50 inputs each.
408
+ std::vector<COutPoint> outpoints_50;
409
+ for (unsigned int j{0 }; j < 50 ; ++j) {
410
+ outpoints_50.emplace_back (Txid::FromUint256 (m_rng.rand256 ()), j);
411
+ }
412
+
413
+ for (unsigned int i{0 }; i < 10 ; ++i) {
414
+ CMutableTransaction tx;
415
+ std::shuffle (outpoints_50.begin (), outpoints_50.end (), m_rng);
416
+ auto ptx = MakeTransactionSpending (outpoints_50, m_rng);
417
+ BOOST_CHECK (orphanage->AddTx (ptx, 0 ));
418
+ if (i < 5 ) BOOST_CHECK (!orphanage->AddTx (ptx, 1 ));
419
+ }
420
+ // 10 of the 9-input transactions + 10 of the 50-input transactions + 5 more announcements of the 50-input transactions
421
+ BOOST_CHECK_EQUAL (orphanage->CountAnnouncements (), 25 );
422
+ // Base of 25 announcements, plus 10 * 5 for the 50-input transactions (counted just once)
423
+ BOOST_CHECK_EQUAL (orphanage->TotalLatencyScore (), 25 + 50 );
424
+
425
+ // Peer 0 sent all 20 transactions
426
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (0 ), 20 );
427
+ BOOST_CHECK_EQUAL (orphanage->LatencyScoreFromPeer (0 ), 20 + 10 * 5 );
428
+
429
+ // Peer 1 sent 5 of the 10 transactions with many inputs
430
+ BOOST_CHECK_EQUAL (orphanage->AnnouncementsFromPeer (1 ), 5 );
431
+ BOOST_CHECK_EQUAL (orphanage->LatencyScoreFromPeer (1 ), 5 + 5 * 5 );
432
+ }
433
+ }
75
434
BOOST_AUTO_TEST_CASE (DoS_mapOrphans)
76
435
{
77
436
// This test had non-deterministic coverage due to
0 commit comments