@@ -460,6 +460,10 @@ class MemPoolAccept
460
460
* partially submitted.
461
461
*/
462
462
const bool m_package_submission;
463
+ /* * When true, use package feerates instead of individual transaction feerates for fee-based
464
+ * policies such as mempool min fee and min relay fee.
465
+ */
466
+ const bool m_package_feerates;
463
467
464
468
/* * Parameters for single transaction mempool validation. */
465
469
static ATMPArgs SingleAccept (const CChainParams& chainparams, int64_t accept_time,
@@ -472,6 +476,7 @@ class MemPoolAccept
472
476
/* m_test_accept */ test_accept,
473
477
/* m_allow_bip125_replacement */ true ,
474
478
/* m_package_submission */ false ,
479
+ /* m_package_feerates */ false ,
475
480
};
476
481
}
477
482
@@ -485,6 +490,7 @@ class MemPoolAccept
485
490
/* m_test_accept */ true ,
486
491
/* m_allow_bip125_replacement */ false ,
487
492
/* m_package_submission */ false , // not submitting to mempool
493
+ /* m_package_feerates */ false ,
488
494
};
489
495
}
490
496
@@ -498,6 +504,7 @@ class MemPoolAccept
498
504
/* m_test_accept */ false ,
499
505
/* m_allow_bip125_replacement */ false ,
500
506
/* m_package_submission */ true ,
507
+ /* m_package_feerates */ true ,
501
508
};
502
509
}
503
510
@@ -510,14 +517,16 @@ class MemPoolAccept
510
517
std::vector<COutPoint>& coins_to_uncache,
511
518
bool test_accept,
512
519
bool allow_bip125_replacement,
513
- bool package_submission)
520
+ bool package_submission,
521
+ bool package_feerates)
514
522
: m_chainparams{chainparams},
515
523
m_accept_time{accept_time},
516
524
m_bypass_limits{bypass_limits},
517
525
m_coins_to_uncache{coins_to_uncache},
518
526
m_test_accept{test_accept},
519
527
m_allow_bip125_replacement{allow_bip125_replacement},
520
- m_package_submission{package_submission}
528
+ m_package_submission{package_submission},
529
+ m_package_feerates{package_feerates}
521
530
{
522
531
}
523
532
};
@@ -819,9 +828,10 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
819
828
return state.Invalid (TxValidationResult::TX_NOT_STANDARD, " bad-txns-too-many-sigops" ,
820
829
strprintf (" %d" , nSigOpsCost));
821
830
822
- // No transactions are allowed below minRelayTxFee except from disconnected
823
- // blocks
824
- if (!bypass_limits && !CheckFeeRate (ws.m_vsize , ws.m_modified_fees , state)) return false ;
831
+ // No individual transactions are allowed below minRelayTxFee and mempool min fee except from
832
+ // disconnected blocks and transactions in a package. Package transactions will be checked using
833
+ // package feerate later.
834
+ if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate (ws.m_vsize , ws.m_modified_fees , state)) return false ;
825
835
826
836
ws.m_iters_conflicting = m_pool.GetIterSet (ws.m_conflicts );
827
837
// Calculate in-mempool ancestors, up to a limit.
@@ -1205,20 +1215,35 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
1205
1215
m_viewmempool.PackageAddTransaction (ws.m_ptx );
1206
1216
}
1207
1217
1218
+ // Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
1219
+ // For transactions consisting of exactly one child and its parents, it suffices to use the
1220
+ // package feerate (total modified fees / total virtual size) to check this requirement.
1221
+ const auto m_total_vsize = std::accumulate (workspaces.cbegin (), workspaces.cend (), int64_t {0 },
1222
+ [](int64_t sum, auto & ws) { return sum + ws.m_vsize ; });
1223
+ const auto m_total_modified_fees = std::accumulate (workspaces.cbegin (), workspaces.cend (), CAmount{0 },
1224
+ [](CAmount sum, auto & ws) { return sum + ws.m_modified_fees ; });
1225
+ const CFeeRate package_feerate (m_total_modified_fees, m_total_vsize);
1226
+ TxValidationState placeholder_state;
1227
+ if (args.m_package_feerates &&
1228
+ !CheckFeeRate (m_total_vsize, m_total_modified_fees, placeholder_state)) {
1229
+ package_state.Invalid (PackageValidationResult::PCKG_POLICY, " package-fee-too-low" );
1230
+ return PackageMempoolAcceptResult (package_state, package_feerate, {});
1231
+ }
1232
+
1208
1233
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
1209
1234
// because it's unnecessary. Also, CPFP carve out can increase the limit for individual
1210
1235
// transactions, but this exemption is not extended to packages in CheckPackageLimits().
1211
1236
std::string err_string;
1212
1237
if (txns.size () > 1 && !PackageMempoolChecks (txns, package_state)) {
1213
- return PackageMempoolAcceptResult (package_state, std::move (results));
1238
+ return PackageMempoolAcceptResult (package_state, package_feerate, std::move (results));
1214
1239
}
1215
1240
1216
1241
for (Workspace& ws : workspaces) {
1217
1242
if (!PolicyScriptChecks (args, ws)) {
1218
1243
// Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.
1219
1244
package_state.Invalid (PackageValidationResult::PCKG_TX, " transaction failed" );
1220
1245
results.emplace (ws.m_ptx ->GetWitnessHash (), MempoolAcceptResult::Failure (ws.m_state ));
1221
- return PackageMempoolAcceptResult (package_state, std::move (results));
1246
+ return PackageMempoolAcceptResult (package_state, package_feerate, std::move (results));
1222
1247
}
1223
1248
if (args.m_test_accept ) {
1224
1249
// When test_accept=true, transactions that pass PolicyScriptChecks are valid because there are
@@ -1229,14 +1254,14 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
1229
1254
}
1230
1255
}
1231
1256
1232
- if (args.m_test_accept ) return PackageMempoolAcceptResult (package_state, std::move (results));
1257
+ if (args.m_test_accept ) return PackageMempoolAcceptResult (package_state, package_feerate, std::move (results));
1233
1258
1234
1259
if (!SubmitPackage (args, workspaces, package_state, results)) {
1235
1260
// PackageValidationState filled in by SubmitPackage().
1236
- return PackageMempoolAcceptResult (package_state, std::move (results));
1261
+ return PackageMempoolAcceptResult (package_state, package_feerate, std::move (results));
1237
1262
}
1238
1263
1239
- return PackageMempoolAcceptResult (package_state, std::move (results));
1264
+ return PackageMempoolAcceptResult (package_state, package_feerate, std::move (results));
1240
1265
}
1241
1266
1242
1267
PackageMempoolAcceptResult MemPoolAccept::AcceptPackage (const Package& package, ATMPArgs& args)
0 commit comments