Do not allow mempool clusters to exceed configured limits

Include an adjustment to mempool_tests.cpp due to the additional memory used by
txgraph.

Includes a temporary change to the mempool_ephemeral_dust.py functional test,
due to validation checks being reordered. This change will revert once the RBF
rules are changed in a later commit.
This commit is contained in:
Suhas Daftuar
2023-09-21 08:58:04 -04:00
parent edb3e7cdf6
commit 95762e6759
6 changed files with 83 additions and 14 deletions

View File

@@ -1126,6 +1126,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
}
// Enforce Rule #2.
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, all_conflicts)}) {
// Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
@@ -1460,13 +1461,6 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransactionInternal(const CTransa
return MempoolAcceptResult::Failure(ws.m_state);
}
if (m_pool.m_opts.require_standard) {
Wtxid dummy_wtxid;
if (!CheckEphemeralSpends(/*package=*/{ptx}, m_pool.m_opts.dust_relay_feerate, m_pool, ws.m_state, dummy_wtxid)) {
return MempoolAcceptResult::Failure(ws.m_state);
}
}
if (m_subpackage.m_rbf && !ReplacementChecks(ws)) {
if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {
// Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
@@ -1475,6 +1469,19 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransactionInternal(const CTransa
return MempoolAcceptResult::Failure(ws.m_state);
}
// Check if the transaction would exceed the cluster size limit.
if (!m_subpackage.m_changeset->CheckMemPoolPolicyLimits()) {
ws.m_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-large-cluster", "");
return MempoolAcceptResult::Failure(ws.m_state);
}
if (m_pool.m_opts.require_standard) {
Wtxid dummy_wtxid;
if (!CheckEphemeralSpends(/*package=*/{ptx}, m_pool.m_opts.dust_relay_feerate, m_pool, ws.m_state, dummy_wtxid)) {
return MempoolAcceptResult::Failure(ws.m_state);
}
}
// Perform the inexpensive checks first and avoid hashing and signature verification unless
// those checks pass, to mitigate CPU exhaustion denial-of-service attacks.
if (!PolicyScriptChecks(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
@@ -1615,6 +1622,12 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactionsInternal(con
return PackageMempoolAcceptResult(package_state, std::move(results));
}
// Check if the transactions would exceed the cluster size limit.
if (!m_subpackage.m_changeset->CheckMemPoolPolicyLimits()) {
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "too-large-cluster", "");
return PackageMempoolAcceptResult(package_state, std::move(results));
}
// Now that we've bounded the resulting possible ancestry count, check package for dust spends
if (m_pool.m_opts.require_standard) {
TxValidationState child_state;