@@ -91,6 +91,7 @@ def create_tx_below_mempoolminfee(self, wallet, utxo_to_spend=None):
91
91
def test_basic_child_then_parent (self ):
92
92
node = self .nodes [0 ]
93
93
self .log .info ("Check that opportunistic 1p1c logic works when child is received before parent" )
94
+ node .setmocktime (int (time .time ()))
94
95
95
96
low_fee_parent = self .create_tx_below_mempoolminfee (self .wallet )
96
97
high_fee_child = self .wallet .create_self_transfer (utxo_to_spend = low_fee_parent ["new_utxo" ], fee_rate = 20 * FEERATE_1SAT_VB )
@@ -100,11 +101,13 @@ def test_basic_child_then_parent(self):
100
101
# 1. Child is received first (perhaps the low feerate parent didn't meet feefilter or the requests were sent to different nodes). It is missing an input.
101
102
high_child_wtxid_int = high_fee_child ["tx" ].wtxid_int
102
103
peer_sender .send_and_ping (msg_inv ([CInv (t = MSG_WTX , h = high_child_wtxid_int )]))
104
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY )
103
105
peer_sender .wait_for_getdata ([high_child_wtxid_int ])
104
106
peer_sender .send_and_ping (msg_tx (high_fee_child ["tx" ]))
105
107
106
108
# 2. Node requests the missing parent by txid.
107
109
parent_txid_int = int (low_fee_parent ["txid" ], 16 )
110
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY + TXID_RELAY_DELAY )
108
111
peer_sender .wait_for_getdata ([parent_txid_int ])
109
112
110
113
# 3. Sender relays the parent. Parent+Child are evaluated as a package and accepted.
@@ -120,6 +123,7 @@ def test_basic_child_then_parent(self):
120
123
@cleanup
121
124
def test_basic_parent_then_child (self , wallet ):
122
125
node = self .nodes [0 ]
126
+ node .setmocktime (int (time .time ()))
123
127
low_fee_parent = self .create_tx_below_mempoolminfee (wallet )
124
128
high_fee_child = wallet .create_self_transfer (utxo_to_spend = low_fee_parent ["new_utxo" ], fee_rate = 20 * FEERATE_1SAT_VB )
125
129
@@ -146,6 +150,7 @@ def test_basic_parent_then_child(self, wallet):
146
150
# 3. Node requests the missing parent by txid.
147
151
# It should do so even if it has previously rejected that parent for being too low feerate.
148
152
parent_txid_int = int (low_fee_parent ["txid" ], 16 )
153
+ node .bumpmocktime (TXID_RELAY_DELAY )
149
154
peer_sender .wait_for_getdata ([parent_txid_int ])
150
155
151
156
# 4. Sender re-relays the parent. Parent+Child are evaluated as a package and accepted.
@@ -159,6 +164,7 @@ def test_basic_parent_then_child(self, wallet):
159
164
@cleanup
160
165
def test_low_and_high_child (self , wallet ):
161
166
node = self .nodes [0 ]
167
+ node .setmocktime (int (time .time ()))
162
168
low_fee_parent = self .create_tx_below_mempoolminfee (wallet )
163
169
# This feerate is above mempoolminfee, but not enough to also bump the low feerate parent.
164
170
feerate_just_above = node .getmempoolinfo ()["mempoolminfee" ]
@@ -189,6 +195,7 @@ def test_low_and_high_child(self, wallet):
189
195
190
196
# 3. Node requests the orphan's missing parent.
191
197
parent_txid_int = int (low_fee_parent ["txid" ], 16 )
198
+ node .bumpmocktime (TXID_RELAY_DELAY )
192
199
peer_sender .wait_for_getdata ([parent_txid_int ])
193
200
194
201
# 4. The low parent + low child are submitted as a package. They are not accepted due to low package feerate.
@@ -216,6 +223,7 @@ def test_low_and_high_child(self, wallet):
216
223
# 6. Node requests the orphan's parent, even though it has already been rejected, both by
217
224
# itself and with a child. This is necessary, otherwise high_fee_child can be censored.
218
225
parent_txid_int = int (low_fee_parent ["txid" ], 16 )
226
+ node .bumpmocktime (TXID_RELAY_DELAY )
219
227
peer_sender .wait_for_getdata ([parent_txid_int ])
220
228
221
229
# 7. The low feerate parent + high feerate child are submitted as a package.
@@ -231,6 +239,7 @@ def test_low_and_high_child(self, wallet):
231
239
def test_orphan_consensus_failure (self ):
232
240
self .log .info ("Check opportunistic 1p1c logic requires parent and child to be from the same peer" )
233
241
node = self .nodes [0 ]
242
+ node .setmocktime (int (time .time ()))
234
243
low_fee_parent = self .create_tx_below_mempoolminfee (self .wallet )
235
244
coin = low_fee_parent ["new_utxo" ]
236
245
address = node .get_deterministic_priv_key ().address
@@ -246,11 +255,13 @@ def test_orphan_consensus_failure(self):
246
255
# 1. Child is received first. It is missing an input.
247
256
child_wtxid_int = tx_orphan_bad_wit .wtxid_int
248
257
bad_orphan_sender .send_and_ping (msg_inv ([CInv (t = MSG_WTX , h = child_wtxid_int )]))
258
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY )
249
259
bad_orphan_sender .wait_for_getdata ([child_wtxid_int ])
250
260
bad_orphan_sender .send_and_ping (msg_tx (tx_orphan_bad_wit ))
251
261
252
262
# 2. Node requests the missing parent by txid.
253
263
parent_txid_int = int (low_fee_parent ["txid" ], 16 )
264
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY + TXID_RELAY_DELAY )
254
265
bad_orphan_sender .wait_for_getdata ([parent_txid_int ])
255
266
256
267
# 3. A different peer relays the parent. Package is not evaluated because the transactions
@@ -273,6 +284,8 @@ def test_orphan_consensus_failure(self):
273
284
def test_parent_consensus_failure (self ):
274
285
self .log .info ("Check opportunistic 1p1c logic with consensus-invalid parent causes disconnect of the correct peer" )
275
286
node = self .nodes [0 ]
287
+ node .setmocktime (int (time .time ()))
288
+
276
289
low_fee_parent = self .create_tx_below_mempoolminfee (self .wallet )
277
290
high_fee_child = self .wallet .create_self_transfer (utxo_to_spend = low_fee_parent ["new_utxo" ], fee_rate = 999 * FEERATE_1SAT_VB )
278
291
@@ -287,11 +300,13 @@ def test_parent_consensus_failure(self):
287
300
# 1. Child is received first. It is missing an input.
288
301
child_wtxid_int = high_fee_child ["tx" ].wtxid_int
289
302
package_sender .send_and_ping (msg_inv ([CInv (t = MSG_WTX , h = child_wtxid_int )]))
303
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY )
290
304
package_sender .wait_for_getdata ([child_wtxid_int ])
291
305
package_sender .send_and_ping (msg_tx (high_fee_child ["tx" ]))
292
306
293
307
# 2. Node requests the missing parent by txid.
294
308
parent_txid_int = tx_parent_bad_wit .txid_int
309
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY + TXID_RELAY_DELAY )
295
310
package_sender .wait_for_getdata ([parent_txid_int ])
296
311
297
312
# 3. A different node relays the parent. The parent is first evaluated by itself and
@@ -309,6 +324,7 @@ def test_parent_consensus_failure(self):
309
324
# It can send the "real" parent transaction, and the package is accepted.
310
325
parent_wtxid_int = low_fee_parent ["tx" ].wtxid_int
311
326
package_sender .send_and_ping (msg_inv ([CInv (t = MSG_WTX , h = parent_wtxid_int )]))
327
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY )
312
328
package_sender .wait_for_getdata ([parent_wtxid_int ])
313
329
package_sender .send_and_ping (msg_tx (low_fee_parent ["tx" ]))
314
330
@@ -355,6 +371,7 @@ def test_multiple_parents(self):
355
371
def test_other_parent_in_mempool (self ):
356
372
self .log .info ("Check opportunistic 1p1c works when part of a 2p1c (child already has another parent in mempool)" )
357
373
node = self .nodes [0 ]
374
+ node .setmocktime (int (time .time ()))
358
375
359
376
# Grandparent will enter mempool by itself
360
377
grandparent_high = self .wallet .create_self_transfer (fee_rate = FEERATE_1SAT_VB * 10 , confirmed_only = True )
@@ -383,6 +400,7 @@ def test_other_parent_in_mempool(self):
383
400
384
401
# 4. Node requests parent_low.
385
402
parent_low_txid_int = int (parent_low ["txid" ], 16 )
403
+ node .bumpmocktime (NONPREF_PEER_TX_DELAY + TXID_RELAY_DELAY )
386
404
peer_sender .wait_for_getdata ([parent_low_txid_int ])
387
405
peer_sender .send_and_ping (msg_tx (parent_low ["tx" ]))
388
406
@@ -410,9 +428,10 @@ def test_orphanage_dos_large(self):
410
428
411
429
peer_normal = node .add_p2p_connection (P2PInterface ())
412
430
peer_doser = node .add_p2p_connection (P2PInterface ())
431
+ num_individual_dosers = 10
413
432
414
433
self .log .info ("Create very large orphans to be sent by DoSy peers (may take a while)" )
415
- large_orphans = [create_large_orphan () for _ in range (100 )]
434
+ large_orphans = [create_large_orphan () for _ in range (50 )]
416
435
# Check to make sure these are orphans, within max standard size (to be accepted into the orphanage)
417
436
for large_orphan in large_orphans :
418
437
assert_greater_than_or_equal (100000 , large_orphan .get_vsize ())
@@ -422,11 +441,10 @@ def test_orphanage_dos_large(self):
422
441
assert not testres [0 ]["allowed" ]
423
442
assert_equal (testres [0 ]["reject-reason" ], "missing-inputs" )
424
443
425
- num_individual_dosers = 30
426
444
self .log .info (f"Connect { num_individual_dosers } peers and send a very large orphan from each one" )
427
445
# This test assumes that unrequested transactions are processed (skipping inv and
428
446
# getdata steps because they require going through request delays)
429
- # Connect 20 peers and have each of them send a large orphan.
447
+ # Connect 10 peers and have each of them send a large orphan.
430
448
for large_orphan in large_orphans [:num_individual_dosers ]:
431
449
peer_doser_individual = node .add_p2p_connection (P2PInterface ())
432
450
peer_doser_individual .send_and_ping (msg_tx (large_orphan ))
@@ -462,7 +480,7 @@ def test_orphanage_dos_large(self):
462
480
peer_normal .wait_for_getdata ([parent_txid_int ])
463
481
464
482
self .log .info ("Send another round of very large orphans from a DoSy peer" )
465
- for large_orphan in large_orphans [30 :]:
483
+ for large_orphan in large_orphans [num_individual_dosers :]:
466
484
peer_doser .send_and_ping (msg_tx (large_orphan ))
467
485
468
486
# Something was evicted; the orphanage does not contain all large orphans + the 1p1c child
@@ -480,12 +498,12 @@ def test_orphanage_dos_many(self):
480
498
481
499
peer_normal = node .add_p2p_connection (P2PInterface ())
482
500
483
- # 2 sets of peers: the first set all send the same batch_size orphans. The second set each
484
- # sends batch_size distinct orphans.
501
+ # The first set of peers all send the same batch_size orphans. Then a single peer sends
502
+ # batch_single_doser distinct orphans.
485
503
batch_size = 51
486
504
num_peers_shared = 60
487
- num_peers_unique = 40
488
-
505
+ batch_single_doser = 100
506
+ assert_greater_than ( num_peers_shared * batch_size + batch_single_doser , 3000 )
489
507
# 60 peers * 51 orphans = 3060 announcements
490
508
shared_orphans = [self .create_small_orphan () for _ in range (batch_size )]
491
509
self .log .info (f"Send the same { batch_size } orphans from { num_peers_shared } DoSy peers (may take a while)" )
@@ -525,22 +543,15 @@ def test_orphanage_dos_many(self):
525
543
node .bumpmocktime (NONPREF_PEER_TX_DELAY + TXID_RELAY_DELAY )
526
544
peer_normal .wait_for_getdata ([parent_txid_int ])
527
545
528
- # Each of the num_peers_unique peers creates a distinct set of orphans
529
- many_orphans = [self .create_small_orphan () for _ in range (batch_size * num_peers_unique )]
530
-
531
- self .log .info (f"Send sets of { batch_size } orphans from { num_peers_unique } DoSy peers (may take a while)" )
532
- for peernum in range (num_peers_unique ):
533
- peer_doser_batch = node .add_p2p_connection (P2PInterface ())
534
- this_batch_orphans = many_orphans [batch_size * peernum : batch_size * (peernum + 1 )]
535
- for tx in this_batch_orphans :
536
- # Don't wait for responses, because it dramatically increases the runtime of this test.
537
- peer_doser_batch .send_without_ping (msg_tx (tx ))
538
-
539
- # Ensure at least one of the peer's orphans shows up in getorphantxs. Since each peer is
540
- # reserved a portion of orphanage space, this must happen as long as the orphans are not
541
- # rejected for some other reason.
542
- peer_doser_batch .sync_with_ping ()
543
- self .wait_until (lambda : any ([tx .txid_hex in node .getorphantxs () for tx in this_batch_orphans ]))
546
+ self .log .info (f"Send { batch_single_doser } new orphans from one DoSy peer" )
547
+ peer_doser_batch = node .add_p2p_connection (P2PInterface ())
548
+ this_batch_orphans = [self .create_small_orphan () for _ in range (batch_single_doser )]
549
+ for tx in this_batch_orphans :
550
+ # Don't wait for responses, because it dramatically increases the runtime of this test.
551
+ peer_doser_batch .send_without_ping (msg_tx (tx ))
552
+
553
+ peer_doser_batch .sync_with_ping ()
554
+ self .wait_until (lambda : any ([tx .txid_hex in node .getorphantxs () for tx in this_batch_orphans ]))
544
555
545
556
self .log .info ("Check that orphan from normal peer still exists in orphanage" )
546
557
assert high_fee_child ["txid" ] in node .getorphantxs ()
0 commit comments