v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3
src/validation.cpp
Before: src/validation.cpp · After: src/validation.cpp
File metadata
index 21ccf045fbfcd200ec1dea6ad867a65eec02dfbc..89daf215e6c9aec6905aa611c1c360fc980e9921 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
|
@@ -926,29 +1079,63 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) (continued)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 942 |
// Enforces 0-fee for dust transactions, no incentive to be mined alone
|
| 943 |
-
if (m_pool.m_opts.require_standard) {
|
| 944 |
if (!PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {
|
| 945 |
return false; // state filled in by PreCheckEphemeralTx
|
| 946 |
}
|
| 947 |
}
|
| 948 |
|
| 949 |
-
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
|
| 950 |
-
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
|
|
|
|
|
|
| 951 |
strprintf("%d", nSigOpsCost));
|
|
|
|
| 952 |
|
| 953 |
// No individual transactions are allowed below the min relay feerate except from disconnected blocks.
|
| 954 |
// This requirement, unlike CheckFeeRate, cannot be bypassed using m_package_feerates because,
|
|
@@ -956,7 +1143,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 956 |
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
|
| 957 |
// due to a replacement.
|
| 958 |
// The only exception is TRUC transactions.
|
| 959 |
-
if (!bypass_limits && ws.m_ptx->version != TRUC_VERSION && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)) {
|
| 960 |
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
| 961 |
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
| 962 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
|
@@ -965,16 +1152,20 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 965 |
// No individual transactions are allowed below the mempool min feerate except from disconnected
|
| 966 |
// blocks and transactions in a package. Package transactions will be checked using package
|
| 967 |
// feerate later.
|
| 968 |
-
if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;
|
| 969 |
|
| 970 |
-
ws.m_iters_conflicting = m_pool.GetIterSet(ws.m_conflicts);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 971 |
|
| 972 |
// Note that these modifications are only applicable to single transaction scenarios;
|
| 973 |
// carve-outs are disabled for multi-transaction evaluations.
|
| 974 |
CTxMemPool::Limits maybe_rbf_limits = m_pool.m_opts.limits;
|
| 975 |
|
| 976 |
// Calculate in-mempool ancestors, up to a limit.
|
| 977 |
-
if (ws.m_conflicts.size() == 1 && args.m_allow_carveouts) {
|
| 978 |
// In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
|
| 979 |
// would meet the chain limits after the conflicts have been removed. However, there isn't a practical
|
| 980 |
// way to do this short of calculating the ancestor and descendant sets with an overlay cache of
|
|
@@ -1009,7 +1200,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1009 |
maybe_rbf_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants();
|
| 1010 |
}
|
| 1011 |
|
| 1012 |
-
if (auto ancestors{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, maybe_rbf_limits)}) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1013 |
ws.m_ancestors = std::move(*ancestors);
|
| 1014 |
} else {
|
| 1015 |
// If CalculateMemPoolAncestors fails second time, we want the original error string.
|
|
@@ -1038,7 +1235,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1038 |
.descendant_count = maybe_rbf_limits.descendant_count + 1,
|
| 1039 |
.descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
|
| 1040 |
};
|
| 1041 |
-
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || ws.m_ptx->version == TRUC_VERSION) {
|
| 1042 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
|
| 1043 |
}
|
| 1044 |
if (auto ancestors_retry{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, cpfp_carve_out_limits)}) {
|
|
@@ -1051,8 +1248,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1051 |
// Even though just checking direct mempool parents for inheritance would be sufficient, we
|
| 1052 |
// check using the full ancestor set here because it's more convenient to use what we have
|
| 1053 |
// already calculated.
|
| 1054 |
-
if (!args.m_bypass_limits) {
|
| 1055 |
-
if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
|
| 1056 |
// Single transaction contexts only.
|
| 1057 |
if (args.m_allow_sibling_eviction && err->second != nullptr) {
|
| 1058 |
// We should only be considering where replacement is considered valid as well.
|
|
@@ -1060,7 +1257,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1060 |
|
| 1061 |
// Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
|
| 1062 |
// included in RBF checks.
|
| 1063 |
-
ws.m_conflicts.insert(err->second->GetHash());
|
|
|
|
| 1064 |
// Adding the sibling to m_iters_conflicting here means that it doesn't count towards
|
| 1065 |
// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
|
| 1066 |
// the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
|
|
@@ -1071,7 +1269,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1071 |
// (which is normally done in PreChecks). However, the only way a TRUC transaction can
|
| 1072 |
// have a non-TRUC and non-BIP125 descendant is due to a reorg.
|
| 1073 |
} else {
|
| 1074 |
-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);
|
| 1075 |
}
|
| 1076 |
}
|
| 1077 |
}
|
|
@@ -1080,18 +1278,22 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 1080 |
// that we have the set of all ancestors we can detect this
|
| 1081 |
// pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
|
| 1082 |
// intersect.
|
| 1083 |
-
if (const auto err_string{EntriesAndTxidsDisjoint(ws.m_ancestors, ws.m_conflicts, hash)}) {
|
|
|
|
| 1084 |
// We classify this as a consensus error because a transaction depending on something it
|
| 1085 |
// conflicts with would be inconsistent.
|
| 1086 |
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);
|
| 1087 |
}
|
|
|
|
|
|
|
|
|
|
| 1088 |
|
| 1089 |
// We want to detect conflicts in any tx in a package to trigger package RBF logic
|
| 1090 |
-
m_subpackage.m_rbf |= !ws.m_conflicts.empty();
|
| 1091 |
return true;
|
| 1092 |
}
|
| 1093 |
|
| 1094 |
-
bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
| 1095 |
{
|
| 1096 |
AssertLockHeld(cs_main);
|
| 1097 |
AssertLockHeld(m_pool.cs);
|
|
@@ -1110,27 +1312,31 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
|
| 1110 |
// guarantee that this is incentive-compatible for miners, because it is possible for a
|
| 1111 |
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
|
| 1112 |
// might replace them, under these rules.
|
|
|
|
| 1113 |
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
|
| 1114 |
// This fee-related failure is TX_RECONSIDERABLE because validating in a package may change
|
| 1115 |
// the result.
|
| 1116 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1117 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1118 |
}
|
|
|
|
| 1119 |
|
| 1120 |
CTxMemPool::setEntries all_conflicts;
|
| 1121 |
|
| 1122 |
// Calculate all conflicting entries and enforce Rule #5.
|
| 1123 |
-
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, all_conflicts)}) {
|
| 1124 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1125 |
strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1126 |
}
|
| 1127 |
// Enforce Rule #2.
|
|
|
|
| 1128 |
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, all_conflicts)}) {
|
| 1129 |
// Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
|
| 1130 |
Assume(!ws.m_sibling_eviction);
|
| 1131 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1132 |
strprintf("replacement-adds-unconfirmed%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1133 |
}
|
|
|
|
| 1134 |
|
| 1135 |
// Check if it's economically rational to mine this transaction rather than the ones it
|
| 1136 |
// replaces and pays for its own relay fees. Enforce Rules #3 and #4.
|
|
@@ -1138,12 +1344,14 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
|
| 1138 |
m_subpackage.m_conflicting_fees += it->GetModifiedFee();
|
| 1139 |
m_subpackage.m_conflicting_size += it->GetTxSize();
|
| 1140 |
}
|
|
|
|
| 1141 |
if (const auto err_string{PaysForRBF(m_subpackage.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
|
| 1142 |
m_pool.m_opts.incremental_relay_feerate, hash)}) {
|
| 1143 |
// Result may change in a package context
|
| 1144 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1145 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1146 |
}
|
|
|
|
| 1147 |
|
| 1148 |
// Add all the to-be-removed transactions to the changeset.
|
| 1149 |
for (auto it : all_conflicts) {
|
|
@@ -1152,7 +1360,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
|
| 1152 |
return true;
|
| 1153 |
}
|
| 1154 |
|
| 1155 |
-
bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txns,
|
| 1156 |
std::vector<Workspace>& workspaces,
|
| 1157 |
const int64_t total_vsize,
|
| 1158 |
PackageValidationState& package_state)
|
|
@@ -1165,7 +1373,13 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
|
|
| 1165 |
|
| 1166 |
assert(txns.size() == workspaces.size());
|
| 1167 |
|
| 1168 |
-
auto result = m_pool.CheckPackageLimits(txns, total_vsize);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1169 |
if (!result) {
|
| 1170 |
// This is a package-wide error, separate from an individual transaction error.
|
| 1171 |
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", util::ErrorString(result).original);
|
|
@@ -1251,6 +1465,77 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
|
|
| 1251 |
return true;
|
| 1252 |
}
|
| 1253 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1254 |
bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
|
| 1255 |
{
|
| 1256 |
AssertLockHeld(cs_main);
|
|
@@ -1258,7 +1543,7 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
|
|
| 1258 |
const CTransaction& tx = *ws.m_ptx;
|
| 1259 |
TxValidationState& state = ws.m_state;
|
| 1260 |
|
| 1261 |
-
constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
|
| 1262 |
|
| 1263 |
// Check input scripts and signatures.
|
| 1264 |
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
|
@@ -1300,7 +1585,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
|
|
| 1300 |
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
|
| 1301 |
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
|
| 1302 |
ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
|
| 1303 |
-
LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString());
|
| 1304 |
return Assume(false);
|
| 1305 |
}
|
| 1306 |
|
|
@@ -1425,7 +1710,7 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
|
|
| 1425 |
const CTransaction& tx = *ws.m_ptx;
|
| 1426 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1427 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1428 |
-
args.m_bypass_limits, args.m_package_submission,
|
| 1429 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1430 |
m_pool.HasNoInputsOf(tx));
|
| 1431 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
@@ -1465,7 +1750,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
|
| 1465 |
}
|
| 1466 |
}
|
| 1467 |
|
| 1468 |
-
if (m_subpackage.m_rbf && !ReplacementChecks(ws)) {
|
| 1469 |
if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {
|
| 1470 |
// Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
|
| 1471 |
return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);
|
|
@@ -1489,7 +1774,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
|
| 1489 |
FinalizeSubpackage(args);
|
| 1490 |
|
| 1491 |
// Limit the mempool, if appropriate.
|
| 1492 |
-
if (!args.m_package_submission && !args.m_bypass_limits) {
|
| 1493 |
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
|
| 1494 |
// If mempool contents change, then the m_view cache is dirty. Given this isn't a package
|
| 1495 |
// submission, we won't be using the cache anymore, but clear it anyway for clarity.
|
|
@@ -1508,7 +1793,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
|
| 1508 |
Assume(iter.has_value());
|
| 1509 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1510 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1511 |
-
args.m_bypass_limits, args.m_package_submission,
|
| 1512 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1513 |
m_pool.HasNoInputsOf(tx));
|
| 1514 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
@@ -1575,12 +1860,14 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
|
| 1575 |
|
| 1576 |
// At this point we have all in-mempool ancestors, and we know every transaction's vsize.
|
| 1577 |
// Run the TRUC checks on the package.
|
|
|
|
|
|
|
| 1578 |
for (Workspace& ws : workspaces) {
|
| 1579 |
-
if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, txns, ws.m_ancestors)}) {
|
| 1580 |
-
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "TRUC-violation", err.value());
|
| 1581 |
return PackageMempoolAcceptResult(package_state, {});
|
| 1582 |
}
|
| 1583 |
-
}
|
| 1584 |
|
| 1585 |
// Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
|
| 1586 |
// For transactions consisting of exactly one child and its parents, it suffices to use the
|
|
@@ -1602,7 +1889,8 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
|
| 1602 |
[](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
|
| 1603 |
TxValidationState placeholder_state;
|
| 1604 |
if (args.m_package_feerates &&
|
| 1605 |
-
!CheckFeeRate(m_subpackage.m_total_vsize, m_subpackage.m_total_modified_fees, placeholder_state)) {
|
|
|
|
| 1606 |
package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
| 1607 |
return PackageMempoolAcceptResult(package_state, {{workspaces.back().m_ptx->GetWitnessHash(),
|
| 1608 |
MempoolAcceptResult::FeeFailure(placeholder_state, CFeeRate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize), all_package_wtxids)}});
|
|
@@ -1610,12 +1898,12 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
|
| 1610 |
|
| 1611 |
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
|
| 1612 |
// because it's unnecessary.
|
| 1613 |
-
if (txns.size() > 1 && !PackageMempoolChecks(txns, workspaces, m_subpackage.m_total_vsize, package_state)) {
|
| 1614 |
return PackageMempoolAcceptResult(package_state, std::move(results));
|
| 1615 |
}
|
| 1616 |
|
| 1617 |
// Now that we've bounded the resulting possible ancestry count, check package for dust spends
|
| 1618 |
-
if (m_pool.m_opts.require_standard) {
|
| 1619 |
TxValidationState child_state;
|
| 1620 |
Wtxid child_wtxid;
|
| 1621 |
if (!CheckEphemeralSpends(txns, m_pool.m_opts.dust_relay_feerate, m_pool, child_state, child_wtxid)) {
|
|
@@ -1865,7 +2153,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
|
| 1865 |
} // anon namespace
|
| 1866 |
|
| 1867 |
MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
|
| 1868 |
-
int64_t accept_time, bool bypass_limits, bool test_accept)
|
| 1869 |
{
|
| 1870 |
AssertLockHeld(::cs_main);
|
| 1871 |
const CChainParams& chainparams{active_chainstate.m_chainman.GetParams()};
|
|
@@ -1873,7 +2161,7 @@ MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTra
|
|
| 1873 |
CTxMemPool& pool{*active_chainstate.GetMempool()};
|
| 1874 |
|
| 1875 |
std::vector<COutPoint> coins_to_uncache;
|
| 1876 |
-
auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept);
|
| 1877 |
MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
|
| 1878 |
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
| 1879 |
// Remove coins that were not present in the coins cache before calling
|
|
@@ -1895,7 +2183,7 @@ MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTra
|
|
| 1895 |
}
|
| 1896 |
|
| 1897 |
PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
|
| 1898 |
-
const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate)
|
| 1899 |
{
|
| 1900 |
AssertLockHeld(cs_main);
|
| 1901 |
assert(!package.empty());
|
|
@@ -1906,10 +2194,10 @@ PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxM
|
|
| 1906 |
auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
| 1907 |
AssertLockHeld(cs_main);
|
| 1908 |
if (test_accept) {
|
| 1909 |
-
auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams, GetTime(), coins_to_uncache);
|
| 1910 |
return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
|
| 1911 |
} else {
|
| 1912 |
-
auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams, GetTime(), coins_to_uncache, client_maxfeerate);
|
| 1913 |
return MemPoolAccept(pool, active_chainstate).AcceptPackage(package, args);
|
|
|
|
| 1117 |
+
}
|
| 1118 |
+
if (dust_penalty > 0) {
|
| 1119 |
+
m_subpackage.m_changeset->m_to_add.modify(ws.m_tx_handle, [&](CTxMemPoolEntry& e) {
|
| 1120 |
+
e.UpdateModifiedFee(-dust_penalty);
|
| 1121 |
+
});
|
| 1122 |
+
ws.m_modified_fees = SaturatingAdd(ws.m_modified_fees, -dust_penalty);
|
| 1123 |
+
}
|
| 1124 |
+
}
|
| 1125 |
+
|
| 1126 |
// Enforces 0-fee for dust transactions, no incentive to be mined alone
|
| 1127 |
+
if (m_pool.m_opts.require_standard && !ignore_rejects.count("dust")) {
|
| 1128 |
if (!PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {
|
| 1129 |
return false; // state filled in by PreCheckEphemeralTx
|
| 1130 |
}
|
| 1131 |
}
|
| 1132 |
|
| 1133 |
+
// To avoid rejecting low-sigop bare-multisig transactions, the sigops
|
| 1134 |
+
// are counted a second time more accurately.
|
| 1135 |
+
if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOpStrict && GetAccurateTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS) > ws.m_vsize * WITNESS_SCALE_FACTOR / nBytesPerSigOpStrict)) {
|
| 1136 |
+
MaybeRejectDbg(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
| 1137 |
strprintf("%d", nSigOpsCost));
|
| 1138 |
+
}
|
| 1139 |
|
| 1140 |
// No individual transactions are allowed below the min relay feerate except from disconnected blocks.
|
| 1141 |
// This requirement, unlike CheckFeeRate, cannot be bypassed using m_package_feerates because,
|
|
|
|
| 1143 |
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
|
| 1144 |
// due to a replacement.
|
| 1145 |
// The only exception is TRUC transactions.
|
| 1146 |
+
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)) {
|
| 1147 |
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
| 1148 |
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
| 1149 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
|
|
|
| 1152 |
// No individual transactions are allowed below the mempool min feerate except from disconnected
|
| 1153 |
// blocks and transactions in a package. Package transactions will be checked using package
|
| 1154 |
// feerate later.
|
| 1155 |
+
if (!args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state, args.m_ignore_rejects)) return false;
|
| 1156 |
|
| 1157 |
+
std::set<Txid> conflicts_as_a_set;
|
| 1158 |
+
std::transform(ws.m_conflicts_incl_policy.begin(), ws.m_conflicts_incl_policy.end(),
|
| 1159 |
+
std::inserter(conflicts_as_a_set, conflicts_as_a_set.end()),
|
| 1160 |
+
[](const std::pair<Txid, bool>& pair){ return pair.first; });
|
| 1161 |
+
ws.m_iters_conflicting = m_pool.GetIterSet(conflicts_as_a_set);
|
| 1162 |
|
| 1163 |
// Note that these modifications are only applicable to single transaction scenarios;
|
| 1164 |
// carve-outs are disabled for multi-transaction evaluations.
|
| 1165 |
CTxMemPool::Limits maybe_rbf_limits = m_pool.m_opts.limits;
|
| 1166 |
|
| 1167 |
// Calculate in-mempool ancestors, up to a limit.
|
| 1168 |
+
if (ws.m_conflicts_incl_policy.size() == 1 && args.m_allow_carveouts) {
|
| 1169 |
// In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
|
| 1170 |
// would meet the chain limits after the conflicts have been removed. However, there isn't a practical
|
| 1171 |
// way to do this short of calculating the ancestor and descendant sets with an overlay cache of
|
|
|
|
| 1200 |
maybe_rbf_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants();
|
| 1201 |
}
|
| 1202 |
|
| 1203 |
+
CTxMemPool::Limits limits;
|
| 1204 |
+
if (ignore_rejects.count("too-long-mempool-chain")) {
|
| 1205 |
+
limits = CTxMemPool::Limits::NoLimits();
|
| 1206 |
+
} else {
|
| 1207 |
+
limits = maybe_rbf_limits;
|
| 1208 |
+
}
|
| 1209 |
+
if (auto ancestors{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, limits)}) {
|
| 1210 |
ws.m_ancestors = std::move(*ancestors);
|
| 1211 |
} else {
|
| 1212 |
// If CalculateMemPoolAncestors fails second time, we want the original error string.
|
|
|
|
| 1235 |
.descendant_count = maybe_rbf_limits.descendant_count + 1,
|
| 1236 |
.descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
|
| 1237 |
};
|
| 1238 |
+
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || (ws.m_ptx->version == TRUC_VERSION && m_pool.m_opts.truc_policy == TRUCPolicy::Enforce)) {
|
| 1239 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
|
| 1240 |
}
|
| 1241 |
if (auto ancestors_retry{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, cpfp_carve_out_limits)}) {
|
|
|
|
| 1248 |
// Even though just checking direct mempool parents for inheritance would be sufficient, we
|
| 1249 |
// check using the full ancestor set here because it's more convenient to use what we have
|
| 1250 |
// already calculated.
|
| 1251 |
+
if (m_pool.m_opts.truc_policy == TRUCPolicy::Enforce && !ignore_rejects.count("truc")) {
|
| 1252 |
+
if (const auto err{SingleTRUCChecks(ws.m_ptx, "truc-", reason, ignore_rejects, ws.m_ancestors, conflicts_as_a_set, ws.m_vsize)}) {
|
| 1253 |
// Single transaction contexts only.
|
| 1254 |
if (args.m_allow_sibling_eviction && err->second != nullptr) {
|
| 1255 |
// We should only be considering where replacement is considered valid as well.
|
|
|
|
| 1257 |
|
| 1258 |
// Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
|
| 1259 |
// included in RBF checks.
|
| 1260 |
+
ws.m_conflicts_incl_policy.emplace(err->second->GetHash(), false);
|
| 1261 |
+
conflicts_as_a_set.insert(err->second->GetHash());
|
| 1262 |
// Adding the sibling to m_iters_conflicting here means that it doesn't count towards
|
| 1263 |
// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
|
| 1264 |
// the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
|
|
|
|
| 1269 |
// (which is normally done in PreChecks). However, the only way a TRUC transaction can
|
| 1270 |
// have a non-TRUC and non-BIP125 descendant is due to a reorg.
|
| 1271 |
} else {
|
| 1272 |
+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, reason, err->first);
|
| 1273 |
}
|
| 1274 |
}
|
| 1275 |
}
|
|
|
|
| 1278 |
// that we have the set of all ancestors we can detect this
|
| 1279 |
// pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
|
| 1280 |
// intersect.
|
| 1281 |
+
bool has_policy_conflict{false};
|
| 1282 |
+
if (const auto err_string{EntriesAndTxidsDisjoint(ws.m_ancestors, ws.m_conflicts_incl_policy, hash, &has_policy_conflict)}) {
|
| 1283 |
// We classify this as a consensus error because a transaction depending on something it
|
| 1284 |
// conflicts with would be inconsistent.
|
| 1285 |
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);
|
| 1286 |
}
|
| 1287 |
+
if (has_policy_conflict) {
|
| 1288 |
+
MaybeReject(TxValidationResult::TX_MEMPOOL_POLICY, "txn-spk-reused-chained");
|
| 1289 |
+
}
|
| 1290 |
|
| 1291 |
// We want to detect conflicts in any tx in a package to trigger package RBF logic
|
| 1292 |
+
m_subpackage.m_rbf |= !ws.m_conflicts_incl_policy.empty();
|
| 1293 |
return true;
|
| 1294 |
}
|
| 1295 |
|
| 1296 |
+
bool MemPoolAccept::ReplacementChecks(ATMPArgs& args, Workspace& ws)
|
| 1297 |
{
|
| 1298 |
AssertLockHeld(cs_main);
|
| 1299 |
AssertLockHeld(m_pool.cs);
|
|
|
|
| 1312 |
// guarantee that this is incentive-compatible for miners, because it is possible for a
|
| 1313 |
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
|
| 1314 |
// might replace them, under these rules.
|
| 1315 |
+
if (!args.m_ignore_rejects.count("insufficient fee")) {
|
| 1316 |
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
|
| 1317 |
// This fee-related failure is TX_RECONSIDERABLE because validating in a package may change
|
| 1318 |
// the result.
|
| 1319 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1320 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1321 |
}
|
| 1322 |
+
} // ignore_rejects
|
| 1323 |
|
| 1324 |
CTxMemPool::setEntries all_conflicts;
|
| 1325 |
|
| 1326 |
// Calculate all conflicting entries and enforce Rule #5.
|
| 1327 |
+
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, all_conflicts, args.m_ignore_rejects)}) {
|
| 1328 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1329 |
strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1330 |
}
|
| 1331 |
// Enforce Rule #2.
|
| 1332 |
+
if (!args.m_ignore_rejects.count("replacement-adds-unconfirmed")) {
|
| 1333 |
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, all_conflicts)}) {
|
| 1334 |
// Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
|
| 1335 |
Assume(!ws.m_sibling_eviction);
|
| 1336 |
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
| 1337 |
strprintf("replacement-adds-unconfirmed%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1338 |
}
|
| 1339 |
+
} // ignore_rejects
|
| 1340 |
|
| 1341 |
// Check if it's economically rational to mine this transaction rather than the ones it
|
| 1342 |
// replaces and pays for its own relay fees. Enforce Rules #3 and #4.
|
|
|
|
| 1344 |
m_subpackage.m_conflicting_fees += it->GetModifiedFee();
|
| 1345 |
m_subpackage.m_conflicting_size += it->GetTxSize();
|
| 1346 |
}
|
| 1347 |
+
if (!args.m_ignore_rejects.count("insufficient fee")) {
|
| 1348 |
if (const auto err_string{PaysForRBF(m_subpackage.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
|
| 1349 |
m_pool.m_opts.incremental_relay_feerate, hash)}) {
|
| 1350 |
// Result may change in a package context
|
| 1351 |
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
|
| 1352 |
strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
| 1353 |
}
|
| 1354 |
+
} // ignore_rejects
|
| 1355 |
|
| 1356 |
// Add all the to-be-removed transactions to the changeset.
|
| 1357 |
for (auto it : all_conflicts) {
|
|
|
|
| 1360 |
return true;
|
| 1361 |
}
|
| 1362 |
|
| 1363 |
+
bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args, const std::vector<CTransactionRef>& txns,
|
| 1364 |
std::vector<Workspace>& workspaces,
|
| 1365 |
const int64_t total_vsize,
|
| 1366 |
PackageValidationState& package_state)
|
|
|
|
| 1373 |
|
| 1374 |
assert(txns.size() == workspaces.size());
|
| 1375 |
|
| 1376 |
+
util::Result<void> result = [&]() EXCLUSIVE_LOCKS_REQUIRED(m_pool.cs) {
|
| 1377 |
+
if (args.m_ignore_rejects.count("package-mempool-limits")) {
|
| 1378 |
+
return util::Result<void>();
|
| 1379 |
+
} else {
|
| 1380 |
+
return m_pool.CheckPackageLimits(txns, total_vsize);
|
| 1381 |
+
}
|
| 1382 |
+
}();
|
| 1383 |
if (!result) {
|
| 1384 |
// This is a package-wide error, separate from an individual transaction error.
|
| 1385 |
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", util::ErrorString(result).original);
|
|
|
|
| 1465 |
return true;
|
| 1466 |
}
|
| 1467 |
|
| 1468 |
+
unsigned int PolicyScriptVerifyFlags(const ignore_rejects_type& ignore_rejects)
|
| 1469 |
+
{
|
| 1470 |
+
if (ignore_rejects.empty()) {
|
| 1471 |
+
return STANDARD_SCRIPT_VERIFY_FLAGS;
|
| 1472 |
+
}
|
| 1473 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag")) {
|
| 1474 |
+
return MANDATORY_SCRIPT_VERIFY_FLAGS;
|
| 1475 |
+
}
|
| 1476 |
+
|
| 1477 |
+
unsigned int flags = STANDARD_SCRIPT_VERIFY_FLAGS;
|
| 1478 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable")) {
|
| 1479 |
+
constexpr unsigned int upgradable_policy_flags =
|
| 1480 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
|
| 1481 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
|
| 1482 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
|
| 1483 |
+
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
|
| 1484 |
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
|
| 1485 |
+
flags &= ~upgradable_policy_flags;
|
| 1486 |
+
} else {
|
| 1487 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-nops")) {
|
| 1488 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS;
|
| 1489 |
+
}
|
| 1490 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-witness_program")) {
|
| 1491 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
|
| 1492 |
+
}
|
| 1493 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-taproot_version")) {
|
| 1494 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION;
|
| 1495 |
+
}
|
| 1496 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-op_success")) {
|
| 1497 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS;
|
| 1498 |
+
}
|
| 1499 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-pubkeytype")) {
|
| 1500 |
+
flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
|
| 1501 |
+
}
|
| 1502 |
+
}
|
| 1503 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-bip62")) {
|
| 1504 |
+
constexpr unsigned int bip62_policy_flags =
|
| 1505 |
+
SCRIPT_VERIFY_LOW_S |
|
| 1506 |
+
SCRIPT_VERIFY_SIGPUSHONLY | // NOTE: not actually set ever
|
| 1507 |
+
SCRIPT_VERIFY_MINIMALDATA;
|
| 1508 |
+
flags &= ~bip62_policy_flags;
|
| 1509 |
+
} else {
|
| 1510 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-low_s")) {
|
| 1511 |
+
flags &= ~SCRIPT_VERIFY_LOW_S;
|
| 1512 |
+
}
|
| 1513 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-minimaldata")) {
|
| 1514 |
+
flags &= ~SCRIPT_VERIFY_MINIMALDATA;
|
| 1515 |
+
}
|
| 1516 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-cleanstack")) {
|
| 1517 |
+
flags &= ~SCRIPT_VERIFY_CLEANSTACK;
|
| 1518 |
+
}
|
| 1519 |
+
}
|
| 1520 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-strictenc")) {
|
| 1521 |
+
flags &= ~SCRIPT_VERIFY_STRICTENC;
|
| 1522 |
+
}
|
| 1523 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-minimalif")) {
|
| 1524 |
+
flags &= ~SCRIPT_VERIFY_MINIMALIF;
|
| 1525 |
+
}
|
| 1526 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-nullfail")) {
|
| 1527 |
+
flags &= ~SCRIPT_VERIFY_NULLFAIL;
|
| 1528 |
+
}
|
| 1529 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-witness_pubkeytype")) {
|
| 1530 |
+
flags &= ~SCRIPT_VERIFY_WITNESS_PUBKEYTYPE;
|
| 1531 |
+
}
|
| 1532 |
+
if (ignore_rejects.count("non-mandatory-script-verify-flag-const_scriptcode")) {
|
| 1533 |
+
flags &= ~SCRIPT_VERIFY_CONST_SCRIPTCODE;
|
| 1534 |
+
}
|
| 1535 |
+
flags |= MANDATORY_SCRIPT_VERIFY_FLAGS; // for safety
|
| 1536 |
+
return flags;
|
| 1537 |
+
}
|
| 1538 |
+
|
| 1539 |
bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
|
| 1540 |
{
|
| 1541 |
AssertLockHeld(cs_main);
|
|
|
|
| 1543 |
const CTransaction& tx = *ws.m_ptx;
|
| 1544 |
TxValidationState& state = ws.m_state;
|
| 1545 |
|
| 1546 |
+
const unsigned int scriptVerifyFlags = PolicyScriptVerifyFlags(args.m_ignore_rejects);
|
| 1547 |
|
| 1548 |
// Check input scripts and signatures.
|
| 1549 |
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
|
|
|
| 1585 |
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
|
| 1586 |
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
|
| 1587 |
ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
|
| 1588 |
+
LogError("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s", hash.ToString(), state.ToString());
|
| 1589 |
return Assume(false);
|
| 1590 |
}
|
| 1591 |
|
|
|
|
| 1710 |
const CTransaction& tx = *ws.m_ptx;
|
| 1711 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1712 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1713 |
+
args.m_ignore_rejects, args.m_package_submission,
|
| 1714 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1715 |
m_pool.HasNoInputsOf(tx));
|
| 1716 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
|
|
| 1750 |
}
|
| 1751 |
}
|
| 1752 |
|
| 1753 |
+
if (m_subpackage.m_rbf && !ReplacementChecks(args, ws)) {
|
| 1754 |
if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {
|
| 1755 |
// Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
|
| 1756 |
return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);
|
|
|
|
| 1774 |
FinalizeSubpackage(args);
|
| 1775 |
|
| 1776 |
// Limit the mempool, if appropriate.
|
| 1777 |
+
if (!args.m_package_submission && !args.m_ignore_rejects.count(rejectmsg_mempoolfull)) {
|
| 1778 |
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
|
| 1779 |
// If mempool contents change, then the m_view cache is dirty. Given this isn't a package
|
| 1780 |
// submission, we won't be using the cache anymore, but clear it anyway for clarity.
|
|
|
|
| 1793 |
Assume(iter.has_value());
|
| 1794 |
const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
|
| 1795 |
ws.m_vsize, (*iter)->GetHeight(),
|
| 1796 |
+
args.m_ignore_rejects, args.m_package_submission,
|
| 1797 |
IsCurrentForFeeEstimation(m_active_chainstate),
|
| 1798 |
m_pool.HasNoInputsOf(tx));
|
| 1799 |
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
|
|
|
|
| 1860 |
|
| 1861 |
// At this point we have all in-mempool ancestors, and we know every transaction's vsize.
|
| 1862 |
// Run the TRUC checks on the package.
|
| 1863 |
+
if (m_pool.m_opts.truc_policy == TRUCPolicy::Enforce) {
|
| 1864 |
+
std::string reason;
|
| 1865 |
for (Workspace& ws : workspaces) {
|
| 1866 |
+
if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, "truc-", reason, args.m_ignore_rejects, txns, ws.m_ancestors)}) {
|
| 1867 |
+
package_state.Invalid(PackageValidationResult::PCKG_POLICY, reason, err.value());
|
| 1868 |
return PackageMempoolAcceptResult(package_state, {});
|
| 1869 |
}
|
| 1870 |
+
}}
|
| 1871 |
|
| 1872 |
// Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
|
| 1873 |
// For transactions consisting of exactly one child and its parents, it suffices to use the
|
|
|
|
| 1889 |
[](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
|
| 1890 |
TxValidationState placeholder_state;
|
| 1891 |
if (args.m_package_feerates &&
|
| 1892 |
+
(!args.m_ignore_rejects.count("package-fee-too-low")) &&
|
| 1893 |
+
!CheckFeeRate(m_subpackage.m_total_vsize, m_subpackage.m_total_modified_fees, placeholder_state, empty_ignore_rejects)) {
|
| 1894 |
package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
| 1895 |
return PackageMempoolAcceptResult(package_state, {{workspaces.back().m_ptx->GetWitnessHash(),
|
| 1896 |
MempoolAcceptResult::FeeFailure(placeholder_state, CFeeRate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize), all_package_wtxids)}});
|
|
|
|
| 1898 |
|
| 1899 |
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
|
| 1900 |
// because it's unnecessary.
|
| 1901 |
+
if (txns.size() > 1 && !PackageMempoolChecks(args, txns, workspaces, m_subpackage.m_total_vsize, package_state)) {
|
| 1902 |
return PackageMempoolAcceptResult(package_state, std::move(results));
|
| 1903 |
}
|
| 1904 |
|
| 1905 |
// Now that we've bounded the resulting possible ancestry count, check package for dust spends
|
| 1906 |
+
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"))) {
|
| 1907 |
TxValidationState child_state;
|
| 1908 |
Wtxid child_wtxid;
|
| 1909 |
if (!CheckEphemeralSpends(txns, m_pool.m_opts.dust_relay_feerate, m_pool, child_state, child_wtxid)) {
|
|
|
|
| 2153 |
} // anon namespace
|
| 2154 |
|
| 2155 |
MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
|
| 2156 |
+
int64_t accept_time, const ignore_rejects_type& ignore_rejects, bool test_accept)
|
| 2157 |
{
|
| 2158 |
AssertLockHeld(::cs_main);
|
| 2159 |
const CChainParams& chainparams{active_chainstate.m_chainman.GetParams()};
|
|
|
|
| 2161 |
CTxMemPool& pool{*active_chainstate.GetMempool()};
|
| 2162 |
|
| 2163 |
std::vector<COutPoint> coins_to_uncache;
|
| 2164 |
+
auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, ignore_rejects, coins_to_uncache, test_accept);
|
| 2165 |
MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
|
| 2166 |
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
| 2167 |
// Remove coins that were not present in the coins cache before calling
|
|
|
|
| 2183 |
}
|
| 2184 |
|
| 2185 |
PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
|
| 2186 |
+
const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate, const ignore_rejects_type& ignore_rejects)
|
| 2187 |
{
|
| 2188 |
AssertLockHeld(cs_main);
|
| 2189 |
assert(!package.empty());
|
|
|
|
| 2194 |
auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
| 2195 |
AssertLockHeld(cs_main);
|
| 2196 |
if (test_accept) {
|
| 2197 |
+
auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams, GetTime(), ignore_rejects, coins_to_uncache);
|
| 2198 |
return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
|
| 2199 |
} else {
|
| 2200 |
+
auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams, GetTime(), coins_to_uncache, client_maxfeerate, ignore_rejects);
|
| 2201 |
return MemPoolAccept(pool, active_chainstate).AcceptPackage(package, args);
|