Skip to content

Commit 5eab397

Browse files
committed
[validation] remove PackageMempoolAcceptResult::m_package_feerate
This value creates an extremely confusing interface as its existence is dependent upon implementation details (whether something was submitted on its own, etc). MempoolAcceptResult::m_effective_feerate is much more helpful, as it always exists for submitted transactions.
1 parent 601bac8 commit 5eab397

File tree

5 files changed

+7
-75
lines changed

5 files changed

+7
-75
lines changed

src/rpc/mempool.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,6 @@ static RPCHelpMan submitpackage()
785785
}},
786786
}}
787787
}},
788-
{RPCResult::Type::STR_AMOUNT, "package-feerate", /*optional=*/true, "package feerate used for feerate checks in " + CURRENCY_UNIT + " per KvB. Excludes transactions which were deduplicated or accepted individually."},
789788
{RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",
790789
{
791790
{RPCResult::Type::STR_HEX, "", "The transaction id"},
@@ -900,9 +899,6 @@ static RPCHelpMan submitpackage()
900899
tx_result_map.pushKV(tx->GetWitnessHash().GetHex(), result_inner);
901900
}
902901
rpc_result.pushKV("tx-results", tx_result_map);
903-
if (package_result.m_package_feerate.has_value()) {
904-
rpc_result.pushKV("package-feerate", ValueFromAmount(package_result.m_package_feerate.value().GetFeePerK()));
905-
}
906902
UniValue replaced_list(UniValue::VARR);
907903
for (const uint256& hash : replaced_txids) replaced_list.push_back(hash.ToString());
908904
rpc_result.pushKV("replaced-transactions", replaced_list);

src/test/txpackage_tests.cpp

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
101101
BOOST_CHECK(it_child != result_parent_child.m_tx_results.end());
102102
BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(),
103103
"Package validation unexpectedly failed: " << it_child->second.m_state.GetRejectReason());
104-
BOOST_CHECK(result_parent_child.m_package_feerate.has_value());
105-
BOOST_CHECK(result_parent_child.m_package_feerate.value() ==
106-
CFeeRate(2 * COIN, GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child)));
107104
BOOST_CHECK(it_child->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child)) == COIN);
108105
BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1);
109106
BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash());
@@ -118,7 +115,6 @@ BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
118115
auto it_giant_tx = result_single_large.m_tx_results.find(giant_ptx->GetWitnessHash());
119116
BOOST_CHECK(it_giant_tx != result_single_large.m_tx_results.end());
120117
BOOST_CHECK_EQUAL(it_giant_tx->second.m_state.GetRejectReason(), "tx-size");
121-
BOOST_CHECK(result_single_large.m_package_feerate == std::nullopt);
122118

123119
// Check that mempool size hasn't changed.
124120
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
@@ -239,7 +235,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
239235
BOOST_CHECK_EQUAL(result_unrelated_submit.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
240236
BOOST_CHECK_EQUAL(result_unrelated_submit.m_state.GetRejectReason(), "package-not-child-with-parents");
241237
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
242-
BOOST_CHECK(result_unrelated_submit.m_package_feerate == std::nullopt);
243238

244239
// Parent and Child (and Grandchild) Package
245240
Package package_parent_child;
@@ -281,7 +276,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
281276
BOOST_CHECK_EQUAL(result_3gen_submit.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
282277
BOOST_CHECK_EQUAL(result_3gen_submit.m_state.GetRejectReason(), "package-not-child-with-parents");
283278
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
284-
BOOST_CHECK(result_3gen_submit.m_package_feerate == std::nullopt);
285279
}
286280

287281
// Parent and child package where transactions are invalid for reasons other than fee and
@@ -314,8 +308,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
314308
BOOST_CHECK_EQUAL(result_missing_parent.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
315309
BOOST_CHECK_EQUAL(result_missing_parent.m_state.GetRejectReason(), "package-not-child-with-unconfirmed-parents");
316310
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
317-
318-
BOOST_CHECK(result_missing_parent.m_package_feerate == std::nullopt);
319311
}
320312

321313
// Submit package with parent + child.
@@ -341,10 +333,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
341333
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
342334
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent->GetHash())));
343335
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child->GetHash())));
344-
345-
// Since both transactions have high feerates, they each passed validation individually.
346-
// Package validation was unnecessary, so there is no package feerate.
347-
BOOST_CHECK(submit_parent_child.m_package_feerate == std::nullopt);
348336
}
349337

350338
// Already-in-mempool transactions should be detected and de-duplicated.
@@ -365,8 +353,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
365353
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
366354
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent->GetHash())));
367355
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child->GetHash())));
368-
369-
BOOST_CHECK(submit_deduped.m_package_feerate == std::nullopt);
370356
}
371357
}
372358

@@ -442,11 +428,8 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
442428
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(ptx_child1->GetHash())));
443429

444430
// Child2 would have been validated individually.
445-
BOOST_CHECK(submit_witness1.m_package_feerate == std::nullopt);
446-
447431
const auto submit_witness2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool,
448432
{ptx_parent, ptx_child2}, /*test_accept=*/false);
449-
BOOST_CHECK(submit_witness2.m_package_feerate == std::nullopt);
450433
BOOST_CHECK_MESSAGE(submit_witness2.m_state.IsValid(),
451434
"Package validation unexpectedly failed: " << submit_witness2.m_state.GetRejectReason());
452435
auto it_parent2_deduped = submit_witness2.m_tx_results.find(ptx_parent->GetWitnessHash());
@@ -470,7 +453,6 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
470453
auto it_child_dup = submit_segwit_dedup.m_tx_results.find(ptx_child1->GetWitnessHash());
471454
BOOST_CHECK(it_parent_dup->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
472455
BOOST_CHECK(it_child_dup->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
473-
BOOST_CHECK(submit_witness2.m_package_feerate == std::nullopt);
474456
}
475457

476458
// Try submitting Package1{child2, grandchild} where child2 is same-txid-different-witness as
@@ -505,9 +487,6 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
505487
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(ptx_child2->GetHash())));
506488
BOOST_CHECK(!m_node.mempool->exists(GenTxid::Wtxid(ptx_child2->GetWitnessHash())));
507489
BOOST_CHECK(m_node.mempool->exists(GenTxid::Wtxid(ptx_grandchild->GetWitnessHash())));
508-
509-
// Since child2 is ignored, grandchild would be validated individually.
510-
BOOST_CHECK(submit_spend_ignored.m_package_feerate == std::nullopt);
511490
}
512491

513492
// A package Package{parent1, parent2, parent3, child} where the parents are a mixture of
@@ -620,11 +599,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
620599
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(ptx_mixed_child->GetHash())));
621600

622601
// package feerate should include parent3 and child. It should not include parent1 or parent2_v1.
623-
BOOST_CHECK(mixed_result.m_package_feerate.has_value());
624602
const CFeeRate expected_feerate(1 * COIN, GetVirtualTransactionSize(*ptx_parent3) + GetVirtualTransactionSize(*ptx_mixed_child));
625-
BOOST_CHECK_MESSAGE(mixed_result.m_package_feerate.value() == expected_feerate,
626-
strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
627-
mixed_result.m_package_feerate.value().ToString()));
628603
BOOST_CHECK(it_parent3->second.m_effective_feerate.value() == expected_feerate);
629604
BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate);
630605
std::vector<uint256> expected_wtxids({ptx_parent3->GetWitnessHash(), ptx_mixed_child->GetWitnessHash()});
@@ -678,11 +653,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
678653
BOOST_CHECK(submit_cpfp_deprio.m_tx_results.empty());
679654
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
680655
const CFeeRate expected_feerate(0, GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child));
681-
BOOST_CHECK(submit_cpfp_deprio.m_package_feerate.has_value());
682-
BOOST_CHECK(submit_cpfp_deprio.m_package_feerate.value() == CFeeRate{0});
683-
BOOST_CHECK_MESSAGE(submit_cpfp_deprio.m_package_feerate.value() == expected_feerate,
684-
strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
685-
submit_cpfp_deprio.m_package_feerate.value().ToString()));
686656
}
687657

688658
// Clear the prioritisation of the parent transaction.
@@ -718,10 +688,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
718688
BOOST_CHECK(it_parent->second.m_wtxids_fee_calculations.value() == expected_wtxids);
719689
BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids);
720690
BOOST_CHECK(expected_feerate.GetFeePerK() > 1000);
721-
BOOST_CHECK(submit_cpfp.m_package_feerate.has_value());
722-
BOOST_CHECK_MESSAGE(submit_cpfp.m_package_feerate.value() == expected_feerate,
723-
strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
724-
submit_cpfp.m_package_feerate.value().ToString()));
725691
}
726692

727693
// Just because we allow low-fee parents doesn't mean we allow low-feerate packages.
@@ -756,10 +722,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
756722
const CFeeRate expected_feerate(200,
757723
GetVirtualTransactionSize(*tx_parent_cheap) + GetVirtualTransactionSize(*tx_child_cheap));
758724
BOOST_CHECK(expected_feerate.GetFeePerK() < 1000);
759-
BOOST_CHECK(submit_package_too_low.m_package_feerate.has_value());
760-
BOOST_CHECK_MESSAGE(submit_package_too_low.m_package_feerate.value() == expected_feerate,
761-
strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
762-
submit_package_too_low.m_package_feerate.value().ToString()));
763725
}
764726

765727
// Package feerate includes the modified fees of the transactions.
@@ -774,10 +736,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
774736
"Package validation unexpectedly failed" << submit_prioritised_package.m_state.GetRejectReason());
775737
const CFeeRate expected_feerate(1 * COIN + 200,
776738
GetVirtualTransactionSize(*tx_parent_cheap) + GetVirtualTransactionSize(*tx_child_cheap));
777-
BOOST_CHECK(submit_prioritised_package.m_package_feerate.has_value());
778-
BOOST_CHECK_MESSAGE(submit_prioritised_package.m_package_feerate.value() == expected_feerate,
779-
strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
780-
submit_prioritised_package.m_package_feerate.value().ToString()));
781739
auto it_parent = submit_prioritised_package.m_tx_results.find(tx_parent_cheap->GetWitnessHash());
782740
auto it_child = submit_prioritised_package.m_tx_results.find(tx_child_cheap->GetWitnessHash());
783741
BOOST_CHECK(it_parent != submit_prioritised_package.m_tx_results.end());
@@ -823,10 +781,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
823781
BOOST_CHECK_MESSAGE(submit_rich_parent.m_state.IsInvalid(), "Package validation unexpectedly succeeded");
824782

825783
// The child would have been validated on its own and failed, then submitted as a "package" of 1.
826-
// The package feerate is just the child's feerate, which is 0sat/vb.
827-
BOOST_CHECK(submit_rich_parent.m_package_feerate.has_value());
828-
BOOST_CHECK_MESSAGE(submit_rich_parent.m_package_feerate.value() == CFeeRate(),
829-
"expected 0, got " << submit_rich_parent.m_package_feerate.value().ToString());
830784
BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
831785
BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetRejectReason(), "package-fee-too-low");
832786

src/validation.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,15 +1251,15 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
12511251
if (args.m_package_feerates &&
12521252
!CheckFeeRate(m_total_vsize, m_total_modified_fees, placeholder_state)) {
12531253
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-fee-too-low");
1254-
return PackageMempoolAcceptResult(package_state, package_feerate, {});
1254+
return PackageMempoolAcceptResult(package_state, {});
12551255
}
12561256

12571257
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
12581258
// because it's unnecessary. Also, CPFP carve out can increase the limit for individual
12591259
// transactions, but this exemption is not extended to packages in CheckPackageLimits().
12601260
std::string err_string;
12611261
if (txns.size() > 1 && !PackageMempoolChecks(txns, package_state)) {
1262-
return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
1262+
return PackageMempoolAcceptResult(package_state, std::move(results));
12631263
}
12641264

12651265
std::vector<uint256> all_package_wtxids;
@@ -1272,7 +1272,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
12721272
// Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.
12731273
package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
12741274
results.emplace(ws.m_ptx->GetWitnessHash(), MempoolAcceptResult::Failure(ws.m_state));
1275-
return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
1275+
return PackageMempoolAcceptResult(package_state, std::move(results));
12761276
}
12771277
if (args.m_test_accept) {
12781278
const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :
@@ -1286,14 +1286,14 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
12861286
}
12871287
}
12881288

1289-
if (args.m_test_accept) return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
1289+
if (args.m_test_accept) return PackageMempoolAcceptResult(package_state, std::move(results));
12901290

12911291
if (!SubmitPackage(args, workspaces, package_state, results)) {
12921292
// PackageValidationState filled in by SubmitPackage().
1293-
return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
1293+
return PackageMempoolAcceptResult(package_state, std::move(results));
12941294
}
12951295

1296-
return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
1296+
return PackageMempoolAcceptResult(package_state, std::move(results));
12971297
}
12981298

12991299
PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package, ATMPArgs& args)
@@ -1418,7 +1418,6 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
14181418

14191419
// Nothing to do if the entire package has already been submitted.
14201420
if (quit_early || txns_new.empty()) {
1421-
// No package feerate when no package validation was done.
14221421
return PackageMempoolAcceptResult(package_state_quit_early, std::move(results));
14231422
}
14241423
// Validate the (deduplicated) transactions as a package.
@@ -1427,7 +1426,6 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
14271426
for (const auto& [wtxid, mempoolaccept_res] : results) {
14281427
submission_result.m_tx_results.emplace(wtxid, mempoolaccept_res);
14291428
}
1430-
if (submission_result.m_state.IsValid()) assert(submission_result.m_package_feerate.has_value());
14311429
return submission_result;
14321430
}
14331431

src/validation.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,14 @@ struct PackageMempoolAcceptResult
216216
* was a package-wide error (see result in m_state), m_tx_results will be empty.
217217
*/
218218
std::map<const uint256, const MempoolAcceptResult> m_tx_results;
219-
/** Package feerate, defined as the aggregated modified fees divided by the total virtual size
220-
* of all transactions in the package. May be unavailable if some inputs were not available or
221-
* a transaction failure caused validation to terminate early. */
222-
std::optional<CFeeRate> m_package_feerate;
223219

224220
explicit PackageMempoolAcceptResult(PackageValidationState state,
225221
std::map<const uint256, const MempoolAcceptResult>&& results)
226222
: m_state{state}, m_tx_results(std::move(results)) {}
227223

228224
explicit PackageMempoolAcceptResult(PackageValidationState state, CFeeRate feerate,
229225
std::map<const uint256, const MempoolAcceptResult>&& results)
230-
: m_state{state}, m_tx_results(std::move(results)), m_package_feerate{feerate} {}
226+
: m_state{state}, m_tx_results(std::move(results)) {}
231227

232228
/** Constructor to create a PackageMempoolAcceptResult from a single MempoolAcceptResult */
233229
explicit PackageMempoolAcceptResult(const uint256& wtxid, const MempoolAcceptResult& result)

test/functional/rpc_packages.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,6 @@ def test_submit_child_with_parents(self, num_parents, partial_submit):
321321
# submitpackage result should be consistent with testmempoolaccept and getmempoolentry
322322
self.assert_equal_package_results(node, testmempoolaccept_result, submitpackage_result)
323323

324-
# Package feerate is calculated for the remaining transactions after deduplication and
325-
# individual submission. If only 0 or 1 transaction is left, e.g. because all transactions
326-
# had high-feerates or were already in the mempool, no package feerate is provided.
327-
# In this case, since all of the parents have high fees, each is accepted individually.
328-
assert "package-feerate" not in submitpackage_result
329-
330324
# The node should announce each transaction. No guarantees for propagation.
331325
peer.wait_for_broadcast([tx["tx"].getwtxid() for tx in package_txns])
332326
self.generate(node, 1)
@@ -363,12 +357,6 @@ def test_submit_cpfp(self):
363357
assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], poor_parent_result["fees"]["effective-includes"])
364358
assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], child_result["fees"]["effective-includes"])
365359

366-
# Package feerate is calculated for the remaining transactions after deduplication and
367-
# individual submission. Since this package had a 0-fee parent, package feerate must have
368-
# been used and returned.
369-
assert "package-feerate" in submitpackage_result
370-
assert_fee_amount(DEFAULT_FEE, rich_parent_result["vsize"] + child_result["vsize"], submitpackage_result["package-feerate"])
371-
372360
# The node will broadcast each transaction, still abiding by its peer's fee filter
373361
peer.wait_for_broadcast([tx["tx"].getwtxid() for tx in package_txns])
374362
self.generate(node, 1)

0 commit comments

Comments
 (0)