Can check m_wtxids_fee_calculations and m_effective_feerate.
Wrote up the changes for this + using CheckPackageMempoolAcceptResult:
index cd69fce2f5..b68686cfcb 100644
--- a/src/test/txpackage_tests.cpp
+++ b/src/test/txpackage_tests.cpp
@@ -975,28 +975,22 @@ BOOST_FIXTURE_TEST_CASE(package_rbf_tests, TestChain100Setup)
LOCK(m_node.mempool->cs);
const auto submit1 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, /*test_accept=*/false, std::nullopt);
- BOOST_CHECK_MESSAGE(submit1.m_state.IsValid(), "Package validation unexpectedly failed: " << submit1.m_state.GetRejectReason());
- auto it_parent_1 = submit1.m_tx_results.find(tx_parent->GetWitnessHash());
- auto it_child_1 = submit1.m_tx_results.find(tx_child_1->GetWitnessHash());
- BOOST_CHECK(it_parent_1 != submit1.m_tx_results.end());
- BOOST_CHECK(it_child_1 != submit1.m_tx_results.end());
- BOOST_CHECK_EQUAL(it_parent_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
- BOOST_CHECK_EQUAL(it_child_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
+ if (auto err_1{CheckPackageMempoolAcceptResult(package1, submit1, /*expect_valid=*/true, m_node.mempool.get())}) {
+ BOOST_ERROR(err_1.value());
+ }
expected_pool_size += 2;
- BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent->GetHash())));
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash())));
const auto submit2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package2, /*test_accept=*/false, std::nullopt);
+ if (auto err_2{CheckPackageMempoolAcceptResult(package2, submit2, /*expect_valid=*/true, m_node.mempool.get())}) {
+ BOOST_ERROR(err_2.value());
+ }
auto it_parent_2 = submit2.m_tx_results.find(tx_parent->GetWitnessHash());
auto it_child_2 = submit2.m_tx_results.find(tx_child_2->GetWitnessHash());
- BOOST_CHECK(it_parent_2 != submit2.m_tx_results.end());
- BOOST_CHECK(it_child_2 != submit2.m_tx_results.end());
- BOOST_CHECK_MESSAGE(submit2.m_state.IsValid(), "Package validation unexpectedly failed" << submit2.m_state.GetRejectReason());
BOOST_CHECK_EQUAL(it_parent_2->second.m_result_type, MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
BOOST_CHECK_EQUAL(it_child_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_2->GetHash())));
+
+ // child1 has been replaced
BOOST_CHECK(!m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash())));
}
@@ -1034,44 +1028,60 @@ BOOST_FIXTURE_TEST_CASE(package_rbf_tests, TestChain100Setup)
Package package3{tx_parent_3, tx_child_3};
const auto submit1 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, false, std::nullopt);
- BOOST_CHECK_MESSAGE(submit1.m_state.IsValid(), "Package validation unexpectedly failed" << submit1.m_state.GetRejectReason());
+ if (auto err_1{CheckPackageMempoolAcceptResult(package1, submit1, /*expect_valid=*/true, m_node.mempool.get())}) {
+ BOOST_ERROR(err_1.value());
+ }
auto it_parent_1 = submit1.m_tx_results.find(tx_parent_1->GetWitnessHash());
auto it_child_1 = submit1.m_tx_results.find(tx_child_1->GetWitnessHash());
- BOOST_CHECK(it_parent_1 != submit1.m_tx_results.end());
- BOOST_CHECK(it_child_1 != submit1.m_tx_results.end());
BOOST_CHECK_EQUAL(it_parent_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
BOOST_CHECK_EQUAL(it_child_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
+ BOOST_CHECK_EQUAL(it_parent_1->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent_1)), 200);
+ BOOST_CHECK_EQUAL(it_child_1->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child_1)), 200);
+ BOOST_CHECK(it_parent_1->second.m_replaced_transactions.empty());
+ BOOST_CHECK(it_child_1->second.m_replaced_transactions.empty());
expected_pool_size += 2;
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent_1->GetHash())));
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash())));
// This replacement is actually not package rbf; the parent carries enough fees
// to replace the entire package on its own.
const auto submit2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package2, false, std::nullopt);
- BOOST_CHECK_MESSAGE(submit2.m_state.IsValid(), "Package validation unexpectedly failed" << submit2.m_state.GetRejectReason());
+ if (auto err_2{CheckPackageMempoolAcceptResult(package2, submit2, /*expect_valid=*/true, m_node.mempool.get())}) {
+ BOOST_ERROR(err_2.value());
+ }
auto it_parent_2 = submit2.m_tx_results.find(tx_parent_2->GetWitnessHash());
auto it_child_2 = submit2.m_tx_results.find(tx_child_2->GetWitnessHash());
- BOOST_CHECK(it_parent_2 != submit2.m_tx_results.end());
- BOOST_CHECK(it_child_2 != submit2.m_tx_results.end());
BOOST_CHECK_EQUAL(it_parent_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
BOOST_CHECK_EQUAL(it_child_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
+ BOOST_CHECK_EQUAL(it_parent_2->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent_2)), 800);
+ BOOST_CHECK_EQUAL(it_child_2->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child_2)), 200);
+
+ // parent2 replaced both transactions
+ BOOST_CHECK(it_parent_2->second.m_replaced_transactions.size() == 2);
+ BOOST_CHECK(it_child_2->second.m_replaced_transactions.empty());
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent_2->GetHash())));
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_2->GetHash())));
// Package RBF, in which the replacement transaction's child sponsors the fees to meet RBF feerate rules
const auto submit3 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package3, false, std::nullopt);
- BOOST_CHECK_MESSAGE(submit3.m_state.IsValid(), "Package validation unexpectedly failed" << submit3.m_state.GetRejectReason());
+ if (auto err_3{CheckPackageMempoolAcceptResult(package3, submit3, /*expect_valid=*/true, m_node.mempool.get())}) {
+ BOOST_ERROR(err_3.value());
+ }
auto it_parent_3 = submit3.m_tx_results.find(tx_parent_3->GetWitnessHash());
auto it_child_3 = submit3.m_tx_results.find(tx_child_3->GetWitnessHash());
- BOOST_CHECK(it_parent_3 != submit3.m_tx_results.end());
- BOOST_CHECK(it_child_3 != submit3.m_tx_results.end());
BOOST_CHECK_EQUAL(it_parent_3->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
BOOST_CHECK_EQUAL(it_child_3->second.m_result_type, MempoolAcceptResult::ResultType::VALID);
+
+ // package3 was considered as a package to replace both package2 transactions
+ BOOST_CHECK(it_parent_3->second.m_replaced_transactions.size() == 2);
+ BOOST_CHECK(it_child_3->second.m_replaced_transactions.empty());
+
+ std::vector<Wtxid> expected_package3_wtxids({tx_parent_3->GetWitnessHash(), tx_child_3->GetWitnessHash()});
+ const auto package3_total_vsize{GetVirtualTransactionSize(*tx_parent_3) + GetVirtualTransactionSize(*tx_child_3)};
+ BOOST_CHECK(it_parent_3->second.m_wtxids_fee_calculations.value() == expected_package3_wtxids);
+ BOOST_CHECK(it_child_3->second.m_wtxids_fee_calculations.value() == expected_package3_wtxids);
+ BOOST_CHECK_EQUAL(it_parent_3->second.m_effective_feerate.value().GetFee(package3_total_vsize), 1499);
+ BOOST_CHECK_EQUAL(it_child_3->second.m_effective_feerate.value().GetFee(package3_total_vsize), 1499);
+
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent_3->GetHash())));
- BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child_3->GetHash())));
}
}