18
18
assert_equal ,
19
19
assert_fee_amount ,
20
20
assert_raises_rpc_error ,
21
+ fill_mempool ,
21
22
)
22
23
from test_framework .wallet import (
23
24
DEFAULT_FEE ,
@@ -82,7 +83,8 @@ def run_test(self):
82
83
self .test_conflicting ()
83
84
self .test_rbf ()
84
85
self .test_submitpackage ()
85
- self .test_maxfeerate_maxburn_submitpackage ()
86
+ self .test_maxfeerate_submitpackage ()
87
+ self .test_maxburn_submitpackage ()
86
88
87
89
def test_independent (self , coin ):
88
90
self .log .info ("Test multiple independent transactions in a package" )
@@ -358,7 +360,7 @@ def test_submitpackage(self):
358
360
assert_equal (res ["tx-results" ][sec_wtxid ]["error" ], "version" )
359
361
peer .wait_for_broadcast ([first_wtxid ])
360
362
361
- def test_maxfeerate_maxburn_submitpackage (self ):
363
+ def test_maxfeerate_submitpackage (self ):
362
364
node = self .nodes [0 ]
363
365
# clear mempool
364
366
deterministic_address = node .get_deterministic_priv_key ().address
@@ -369,23 +371,72 @@ def test_maxfeerate_maxburn_submitpackage(self):
369
371
minrate_btc_kvb = min ([chained_txn ["fee" ] / chained_txn ["tx" ].get_vsize () * 1000 for chained_txn in chained_txns ])
370
372
chain_hex = [t ["hex" ] for t in chained_txns ]
371
373
pkg_result = node .submitpackage (chain_hex , maxfeerate = minrate_btc_kvb - Decimal ("0.00000001" ))
374
+
375
+ # First tx failed in single transaction evaluation, so package message is generic
376
+ assert_equal (pkg_result ["package_msg" ], "transaction failed" )
372
377
assert_equal (pkg_result ["tx-results" ][chained_txns [0 ]["wtxid" ]]["error" ], "max feerate exceeded" )
373
378
assert_equal (pkg_result ["tx-results" ][chained_txns [1 ]["wtxid" ]]["error" ], "bad-txns-inputs-missingorspent" )
374
379
assert_equal (node .getrawmempool (), [])
375
380
381
+ # Make chain of two transactions where parent doesn't make minfee threshold
382
+ # but child is too high fee
383
+ # Lower mempool limit to make it easier to fill_mempool
384
+ self .restart_node (0 , extra_args = [
385
+ "-datacarriersize=100000" ,
386
+ "-maxmempool=5" ,
387
+ "-persistmempool=0" ,
388
+ ])
389
+
390
+ fill_mempool (self , node , self .wallet )
391
+
392
+ minrelay = node .getmempoolinfo ()["minrelaytxfee" ]
393
+ parent = self .wallet .create_self_transfer (
394
+ fee_rate = minrelay ,
395
+ )
396
+
397
+ child = self .wallet .create_self_transfer (
398
+ fee_rate = DEFAULT_FEE ,
399
+ utxo_to_spend = parent ["new_utxo" ],
400
+ )
401
+
402
+ pkg_result = node .submitpackage ([parent ["hex" ], child ["hex" ]], maxfeerate = DEFAULT_FEE - Decimal ("0.00000001" ))
403
+
404
+ # Child is connected even though parent is invalid and still reports fee exceeded
405
+ # this implies sub-package evaluation of both entries together.
406
+ assert_equal (pkg_result ["package_msg" ], "transaction failed" )
407
+ assert "mempool min fee not met" in pkg_result ["tx-results" ][parent ["wtxid" ]]["error" ]
408
+ assert_equal (pkg_result ["tx-results" ][child ["wtxid" ]]["error" ], "max feerate exceeded" )
409
+ assert parent ["txid" ] not in node .getrawmempool ()
410
+ assert child ["txid" ] not in node .getrawmempool ()
411
+
412
+ # Reset maxmempool, datacarriersize, reset dynamic mempool minimum feerate, and empty mempool.
413
+ self .restart_node (0 )
414
+
415
+ assert_equal (node .getrawmempool (), [])
416
+
417
+ def test_maxburn_submitpackage (self ):
418
+ node = self .nodes [0 ]
419
+
420
+ assert_equal (node .getrawmempool (), [])
421
+
376
422
self .log .info ("Submitpackage maxburnamount arg testing" )
377
- tx = tx_from_hex (chain_hex [1 ])
423
+ chained_txns_burn = self .wallet .create_self_transfer_chain (chain_length = 2 )
424
+ chained_burn_hex = [t ["hex" ] for t in chained_txns_burn ]
425
+
426
+ tx = tx_from_hex (chained_burn_hex [1 ])
378
427
tx .vout [- 1 ].scriptPubKey = b'a' * 10001 # scriptPubKey bigger than 10k IsUnspendable
379
- chain_hex = [chain_hex [0 ], tx .serialize ().hex ()]
428
+ chained_burn_hex = [chained_burn_hex [0 ], tx .serialize ().hex ()]
380
429
# burn test is run before any package evaluation; nothing makes it in and we get broader exception
381
- assert_raises_rpc_error (- 25 , "Unspendable output exceeds maximum configured by user" , node .submitpackage , chain_hex , 0 , chained_txns [1 ]["new_utxo" ]["value" ] - Decimal ("0.00000001" ))
430
+ assert_raises_rpc_error (- 25 , "Unspendable output exceeds maximum configured by user" , node .submitpackage , chained_burn_hex , 0 , chained_txns_burn [1 ]["new_utxo" ]["value" ] - Decimal ("0.00000001" ))
382
431
assert_equal (node .getrawmempool (), [])
383
432
433
+ minrate_btc_kvb_burn = min ([chained_txn_burn ["fee" ] / chained_txn_burn ["tx" ].get_vsize () * 1000 for chained_txn_burn in chained_txns_burn ])
434
+
384
435
# Relax the restrictions for both and send it; parent gets through as own subpackage
385
- pkg_result = node .submitpackage (chain_hex , maxfeerate = minrate_btc_kvb , maxburnamount = chained_txns [1 ]["new_utxo" ]["value" ])
386
- assert "error" not in pkg_result ["tx-results" ][chained_txns [0 ]["wtxid" ]]
436
+ pkg_result = node .submitpackage (chained_burn_hex , maxfeerate = minrate_btc_kvb_burn , maxburnamount = chained_txns_burn [1 ]["new_utxo" ]["value" ])
437
+ assert "error" not in pkg_result ["tx-results" ][chained_txns_burn [0 ]["wtxid" ]]
387
438
assert_equal (pkg_result ["tx-results" ][tx .getwtxid ()]["error" ], "scriptpubkey" )
388
- assert_equal (node .getrawmempool (), [chained_txns [0 ]["txid" ]])
439
+ assert_equal (node .getrawmempool (), [chained_txns_burn [0 ]["txid" ]])
389
440
390
441
if __name__ == "__main__" :
391
442
RPCPackagesTest ().main ()
0 commit comments