v29.4-roots.3 · Commit 3: [PATCH 03/30] policy: restore conservative relay and network controls
src/validation.cpp
Before: src/validation.cpp · After: src/validation.cpp
File metadata
index ff281bc1a6f885fd9efe1f01cfc2b91d230df084..c2530e7d119fcc4fe7fb0f89824eeaad60e13a37 100644
Download original patch · Release notes
Diff rows 401–800 of 802. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
src/validation.cpp
CHANGED
|
@@ -907,29 +1060,63 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) (continued)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 923 |
// Enforces 0-fee for dust transactions, no incentive to be mined alone
|
| 924 |
-
if (m_pool.m_opts.require_standard) {
|
| 925 |
if (!PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {
|
| 926 |
return false; // state filled in by PreCheckEphemeralTx
|
| 927 |
}
|
| 928 |
}
|
| 929 |
|
| 930 |
-
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
|
| 931 |
-
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
|
|
|
|
|
|
| 932 |
strprintf("%d", nSigOpsCost));
|
|
|
|
| 933 |
|
| 934 |
// No individual transactions are allowed below the min relay feerate except from disconnected blocks.
|
| 935 |
// This requirement, unlike CheckFeeRate, cannot be bypassed using m_package_feerates because,
|
|
@@ -937,7 +1124,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 937 |
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
|
| 938 |
// due to a replacement.
|
| 939 |
// The only exception is TRUC transactions.
|
| 940 |
-
if (!bypass_limits && ws.m_ptx->version != TRUC_VERSION && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)) {
|
| 941 |
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
| 942 |
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
| 943 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
|
@@ -946,16 +1133,20 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 946 |
// No individual transactions are allowed below the mempool min feerate except from disconnected
|
| 947 |
// blocks and transactions in a package. Package transactions will be checked using package
|
| 948 |
// feerate later.
|
| 949 |
-
if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;
|
| 950 |
|
| 951 |
-
ws.m_iters_conflicting = m_pool.GetIterSet(ws.m_conflicts);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 952 |
|
| 953 |
// Note that these modifications are only applicable to single transaction scenarios;
|
| 954 |
// carve-outs are disabled for multi-transaction evaluations.
|
| 955 |
CTxMemPool::Limits maybe_rbf_limits = m_pool.m_opts.limits;
|
| 956 |
|
| 957 |
// Calculate in-mempool ancestors, up to a limit.
|
| 958 |
-
if (ws.m_conflicts.size() == 1 && args.m_allow_carveouts) {
|
| 959 |
// In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
|
| 960 |
// would meet the chain limits after the conflicts have been removed. However, there isn't a practical
|
| 961 |
// way to do this short of calculating the ancestor and descendant sets with an overlay cache of
|
|
@@ -990,7 +1181,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 990 |
maybe_rbf_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants();
|
| 991 |
}
|
| 992 |
|
| 993 |
-
if (auto ancestors{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, maybe_rbf_limits)}) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 994 |
ws.m_ancestors = std::move(*ancestors);
|
| 995 |
} else {
|
| 996 |
// If CalculateMemPoolAncestors fails second time, we want the original error string.
|
|
@@ -1019,7 +1216,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1019 |
.descendant_count = maybe_rbf_limits.descendant_count + 1,
|
| 1020 |
.descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
|
| 1021 |
};
|
| 1022 |
-
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || ws.m_ptx->version == TRUC_VERSION) {
|
| 1023 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
|
| 1024 |
}
|
| 1025 |
if (auto ancestors_retry{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, cpfp_carve_out_limits)}) {
|
|
@@ -1032,8 +1229,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1032 |
// Even though just checking direct mempool parents for inheritance would be sufficient, we
|
| 1033 |
// check using the full ancestor set here because it's more convenient to use what we have
|
| 1034 |
// already calculated.
|
| 1035 |
-
if (!args.m_bypass_limits) {
|
| 1036 |
-
if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
|
| 1037 |
// Single transaction contexts only.
|
| 1038 |
if (args.m_allow_sibling_eviction && err->second != nullptr) {
|
| 1039 |
// We should only be considering where replacement is considered valid as well.
|
|
@@ -1041,7 +1238,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1041 |
|
| 1042 |
// Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
|
| 1043 |
// included in RBF checks.
|
| 1044 |
-
ws.m_conflicts.insert(err->second->GetHash());
|
|
|
|
| 1045 |
// Adding the sibling to m_iters_conflicting here means that it doesn't count towards
|
| 1046 |
// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
|
| 1047 |
// the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
|
|
@@ -1052,7 +1250,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1052 |
// (which is normally done in PreChecks). However, the only way a TRUC transaction can
|
| 1053 |
// have a non-TRUC and non-BIP125 descendant is due to a reorg.
|
| 1054 |
} else {
|
| 1055 |
-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);
|
| 1056 |
}
|
| 1057 |
}
|
| 1058 |
}
|
|
@@ -1061,18 +1259,22 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1061 |
// that we have the set of all ancestors we can detect this
|
| 1062 |
// pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
|
| 1063 |
// intersect.
|
| 1064 |
-
if (const auto err_string{EntriesAndTxidsDisjoint(ws.m_ancestors, ws.m_conflicts, hash)}) {
|
|
|
|
| 1065 |
// We classify this as a consensus error because a transaction depending on something it
|
| 1066 |
// conflicts with would be inconsistent.
|
| 1067 |
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);
|
| 1068 |
}
|
|
|
|
|
|
|
|
|
|
| 1069 |
|
| 1070 |
// We want to detect conflicts in any tx in a package to trigger package RBF logic
|
| 1071 |
-
m_subpackage.m_rbf |= !ws.m_conflicts.empty();
|
| 1072 |
return true;
|
| 1073 |
}
|
| 1074 |
|
| 1075 |
-
bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
| 1076 |
{
|
| 1077 |
AssertLockHeld(cs_main);
|
| 1078 |
AssertLockHeld(m_pool.cs);
|
|
@@ -1091,27 +1293,31 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
|
| 1091 |
// guarantee that this is incentive-compatible for miners, because it is possible for a
|
| 1092 |
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
|
| 1093 |
// might replace them, under these rules.
|
|
|
|
| 1094 |
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
|
| 1095 |
// This fee-related failure is TX_RECONSIDERABLE because validating in a package may change
|
| 1096 |
// the result.
|
| 1097 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1098 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1099 |
}
|
|
|
|
| 1100 |
|
| 1101 |
CTxMemPool::setEntries all_conflicts;
|
| 1102 |
|
| 1103 |
// Calculate all conflicting entries and enforce Rule #5.
|
| 1104 |
-
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, all_conflicts)}) {
|
| 1105 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1106 |
strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1107 |
}
|
| 1108 |
// Enforce Rule #2.
|
|
|
|
| 1109 |
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, all_conflicts)}) {
|
| 1110 |
// Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
|
| 1111 |
Assume(!ws.m_sibling_eviction);
|
| 1112 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1113 |
strprintf("replacement-adds-unconfirmed%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1114 |
}
|
|
|
|
| 1115 |
|
| 1116 |
// Check if it's economically rational to mine this transaction rather than the ones it
|
| 1117 |
// replaces and pays for its own relay fees. Enforce Rules #3 and #4.
|
|
@@ -1119,12 +1325,14 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
|
| 1119 |
m_subpackage.m_conflicting_fees += it->GetModifiedFee();
|
| 1120 |
m_subpackage.m_conflicting_size += it->GetTxSize();
|
| 1121 |
}
|
|
|
|
| 1122 |
if (const auto err_string{PaysForRBF(m_subpackage.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
|
| 1123 |
m_pool.m_opts.incremental_relay_feerate, hash)}) {
|
| 1124 |
// Result may change in a package context
|
| 1125 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1126 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1127 |
}
|
|
|
|
| 1128 |
|
| 1129 |
// Add all the to-be-removed transactions to the changeset.
|
| 1130 |
for (auto it : all_conflicts) {
|
|
@@ -1133,7 +1341,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
|
| 1133 |
return true;
|
| 1134 |
}
|
| 1135 |
|
| 1136 |
-
bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txns,
|
| 1137 |
std::vector<Workspace>& workspaces,
|
| 1138 |
const int64_t total_vsize,
|
| 1139 |
PackageValidationState& package_state)
|
|
@@ -1147,7 +1355,13 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
|
|
| 1147 |
|
| 1148 |
assert(txns.size() == workspaces.size());
|
| 1149 |
|
| 1150 |
-
auto result = m_pool.CheckPackageLimits(txns, total_vsize);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1151 |
if (!result) {
|
| 1152 |
// This is a package-wide error, separate from an individual transaction error.
|
| 1153 |
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", util::ErrorString(result).original);
|
|
@@ -1233,6 +1447,77 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
|
|
| 1233 |
return true;
|
| 1234 |
}
|
| 1235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1236 |
bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
|
| 1237 |
{
|
| 1238 |
AssertLockHeld(cs_main);
|
|
@@ -1240,7 +1525,7 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
|
|
| 1240 |
const CTransaction& tx = *ws.m_ptx;
|
| 1241 |
TxValidationState& state = ws.m_state;
|
| 1242 |
|
| 1243 |
-
constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
|
| 1244 |
|
| 1245 |
// Check input scripts and signatures.
|
| 1246 |
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
|
@@ -1282,7 +1567,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
|
|
| 1282 |
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
|
| 1283 |
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
|
| 1284 |
ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
|
| 1285 |
-
LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString());
|
| 1286 |
return Assume(false);
|
| 1287 |
}
|
| 1288 |
|
|
@@ -1408,7 +1693,7 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
|
|
| 1408 |
const CTransaction& tx = *ws.m_ptx;
|
| 1409 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1410 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1411 |
-
args.m_bypass_limits, args.m_package_submission,
|
| 1412 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1413 |
m_pool.HasNoInputsOf(tx));
|
| 1414 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
@@ -1448,7 +1733,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
|
| 1448 |
}
|
| 1449 |
}
|
| 1450 |
|
| 1451 |
-
if (m_subpackage.m_rbf && !ReplacementChecks(ws)) {
|
| 1452 |
if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {
|
| 1453 |
// Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
|
| 1454 |
return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);
|
|
@@ -1472,7 +1757,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
|
| 1472 |
FinalizeSubpackage(args);
|
| 1473 |
|
| 1474 |
// Limit the mempool, if appropriate.
|
| 1475 |
-
if (!args.m_package_submission && !args.m_bypass_limits) {
|
| 1476 |
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
|
| 1477 |
if (!m_pool.exists(GenTxid::Txid(ws.m_hash))) {
|
| 1478 |
// The tx no longer meets our (new) mempool minimum feerate but could be reconsidered in a package.
|
|
@@ -1487,7 +1772,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
|
| 1487 |
Assume(iter.has_value());
|
| 1488 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1489 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1490 |
-
args.m_bypass_limits, args.m_package_submission,
|
| 1491 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1492 |
m_pool.HasNoInputsOf(tx));
|
| 1493 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
@@ -1554,12 +1839,14 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
|
| 1554 |
|
| 1555 |
// At this point we have all in-mempool ancestors, and we know every transaction's vsize.
|
| 1556 |
// Run the TRUC checks on the package.
|
|
|
|
|
|
|
| 1557 |
for (Workspace& ws : workspaces) {
|
| 1558 |
-
if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, txns, ws.m_ancestors)}) {
|
| 1559 |
-
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "TRUC-violation", err.value());
|
| 1560 |
return PackageMempoolAcceptResult(package_state, {});
|
| 1561 |
}
|
| 1562 |
-
}
|
| 1563 |
|
| 1564 |
// Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
|
| 1565 |
// For transactions consisting of exactly one child and its parents, it suffices to use the
|
|
@@ -1581,7 +1868,8 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
|
| 1581 |
[](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
|
| 1582 |
TxValidationState placeholder_state;
|
| 1583 |
if (args.m_package_feerates &&
|
| 1584 |
-
!CheckFeeRate(m_subpackage.m_total_vsize, m_subpackage.m_total_modified_fees, placeholder_state)) {
|
|
|
|
| 1585 |
package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
| 1586 |
return PackageMempoolAcceptResult(package_state, {{workspaces.back().m_ptx->GetWitnessHash(),
|
| 1587 |
MempoolAcceptResult::FeeFailure(placeholder_state, CFeeRate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize), all_package_wtxids)}});
|
|
@@ -1589,12 +1877,12 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
|
| 1589 |
|
| 1590 |
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
|
| 1591 |
// because it's unnecessary.
|
| 1592 |
-
if (txns.size() > 1 && !PackageMempoolChecks(txns, workspaces, m_subpackage.m_total_vsize, package_state)) {
|
| 1593 |
return PackageMempoolAcceptResult(package_state, std::move(results));
|
| 1594 |
}
|
| 1595 |
|
| 1596 |
// Now that we've bounded the resulting possible ancestry count, check package for dust spends
|
| 1597 |
-
if (m_pool.m_opts.require_standard) {
|
| 1598 |
TxValidationState child_state;
|
| 1599 |
Wtxid child_wtxid;
|
| 1600 |
if (!CheckEphemeralSpends(txns, m_pool.m_opts.dust_relay_feerate, m_pool, child_state, child_wtxid)) {
|
|
@@ -1880,7 +2168,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
|
| 1880 |
} // anon namespace
|
| 1881 |
|
| 1882 |
MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
|
| 1883 |
-
int64_t accept_time, bool bypass_limits, bool test_accept)
|
| 1884 |
{
|
| 1885 |
AssertLockHeld(::cs_main);
|
| 1886 |
const CChainParams& chainparams{active_chainstate.m_chainman.GetParams()};
|
|
@@ -1888,7 +2176,7 @@ MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTra
|
|
| 1888 |
CTxMemPool& pool{*active_chainstate.GetMempool()};
|
| 1889 |
|
| 1890 |
std::vector<COutPoint> coins_to_uncache;
|
| 1891 |
-
auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept);
|
| 1892 |
MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
|
| 1893 |
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
| 1894 |
// Remove coins that were not present in the coins cache before calling
|
|
@@ -1910,7 +2198,7 @@ MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTra
|
|
| 1910 |
}
|
| 1911 |
|
| 1912 |
PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
|
| 1913 |
-
const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate)
|
| 1914 |
{
|
| 1915 |
AssertLockHeld(cs_main);
|
| 1916 |
assert(!package.empty());
|
|
@@ -1921,10 +2209,10 @@ PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxM
|
|
| 1921 |
auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
| 1922 |
AssertLockHeld(cs_main);
|
| 1923 |
if (test_accept) {
|
| 1924 |
-
auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams, GetTime(), coins_to_uncache);
|
| 1925 |
return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
|
| 1926 |
} else {
|
| 1927 |
-
auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams, GetTime(), coins_to_uncache, client_maxfeerate);
|
| 1928 |
return MemPoolAccept(pool, active_chainstate).AcceptPackage(package, args);
|
|
|
|
| 1098 |
+
}
|
| 1099 |
+
if (dust_penalty > 0) {
|
| 1100 |
+
m_subpackage.m_changeset->m_to_add.modify(ws.m_tx_handle, [&](CTxMemPoolEntry& e) {
|
| 1101 |
+
e.UpdateModifiedFee(-dust_penalty);
|
| 1102 |
+
});
|
| 1103 |
+
ws.m_modified_fees = SaturatingAdd(ws.m_modified_fees, -dust_penalty);
|
| 1104 |
+
}
|
| 1105 |
+
}
|
| 1106 |
+
|
| 1107 |
// Enforces 0-fee for dust transactions, no incentive to be mined alone
|
| 1108 |
+
if (m_pool.m_opts.require_standard && !ignore_rejects.count("dust")) {
|
| 1109 |
if (!PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {
|
| 1110 |
return false; // state filled in by PreCheckEphemeralTx
|
| 1111 |
}
|
| 1112 |
}
|
| 1113 |
|
| 1114 |
+
// To avoid rejecting low-sigop bare-multisig transactions, the sigops
|
| 1115 |
+
// are counted a second time more accurately.
|
| 1116 |
+
if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOpStrict && GetAccurateTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS) > ws.m_vsize * WITNESS_SCALE_FACTOR / nBytesPerSigOpStrict)) {
|
| 1117 |
+
MaybeRejectDbg(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
| 1118 |
strprintf("%d", nSigOpsCost));
|
| 1119 |
+
}
|
| 1120 |
|
| 1121 |
// No individual transactions are allowed below the min relay feerate except from disconnected blocks.
|
| 1122 |
// This requirement, unlike CheckFeeRate, cannot be bypassed using m_package_feerates because,
|
|
|
|
| 1124 |
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
|
| 1125 |
// due to a replacement.
|
| 1126 |
// The only exception is TRUC transactions.
|
| 1127 |
+
if ((ws.m_ptx->version != TRUC_VERSION || m_pool.m_opts.truc_policy != TRUCPolicy::Enforce) && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize) && !args.m_ignore_rejects.count(rejectmsg_lowfee_relay)) {
|
| 1128 |
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
| 1129 |
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
| 1130 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
|
|
|
| 1133 |
// No individual transactions are allowed below the mempool min feerate except from disconnected
|
| 1134 |
// blocks and transactions in a package. Package transactions will be checked using package
|
| 1135 |
// feerate later.
|
| 1136 |
+
if (!args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state, args.m_ignore_rejects)) return false;
|
| 1137 |
|
| 1138 |
+
std::set<Txid> conflicts_as_a_set;
|
| 1139 |
+
std::transform(ws.m_conflicts_incl_policy.begin(), ws.m_conflicts_incl_policy.end(),
|
| 1140 |
+
std::inserter(conflicts_as_a_set, conflicts_as_a_set.end()),
|
| 1141 |
+
[](const std::pair<Txid, bool>& pair){ return pair.first; });
|
| 1142 |
+
ws.m_iters_conflicting = m_pool.GetIterSet(conflicts_as_a_set);
|
| 1143 |
|
| 1144 |
// Note that these modifications are only applicable to single transaction scenarios;
|
| 1145 |
// carve-outs are disabled for multi-transaction evaluations.
|
| 1146 |
CTxMemPool::Limits maybe_rbf_limits = m_pool.m_opts.limits;
|
| 1147 |
|
| 1148 |
// Calculate in-mempool ancestors, up to a limit.
|
| 1149 |
+
if (ws.m_conflicts_incl_policy.size() == 1 && args.m_allow_carveouts) {
|
| 1150 |
// In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
|
| 1151 |
// would meet the chain limits after the conflicts have been removed. However, there isn't a practical
|
| 1152 |
// way to do this short of calculating the ancestor and descendant sets with an overlay cache of
|
|
|
|
| 1181 |
maybe_rbf_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants();
|
| 1182 |
}
|
| 1183 |
|
| 1184 |
+
CTxMemPool::Limits limits;
|
| 1185 |
+
if (ignore_rejects.count("too-long-mempool-chain")) {
|
| 1186 |
+
limits = CTxMemPool::Limits::NoLimits();
|
| 1187 |
+
} else {
|
| 1188 |
+
limits = maybe_rbf_limits;
|
| 1189 |
+
}
|
| 1190 |
+
if (auto ancestors{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, limits)}) {
|
| 1191 |
ws.m_ancestors = std::move(*ancestors);
|
| 1192 |
} else {
|
| 1193 |
// If CalculateMemPoolAncestors fails second time, we want the original error string.
|
|
|
|
| 1216 |
.descendant_count = maybe_rbf_limits.descendant_count + 1,
|
| 1217 |
.descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
|
| 1218 |
};
|
| 1219 |
+
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || (ws.m_ptx->version == TRUC_VERSION && m_pool.m_opts.truc_policy == TRUCPolicy::Enforce)) {
|
| 1220 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
|
| 1221 |
}
|
| 1222 |
if (auto ancestors_retry{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, cpfp_carve_out_limits)}) {
|
|
|
|
| 1229 |
// Even though just checking direct mempool parents for inheritance would be sufficient, we
|
| 1230 |
// check using the full ancestor set here because it's more convenient to use what we have
|
| 1231 |
// already calculated.
|
| 1232 |
+
if (m_pool.m_opts.truc_policy == TRUCPolicy::Enforce && !ignore_rejects.count("truc")) {
|
| 1233 |
+
if (const auto err{SingleTRUCChecks(ws.m_ptx, "truc-", reason, ignore_rejects, ws.m_ancestors, conflicts_as_a_set, ws.m_vsize)}) {
|
| 1234 |
// Single transaction contexts only.
|
| 1235 |
if (args.m_allow_sibling_eviction && err->second != nullptr) {
|
| 1236 |
// We should only be considering where replacement is considered valid as well.
|
|
|
|
| 1238 |
|
| 1239 |
// Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
|
| 1240 |
// included in RBF checks.
|
| 1241 |
+
ws.m_conflicts_incl_policy.emplace(err->second->GetHash(), false);
|
| 1242 |
+
conflicts_as_a_set.insert(err->second->GetHash());
|
| 1243 |
// Adding the sibling to m_iters_conflicting here means that it doesn't count towards
|
| 1244 |
// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
|
| 1245 |
// the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
|
|
|
|
| 1250 |
// (which is normally done in PreChecks). However, the only way a TRUC transaction can
|
| 1251 |
// have a non-TRUC and non-BIP125 descendant is due to a reorg.
|
| 1252 |
} else {
|
| 1253 |
+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, reason, err->first);
|
| 1254 |
}
|
| 1255 |
}
|
| 1256 |
}
|
|
|
|
| 1259 |
// that we have the set of all ancestors we can detect this
|
| 1260 |
// pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
|
| 1261 |
// intersect.
|
| 1262 |
+
bool has_policy_conflict{false};
|
| 1263 |
+
if (const auto err_string{EntriesAndTxidsDisjoint(ws.m_ancestors, ws.m_conflicts_incl_policy, hash, &has_policy_conflict)}) {
|
| 1264 |
// We classify this as a consensus error because a transaction depending on something it
|
| 1265 |
// conflicts with would be inconsistent.
|
| 1266 |
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);
|
| 1267 |
}
|
| 1268 |
+
if (has_policy_conflict) {
|
| 1269 |
+
MaybeReject(TxValidationResult::TX_MEMPOOL_POLICY, "txn-spk-reused-chained");
|
| 1270 |
+
}
|
| 1271 |
|
| 1272 |
// We want to detect conflicts in any tx in a package to trigger package RBF logic
|
| 1273 |
+
m_subpackage.m_rbf |= !ws.m_conflicts_incl_policy.empty();
|
| 1274 |
return true;
|
| 1275 |
}
|
| 1276 |
|
| 1277 |
+
bool MemPoolAccept::ReplacementChecks(ATMPArgs& args, Workspace& ws)
|
| 1278 |
{
|
| 1279 |
AssertLockHeld(cs_main);
|
| 1280 |
AssertLockHeld(m_pool.cs);
|
|
|
|
| 1293 |
// guarantee that this is incentive-compatible for miners, because it is possible for a
|
| 1294 |
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
|
| 1295 |
// might replace them, under these rules.
|
| 1296 |
+
if (!args.m_ignore_rejects.count("insufficient fee")) {
|
| 1297 |
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
|
| 1298 |
// This fee-related failure is TX_RECONSIDERABLE because validating in a package may change
|
| 1299 |
// the result.
|
| 1300 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1301 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1302 |
}
|
| 1303 |
+
} // ignore_rejects
|
| 1304 |
|
| 1305 |
CTxMemPool::setEntries all_conflicts;
|
| 1306 |
|
| 1307 |
// Calculate all conflicting entries and enforce Rule #5.
|
| 1308 |
+
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, all_conflicts, args.m_ignore_rejects)}) {
|
| 1309 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1310 |
strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1311 |
}
|
| 1312 |
// Enforce Rule #2.
|
| 1313 |
+
if (!args.m_ignore_rejects.count("replacement-adds-unconfirmed")) {
|
| 1314 |
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, all_conflicts)}) {
|
| 1315 |
// Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
|
| 1316 |
Assume(!ws.m_sibling_eviction);
|
| 1317 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1318 |
strprintf("replacement-adds-unconfirmed%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1319 |
}
|
| 1320 |
+
} // ignore_rejects
|
| 1321 |
|
| 1322 |
// Check if it's economically rational to mine this transaction rather than the ones it
|
| 1323 |
// replaces and pays for its own relay fees. Enforce Rules #3 and #4.
|
|
|
|
| 1325 |
m_subpackage.m_conflicting_fees += it->GetModifiedFee();
|
| 1326 |
m_subpackage.m_conflicting_size += it->GetTxSize();
|
| 1327 |
}
|
| 1328 |
+
if (!args.m_ignore_rejects.count("insufficient fee")) {
|
| 1329 |
if (const auto err_string{PaysForRBF(m_subpackage.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
|
| 1330 |
m_pool.m_opts.incremental_relay_feerate, hash)}) {
|
| 1331 |
// Result may change in a package context
|
| 1332 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1333 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1334 |
}
|
| 1335 |
+
} // ignore_rejects
|
| 1336 |
|
| 1337 |
// Add all the to-be-removed transactions to the changeset.
|
| 1338 |
for (auto it : all_conflicts) {
|
|
|
|
| 1341 |
return true;
|
| 1342 |
}
|
| 1343 |
|
| 1344 |
+
bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args, const std::vector<CTransactionRef>& txns,
|
| 1345 |
std::vector<Workspace>& workspaces,
|
| 1346 |
const int64_t total_vsize,
|
| 1347 |
PackageValidationState& package_state)
|
|
|
|
| 1355 |
|
| 1356 |
assert(txns.size() == workspaces.size());
|
| 1357 |
|
| 1358 |
+
util::Result<void> result = [&]() EXCLUSIVE_LOCKS_REQUIRED(m_pool.cs) {
|
| 1359 |
+
if (args.m_ignore_rejects.count("package-mempool-limits")) {
|
| 1360 |
+
return util::Result<void>();
|
| 1361 |
+
} else {
|
| 1362 |
+
return m_pool.CheckPackageLimits(txns, total_vsize);
|
| 1363 |
+
}
|
| 1364 |
+
}();
|
| 1365 |
if (!result) {
|
| 1366 |
// This is a package-wide error, separate from an individual transaction error.
|
| 1367 |
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", util::ErrorString(result).original);
|
|
|
|
| 1447 |
return true;
|
| 1448 |
}
|
| 1449 |
|
| 1450 |
+
unsigned int PolicyScriptVerifyFlags(const ignore_rejects_type& ignore_rejects)
|
| 1451 |
+
{
|
| 1452 |
+
if (ignore_rejects.empty()) {
|
| 1453 |
+
return STANDARD_SCRIPT_VERIFY_FLAGS;
|
| 1454 |
+
}
|
| 1455 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag")) {
|
| 1456 |
+
return MANDATORY_SCRIPT_VERIFY_FLAGS;
|
| 1457 |
+
}
|
| 1458 |
+
|
| 1459 |
+
unsigned int flags = STANDARD_SCRIPT_VERIFY_FLAGS;
|
| 1460 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable")) {
|
| 1461 |
+
constexpr unsigned int upgradable_policy_flags =
|
| 1462 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
|
| 1463 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
|
| 1464 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
|
| 1465 |
+
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
|
| 1466 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
|
| 1467 |
+
flags &= ~upgradable_policy_flags;
|
| 1468 |
+
} else {
|
| 1469 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-nops")) {
|
| 1470 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS;
|
| 1471 |
+
}
|
| 1472 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-witness_program")) {
|
| 1473 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
|
| 1474 |
+
}
|
| 1475 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-taproot_version")) {
|
| 1476 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION;
|
| 1477 |
+
}
|
| 1478 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-op_success")) {
|
| 1479 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS;
|
| 1480 |
+
}
|
| 1481 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-pubkeytype")) {
|
| 1482 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
|
| 1483 |
+
}
|
| 1484 |
+
}
|
| 1485 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-bip62")) {
|
| 1486 |
+
constexpr unsigned int bip62_policy_flags =
|
| 1487 |
+
SCRIPT_VERIFY_LOW_S |
|
| 1488 |
+
SCRIPT_VERIFY_SIGPUSHONLY | // NOTE: not actually set ever
|
| 1489 |
+
SCRIPT_VERIFY_MINIMALDATA;
|
| 1490 |
+
flags &= ~bip62_policy_flags;
|
| 1491 |
+
} else {
|
| 1492 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-low_s")) {
|
| 1493 |
+
flags &= ~SCRIPT_VERIFY_LOW_S;
|
| 1494 |
+
}
|
| 1495 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-minimaldata")) {
|
| 1496 |
+
flags &= ~SCRIPT_VERIFY_MINIMALDATA;
|
| 1497 |
+
}
|
| 1498 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-cleanstack")) {
|
| 1499 |
+
flags &= ~SCRIPT_VERIFY_CLEANSTACK;
|
| 1500 |
+
}
|
| 1501 |
+
}
|
| 1502 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-strictenc")) {
|
| 1503 |
+
flags &= ~SCRIPT_VERIFY_STRICTENC;
|
| 1504 |
+
}
|
| 1505 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-minimalif")) {
|
| 1506 |
+
flags &= ~SCRIPT_VERIFY_MINIMALIF;
|
| 1507 |
+
}
|
| 1508 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-nullfail")) {
|
| 1509 |
+
flags &= ~SCRIPT_VERIFY_NULLFAIL;
|
| 1510 |
+
}
|
| 1511 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-witness_pubkeytype")) {
|
| 1512 |
+
flags &= ~SCRIPT_VERIFY_WITNESS_PUBKEYTYPE;
|
| 1513 |
+
}
|
| 1514 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-const_scriptcode")) {
|
| 1515 |
+
flags &= ~SCRIPT_VERIFY_CONST_SCRIPTCODE;
|
| 1516 |
+
}
|
| 1517 |
+
flags |= MANDATORY_SCRIPT_VERIFY_FLAGS; // for safety
|
| 1518 |
+
return flags;
|
| 1519 |
+
}
|
| 1520 |
+
|
| 1521 |
bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
|
| 1522 |
{
|
| 1523 |
AssertLockHeld(cs_main);
|
|
|
|
| 1525 |
const CTransaction& tx = *ws.m_ptx;
|
| 1526 |
TxValidationState& state = ws.m_state;
|
| 1527 |
|
| 1528 |
+
const unsigned int scriptVerifyFlags = PolicyScriptVerifyFlags(args.m_ignore_rejects);
|
| 1529 |
|
| 1530 |
// Check input scripts and signatures.
|
| 1531 |
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
|
|
|
| 1567 |
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
|
| 1568 |
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
|
| 1569 |
ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
|
| 1570 |
+
LogError("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s", hash.ToString(), state.ToString());
|
| 1571 |
return Assume(false);
|
| 1572 |
}
|
| 1573 |
|
|
|
|
| 1693 |
const CTransaction& tx = *ws.m_ptx;
|
| 1694 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1695 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1696 |
+
args.m_ignore_rejects, args.m_package_submission,
|
| 1697 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1698 |
m_pool.HasNoInputsOf(tx));
|
| 1699 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
|
|
| 1733 |
}
|
| 1734 |
}
|
| 1735 |
|
| 1736 |
+
if (m_subpackage.m_rbf && !ReplacementChecks(args, ws)) {
|
| 1737 |
if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {
|
| 1738 |
// Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
|
| 1739 |
return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);
|
|
|
|
| 1757 |
FinalizeSubpackage(args);
|
| 1758 |
|
| 1759 |
// Limit the mempool, if appropriate.
|
| 1760 |
+
if (!args.m_package_submission && !args.m_ignore_rejects.count(rejectmsg_mempoolfull)) {
|
| 1761 |
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
|
| 1762 |
if (!m_pool.exists(GenTxid::Txid(ws.m_hash))) {
|
| 1763 |
// The tx no longer meets our (new) mempool minimum feerate but could be reconsidered in a package.
|
|
|
|
| 1772 |
Assume(iter.has_value());
|
| 1773 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1774 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1775 |
+
args.m_ignore_rejects, args.m_package_submission,
|
| 1776 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1777 |
m_pool.HasNoInputsOf(tx));
|
| 1778 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
|
|
| 1839 |
|
| 1840 |
// At this point we have all in-mempool ancestors, and we know every transaction's vsize.
|
| 1841 |
// Run the TRUC checks on the package.
|
| 1842 |
+
if (m_pool.m_opts.truc_policy == TRUCPolicy::Enforce) {
|
| 1843 |
+
std::string reason;
|
| 1844 |
for (Workspace& ws : workspaces) {
|
| 1845 |
+
if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, "truc-", reason, args.m_ignore_rejects, txns, ws.m_ancestors)}) {
|
| 1846 |
+
package_state.Invalid(PackageValidationResult::PCKG_POLICY, reason, err.value());
|
| 1847 |
return PackageMempoolAcceptResult(package_state, {});
|
| 1848 |
}
|
| 1849 |
+
}}
|
| 1850 |
|
| 1851 |
// Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
|
| 1852 |
// For transactions consisting of exactly one child and its parents, it suffices to use the
|
|
|
|
| 1868 |
[](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
|
| 1869 |
TxValidationState placeholder_state;
|
| 1870 |
if (args.m_package_feerates &&
|
| 1871 |
+
(!args.m_ignore_rejects.count("package-fee-too-low")) &&
|
| 1872 |
+
!CheckFeeRate(m_subpackage.m_total_vsize, m_subpackage.m_total_modified_fees, placeholder_state, empty_ignore_rejects)) {
|
| 1873 |
package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
| 1874 |
return PackageMempoolAcceptResult(package_state, {{workspaces.back().m_ptx->GetWitnessHash(),
|
| 1875 |
MempoolAcceptResult::FeeFailure(placeholder_state, CFeeRate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize), all_package_wtxids)}});
|
|
|
|
| 1877 |
|
| 1878 |
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
|
| 1879 |
// because it's unnecessary.
|
| 1880 |
+
if (txns.size() > 1 && !PackageMempoolChecks(args, txns, workspaces, m_subpackage.m_total_vsize, package_state)) {
|
| 1881 |
return PackageMempoolAcceptResult(package_state, std::move(results));
|
| 1882 |
}
|
| 1883 |
|
| 1884 |
// Now that we've bounded the resulting possible ancestry count, check package for dust spends
|
| 1885 |
+
if (m_pool.m_opts.require_standard && !(args.m_ignore_rejects.count("dust") || args.m_ignore_rejects.count("unspent-dust") || args.m_ignore_rejects.count("missing-ephemeral-spends"))) {
|
| 1886 |
TxValidationState child_state;
|
| 1887 |
Wtxid child_wtxid;
|
| 1888 |
if (!CheckEphemeralSpends(txns, m_pool.m_opts.dust_relay_feerate, m_pool, child_state, child_wtxid)) {
|
|
|
|
| 2168 |
} // anon namespace
|
| 2169 |
|
| 2170 |
MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
|
| 2171 |
+
int64_t accept_time, const ignore_rejects_type& ignore_rejects, bool test_accept)
|
| 2172 |
{
|
| 2173 |
AssertLockHeld(::cs_main);
|
| 2174 |
const CChainParams& chainparams{active_chainstate.m_chainman.GetParams()};
|
|
|
|
| 2176 |
CTxMemPool& pool{*active_chainstate.GetMempool()};
|
| 2177 |
|
| 2178 |
std::vector<COutPoint> coins_to_uncache;
|
| 2179 |
+
auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, ignore_rejects, coins_to_uncache, test_accept);
|
| 2180 |
MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
|
| 2181 |
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
| 2182 |
// Remove coins that were not present in the coins cache before calling
|
|
|
|
| 2198 |
}
|
| 2199 |
|
| 2200 |
PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
|
| 2201 |
+
const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate, const ignore_rejects_type& ignore_rejects)
|
| 2202 |
{
|
| 2203 |
AssertLockHeld(cs_main);
|
| 2204 |
assert(!package.empty());
|
|
|
|
| 2209 |
auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
| 2210 |
AssertLockHeld(cs_main);
|
| 2211 |
if (test_accept) {
|
| 2212 |
+
auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams, GetTime(), ignore_rejects, coins_to_uncache);
|
| 2213 |
return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
|
| 2214 |
} else {
|
| 2215 |
+
auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams, GetTime(), coins_to_uncache, client_maxfeerate, ignore_rejects);
|
| 2216 |
return MemPoolAccept(pool, active_chainstate).AcceptPackage(package, args);
|