16
16
#include < boost/test/unit_test.hpp>
17
17
18
18
BOOST_AUTO_TEST_SUITE (txpackage_tests)
19
+ // A fee amount that is above 1sat/vB but below 5sat/vB for most transactions created within these
20
+ // unit tests.
21
+ static const CAmount low_fee_amt{200 };
19
22
20
23
// Create placeholder transactions that have no meaning.
21
24
inline CTransactionRef create_placeholder_tx (size_t num_inputs, size_t num_outputs)
@@ -373,6 +376,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
373
376
{
374
377
// Mine blocks to mature coinbases.
375
378
mineBlocks (5 );
379
+ MockMempoolMinFee (CFeeRate (5000 ));
376
380
LOCK (cs_main);
377
381
378
382
// Transactions with a same-txid-different-witness transaction in the mempool should be ignored,
@@ -560,13 +564,15 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
560
564
BOOST_CHECK (parent2_v2_result.m_result_type == MempoolAcceptResult::ResultType::VALID);
561
565
package_mixed.push_back (ptx_parent2_v1);
562
566
563
- // parent3 will be a new transaction. Put 0 fees on it to make it invalid on its own.
567
+ // parent3 will be a new transaction. Put a low feerate to make it invalid on its own.
564
568
auto mtx_parent3 = CreateValidMempoolTransaction (/* input_transaction=*/ m_coinbase_txns[3 ], /* input_vout=*/ 0 ,
565
569
/* input_height=*/ 0 , /* input_signing_key=*/ coinbaseKey,
566
570
/* output_destination=*/ acs_spk,
567
- /* output_amount=*/ CAmount (50 * COIN), /* submit=*/ false );
571
+ /* output_amount=*/ CAmount (50 * COIN - low_fee_amt ), /* submit=*/ false );
568
572
CTransactionRef ptx_parent3 = MakeTransactionRef (mtx_parent3);
569
573
package_mixed.push_back (ptx_parent3);
574
+ BOOST_CHECK (m_node.mempool ->GetMinFee ().GetFee (GetVirtualTransactionSize (*ptx_parent3)) > low_fee_amt);
575
+ BOOST_CHECK (m_node.mempool ->m_min_relay_feerate .GetFee (GetVirtualTransactionSize (*ptx_parent3)) <= low_fee_amt);
570
576
571
577
// child spends parent1, parent2, and parent3
572
578
CKey mixed_grandchild_key;
@@ -627,6 +633,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
627
633
BOOST_FIXTURE_TEST_CASE (package_cpfp_tests, TestChain100Setup)
628
634
{
629
635
mineBlocks (5 );
636
+ MockMempoolMinFee (CFeeRate (5000 ));
630
637
LOCK (::cs_main);
631
638
size_t expected_pool_size = m_node.mempool ->size ();
632
639
CKey child_key;
@@ -636,9 +643,9 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
636
643
grandchild_key.MakeNewKey (true );
637
644
CScript child_spk = GetScriptForDestination (WitnessV0KeyHash (grandchild_key.GetPubKey ()));
638
645
639
- // zero -fee parent and high-fee child package
646
+ // low -fee parent and high-fee child package
640
647
const CAmount coinbase_value{50 * COIN};
641
- const CAmount parent_value{coinbase_value - 0 };
648
+ const CAmount parent_value{coinbase_value - low_fee_amt };
642
649
const CAmount child_value{parent_value - COIN};
643
650
644
651
Package package_cpfp;
@@ -657,9 +664,9 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
657
664
package_cpfp.push_back (tx_child);
658
665
659
666
// Package feerate is calculated using modified fees, and prioritisetransaction accepts negative
660
- // fee deltas. This should be taken into account. De-prioritise the parent transaction by -1BTC,
661
- // bringing the package feerate to 0.
662
- m_node.mempool ->PrioritiseTransaction (tx_parent->GetHash (), - 1 * COIN );
667
+ // fee deltas. This should be taken into account. De-prioritise the parent transaction
668
+ // to bring the package feerate to 0.
669
+ m_node.mempool ->PrioritiseTransaction (tx_parent->GetHash (), child_value - coinbase_value );
663
670
{
664
671
BOOST_CHECK_EQUAL (m_node.mempool ->size (), expected_pool_size);
665
672
const auto submit_cpfp_deprio = ProcessNewPackage (m_node.chainman ->ActiveChainstate (), *m_node.mempool ,
@@ -675,8 +682,8 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
675
682
// Clear the prioritisation of the parent transaction.
676
683
WITH_LOCK (m_node.mempool ->cs , m_node.mempool ->ClearPrioritisation (tx_parent->GetHash ()));
677
684
678
- // Package CPFP: Even though the parent pays 0 absolute fees, the child pays 1 BTC which is
679
- // enough for the package feerate to meet the threshold.
685
+ // Package CPFP: Even though the parent's feerate is below the mempool minimum feerate, the
686
+ // child pays enough for the package feerate to meet the threshold.
680
687
{
681
688
BOOST_CHECK_EQUAL (m_node.mempool ->size (), expected_pool_size);
682
689
const auto submit_cpfp = ProcessNewPackage (m_node.chainman ->ActiveChainstate (), *m_node.mempool ,
@@ -689,7 +696,7 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
689
696
auto it_child = submit_cpfp.m_tx_results .find (tx_child->GetWitnessHash ());
690
697
BOOST_CHECK (it_parent != submit_cpfp.m_tx_results .end ());
691
698
BOOST_CHECK (it_parent->second .m_result_type == MempoolAcceptResult::ResultType::VALID);
692
- BOOST_CHECK (it_parent->second .m_base_fees .value () == 0 );
699
+ BOOST_CHECK (it_parent->second .m_base_fees .value () == coinbase_value - parent_value );
693
700
BOOST_CHECK (it_child != submit_cpfp.m_tx_results .end ());
694
701
BOOST_CHECK (it_child->second .m_result_type == MempoolAcceptResult::ResultType::VALID);
695
702
BOOST_CHECK (it_child->second .m_base_fees .value () == COIN);
@@ -709,22 +716,28 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
709
716
}
710
717
711
718
// Just because we allow low-fee parents doesn't mean we allow low-feerate packages.
712
- // This package just pays 200 satoshis total. This would be enough to pay for the child alone,
713
- // but isn't enough for the entire package to meet the 1sat/vbyte minimum .
719
+ // The mempool minimum feerate is 5sat/vB, but this package just pays 800 satoshis total.
720
+ // The child fees would be able to pay for itself, but isn't enough for the entire package.
714
721
Package package_still_too_low;
722
+ const CAmount parent_fee{200 };
723
+ const CAmount child_fee{600 };
715
724
auto mtx_parent_cheap = CreateValidMempoolTransaction (/* input_transaction=*/ m_coinbase_txns[1 ], /* input_vout=*/ 0 ,
716
725
/* input_height=*/ 0 , /* input_signing_key=*/ coinbaseKey,
717
726
/* output_destination=*/ parent_spk,
718
- /* output_amount=*/ coinbase_value, /* submit=*/ false );
727
+ /* output_amount=*/ coinbase_value - parent_fee , /* submit=*/ false );
719
728
CTransactionRef tx_parent_cheap = MakeTransactionRef (mtx_parent_cheap);
720
729
package_still_too_low.push_back (tx_parent_cheap);
730
+ BOOST_CHECK (m_node.mempool ->GetMinFee ().GetFee (GetVirtualTransactionSize (*tx_parent_cheap)) > parent_fee);
731
+ BOOST_CHECK (m_node.mempool ->m_min_relay_feerate .GetFee (GetVirtualTransactionSize (*tx_parent_cheap)) <= parent_fee);
721
732
722
733
auto mtx_child_cheap = CreateValidMempoolTransaction (/* input_transaction=*/ tx_parent_cheap, /* input_vout=*/ 0 ,
723
734
/* input_height=*/ 101 , /* input_signing_key=*/ child_key,
724
735
/* output_destination=*/ child_spk,
725
- /* output_amount=*/ coinbase_value - 200 , /* submit=*/ false );
736
+ /* output_amount=*/ coinbase_value - parent_fee - child_fee , /* submit=*/ false );
726
737
CTransactionRef tx_child_cheap = MakeTransactionRef (mtx_child_cheap);
727
738
package_still_too_low.push_back (tx_child_cheap);
739
+ BOOST_CHECK (m_node.mempool ->GetMinFee ().GetFee (GetVirtualTransactionSize (*tx_child_cheap)) <= child_fee);
740
+ BOOST_CHECK (m_node.mempool ->GetMinFee ().GetFee (GetVirtualTransactionSize (*tx_parent_cheap) + GetVirtualTransactionSize (*tx_child_cheap)) > parent_fee + child_fee);
728
741
729
742
// Cheap package should fail with package-fee-too-low.
730
743
{
@@ -735,11 +748,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
735
748
BOOST_CHECK_EQUAL (submit_package_too_low.m_state .GetResult (), PackageValidationResult::PCKG_POLICY);
736
749
BOOST_CHECK_EQUAL (submit_package_too_low.m_state .GetRejectReason (), " package-fee-too-low" );
737
750
BOOST_CHECK_EQUAL (m_node.mempool ->size (), expected_pool_size);
738
- const CFeeRate child_feerate (200 , GetVirtualTransactionSize (*tx_child_cheap));
739
- BOOST_CHECK (child_feerate.GetFeePerK () > 1000 );
740
- const CFeeRate expected_feerate (200 ,
741
- GetVirtualTransactionSize (*tx_parent_cheap) + GetVirtualTransactionSize (*tx_child_cheap));
742
- BOOST_CHECK (expected_feerate.GetFeePerK () < 1000 );
743
751
}
744
752
745
753
// Package feerate includes the modified fees of the transactions.
@@ -752,18 +760,18 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
752
760
expected_pool_size += 2 ;
753
761
BOOST_CHECK_MESSAGE (submit_prioritised_package.m_state .IsValid (),
754
762
" Package validation unexpectedly failed" << submit_prioritised_package.m_state .GetRejectReason ());
755
- const CFeeRate expected_feerate (1 * COIN + 200 ,
763
+ const CFeeRate expected_feerate (1 * COIN + parent_fee + child_fee ,
756
764
GetVirtualTransactionSize (*tx_parent_cheap) + GetVirtualTransactionSize (*tx_child_cheap));
757
765
BOOST_CHECK_EQUAL (submit_prioritised_package.m_tx_results .size (), package_still_too_low.size ());
758
766
auto it_parent = submit_prioritised_package.m_tx_results .find (tx_parent_cheap->GetWitnessHash ());
759
767
auto it_child = submit_prioritised_package.m_tx_results .find (tx_child_cheap->GetWitnessHash ());
760
768
BOOST_CHECK (it_parent != submit_prioritised_package.m_tx_results .end ());
761
769
BOOST_CHECK (it_parent->second .m_result_type == MempoolAcceptResult::ResultType::VALID);
762
- BOOST_CHECK (it_parent->second .m_base_fees .value () == 0 );
770
+ BOOST_CHECK (it_parent->second .m_base_fees .value () == parent_fee );
763
771
BOOST_CHECK (it_parent->second .m_effective_feerate .value () == expected_feerate);
764
772
BOOST_CHECK (it_child != submit_prioritised_package.m_tx_results .end ());
765
773
BOOST_CHECK (it_child->second .m_result_type == MempoolAcceptResult::ResultType::VALID);
766
- BOOST_CHECK (it_child->second .m_base_fees .value () == 200 );
774
+ BOOST_CHECK (it_child->second .m_base_fees .value () == child_fee );
767
775
BOOST_CHECK (it_child->second .m_effective_feerate .value () == expected_feerate);
768
776
std::vector<uint256> expected_wtxids ({tx_parent_cheap->GetWitnessHash (), tx_child_cheap->GetWitnessHash ()});
769
777
BOOST_CHECK (it_parent->second .m_wtxids_fee_calculations .value () == expected_wtxids);
0 commit comments