0index cd69fce2f5..b68686cfcb 100644
1--- a/src/test/txpackage_tests.cpp
2+++ b/src/test/txpackage_tests.cpp
3@@ -975,28 +975,22 @@ BOOST_FIXTURE_TEST_CASE(package_rbf_tests, TestChain100Setup)
4
5 LOCK(m_node.mempool->cs);
6 const auto submit1 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, /*test_accept=*/false, std::nullopt);
7- BOOST_CHECK_MESSAGE(submit1.m_state.IsValid(), "Package validation unexpectedly failed: " << submit1.m_state.GetRejectReason());
8- auto it_parent_1 = submit1.m_tx_results.find(tx_parent->GetWitnessHash());
9- auto it_child_1 = submit1.m_tx_results.find(tx_child_1->GetWitnessHash());
10- BOOST_CHECK(it_parent_1 != submit1.m_tx_results.end());
11- BOOST_CHECK(it_child_1 != submit1.m_tx_results.end());
12- BOOST_CHECK_EQUAL(it_parent_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
13- BOOST_CHECK_EQUAL(it_child_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
14+ if (auto err_1{CheckPackageMempoolAcceptResult(package1, submit1, /*expect_valid=*/true, m_node.mempool.get())}) {
15+ BOOST_ERROR(err_1.value());
16+ }
17 expected_pool_size += 2;
18- BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
19- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent->GetHash())));
20- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash())));
21
22 const auto submit2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package2, /*test_accept=*/false, std::nullopt);
23+ if (auto err_2{CheckPackageMempoolAcceptResult(package2, submit2, /*expect_valid=*/true, m_node.mempool.get())}) {
24+ BOOST_ERROR(err_2.value());
25+ }
26 auto it_parent_2 = submit2.m_tx_results.find(tx_parent->GetWitnessHash());
27 auto it_child_2 = submit2.m_tx_results.find(tx_child_2->GetWitnessHash());
28- BOOST_CHECK(it_parent_2 != submit2.m_tx_results.end());
29- BOOST_CHECK(it_child_2 != submit2.m_tx_results.end());
30- BOOST_CHECK_MESSAGE(submit2.m_state.IsValid(), "Package validation unexpectedly failed" << submit2.m_state.GetRejectReason());
31 BOOST_CHECK_EQUAL(it_parent_2->second.m_result_type, MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
32 BOOST_CHECK_EQUAL(it_child_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
33 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
34- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_2->GetHash())));
35+
36+ // child1 has been replaced
37 BOOST_CHECK(!m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash())));
38 }
39
40@@ -1034,44 +1028,60 @@ BOOST_FIXTURE_TEST_CASE(package_rbf_tests, TestChain100Setup)
41 Package package3{tx_parent_3, tx_child_3};
42
43 const auto submit1 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, false, std::nullopt);
44- BOOST_CHECK_MESSAGE(submit1.m_state.IsValid(), "Package validation unexpectedly failed" << submit1.m_state.GetRejectReason());
45+ if (auto err_1{CheckPackageMempoolAcceptResult(package1, submit1, /*expect_valid=*/true, m_node.mempool.get())}) {
46+ BOOST_ERROR(err_1.value());
47+ }
48 auto it_parent_1 = submit1.m_tx_results.find(tx_parent_1->GetWitnessHash());
49 auto it_child_1 = submit1.m_tx_results.find(tx_child_1->GetWitnessHash());
50- BOOST_CHECK(it_parent_1 != submit1.m_tx_results.end());
51- BOOST_CHECK(it_child_1 != submit1.m_tx_results.end());
52 BOOST_CHECK_EQUAL(it_parent_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
53 BOOST_CHECK_EQUAL(it_child_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
54+ BOOST_CHECK_EQUAL(it_parent_1->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent_1)), 200);
55+ BOOST_CHECK_EQUAL(it_child_1->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child_1)), 200);
56+ BOOST_CHECK(it_parent_1->second.m_replaced_transactions.empty());
57+ BOOST_CHECK(it_child_1->second.m_replaced_transactions.empty());
58 expected_pool_size += 2;
59 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
60- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent_1->GetHash())));
61- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash())));
62
63 // This replacement is actually not package rbf; the parent carries enough fees
64 // to replace the entire package on its own.
65 const auto submit2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package2, false, std::nullopt);
66- BOOST_CHECK_MESSAGE(submit2.m_state.IsValid(), "Package validation unexpectedly failed" << submit2.m_state.GetRejectReason());
67+ if (auto err_2{CheckPackageMempoolAcceptResult(package2, submit2, /*expect_valid=*/true, m_node.mempool.get())}) {
68+ BOOST_ERROR(err_2.value());
69+ }
70 auto it_parent_2 = submit2.m_tx_results.find(tx_parent_2->GetWitnessHash());
71 auto it_child_2 = submit2.m_tx_results.find(tx_child_2->GetWitnessHash());
72- BOOST_CHECK(it_parent_2 != submit2.m_tx_results.end());
73- BOOST_CHECK(it_child_2 != submit2.m_tx_results.end());
74 BOOST_CHECK_EQUAL(it_parent_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
75 BOOST_CHECK_EQUAL(it_child_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
76+ BOOST_CHECK_EQUAL(it_parent_2->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent_2)), 800);
77+ BOOST_CHECK_EQUAL(it_child_2->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child_2)), 200);
78+
79+ // parent2 replaced both transactions
80+ BOOST_CHECK(it_parent_2->second.m_replaced_transactions.size() == 2);
81+ BOOST_CHECK(it_child_2->second.m_replaced_transactions.empty());
82 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
83- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent_2->GetHash())));
84- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_2->GetHash())));
85
86 // Package RBF, in which the replacement transaction's child sponsors the fees to meet RBF feerate rules
87 const auto submit3 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package3, false, std::nullopt);
88- BOOST_CHECK_MESSAGE(submit3.m_state.IsValid(), "Package validation unexpectedly failed" << submit3.m_state.GetRejectReason());
89+ if (auto err_3{CheckPackageMempoolAcceptResult(package3, submit3, /*expect_valid=*/true, m_node.mempool.get())}) {
90+ BOOST_ERROR(err_3.value());
91+ }
92 auto it_parent_3 = submit3.m_tx_results.find(tx_parent_3->GetWitnessHash());
93 auto it_child_3 = submit3.m_tx_results.find(tx_child_3->GetWitnessHash());
94- BOOST_CHECK(it_parent_3 != submit3.m_tx_results.end());
95- BOOST_CHECK(it_child_3 != submit3.m_tx_results.end());
96 BOOST_CHECK_EQUAL(it_parent_3->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
97 BOOST_CHECK_EQUAL(it_child_3->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
98+
99+ // package3 was considered as a package to replace both package2 transactions
100+ BOOST_CHECK(it_parent_3->second.m_replaced_transactions.size() == 2);
101+ BOOST_CHECK(it_child_3->second.m_replaced_transactions.empty());
102+
103+ std::vector<Wtxid> expected_package3_wtxids({tx_parent_3->GetWitnessHash(), tx_child_3->GetWitnessHash()});
104+ const auto package3_total_vsize{GetVirtualTransactionSize(*tx_parent_3) + GetVirtualTransactionSize(*tx_child_3)};
105+ BOOST_CHECK(it_parent_3->second.m_wtxids_fee_calculations.value() == expected_package3_wtxids);
106+ BOOST_CHECK(it_child_3->second.m_wtxids_fee_calculations.value() == expected_package3_wtxids);
107+ BOOST_CHECK_EQUAL(it_parent_3->second.m_effective_feerate.value().GetFee(package3_total_vsize), 1499);
108+ BOOST_CHECK_EQUAL(it_child_3->second.m_effective_feerate.value().GetFee(package3_total_vsize), 1499);
109+
110 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
111- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent_3->GetHash())));
112- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_3->GetHash())));
113 }
114
115 }