Skip to content

Commit c9b1439

Browse files
committed
MOVEONLY: mempool checks to their own functions
No change in behavior, because package transactions would not be going through the rbf logic in PreChecks anyway (BIP125 is currently disabled for package acceptance, see ATMPArgs). We draw the line here because each individual transaction in package validation still goes through all PreChecks. For example, checking that one's own conflicts and dependencies are disjoint (a consensus check) and individual transaction mempool ancestor/descendant limits.
1 parent 9e910d8 commit c9b1439

File tree

1 file changed

+66
-37
lines changed

1 file changed

+66
-37
lines changed

src/validation.cpp

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,14 @@ class MemPoolAccept
541541
// only tests that are fast should be done here (to avoid CPU DoS).
542542
bool PreChecks(ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
543543

544+
// Run checks for mempool replace-by-fee.
545+
bool ReplacementChecks(Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
546+
547+
// Enforce package mempool ancestor/descendant limits (distinct from individual
548+
// ancestor/descendant limits done in PreChecks).
549+
bool PackageMempoolChecks(const std::vector<CTransactionRef>& txns,
550+
PackageValidationState& package_state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
551+
544552
// Run the script checks using our policy flags. As this can be slow, we should
545553
// only invoke this on transactions that have otherwise passed policy checks.
546554
bool PolicyScriptChecks(const ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
@@ -823,43 +831,67 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
823831
}
824832

825833
m_rbf = !ws.m_conflicts.empty();
826-
if (m_rbf) {
827-
CFeeRate newFeeRate(ws.m_modified_fees, ws.m_vsize);
828-
// It's possible that the replacement pays more fees than its direct conflicts but not more
829-
// than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
830-
// replacement doesn't pay more fees than its direct conflicts, then we can be sure it's not
831-
// more economically rational to mine. Before we go digging through the mempool for all
832-
// transactions that would need to be removed (direct conflicts and all descendants), check
833-
// that the replacement transaction pays more than its direct conflicts.
834-
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
835-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
836-
}
834+
return true;
835+
}
837836

838-
// Calculate all conflicting entries and enforce BIP125 Rule #5.
839-
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, ws.m_all_conflicting)}) {
840-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
841-
"too many potential replacements", *err_string);
842-
}
843-
// Enforce BIP125 Rule #2.
844-
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, ws.m_iters_conflicting)}) {
845-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
846-
"replacement-adds-unconfirmed", *err_string);
847-
}
837+
bool MemPoolAccept::ReplacementChecks(Workspace& ws)
838+
{
839+
AssertLockHeld(cs_main);
840+
AssertLockHeld(m_pool.cs);
848841

849-
// Check if it's economically rational to mine this transaction rather than the ones it
850-
// replaces and pays for its own relay fees. Enforce BIP125 Rules #3 and #4.
851-
for (CTxMemPool::txiter it : ws.m_all_conflicting) {
852-
ws.m_conflicting_fees += it->GetModifiedFee();
853-
ws.m_conflicting_size += it->GetTxSize();
854-
}
855-
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
856-
::incrementalRelayFee, hash)}) {
857-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
858-
}
842+
const CTransaction& tx = *ws.m_ptx;
843+
const uint256& hash = ws.m_hash;
844+
TxValidationState& state = ws.m_state;
845+
846+
CFeeRate newFeeRate(ws.m_modified_fees, ws.m_vsize);
847+
// It's possible that the replacement pays more fees than its direct conflicts but not more
848+
// than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
849+
// replacement doesn't pay more fees than its direct conflicts, then we can be sure it's not
850+
// more economically rational to mine. Before we go digging through the mempool for all
851+
// transactions that would need to be removed (direct conflicts and all descendants), check
852+
// that the replacement transaction pays more than its direct conflicts.
853+
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
854+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
855+
}
856+
857+
// Calculate all conflicting entries and enforce BIP125 Rule #5.
858+
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, ws.m_all_conflicting)}) {
859+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
860+
"too many potential replacements", *err_string);
861+
}
862+
// Enforce BIP125 Rule #2.
863+
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, ws.m_iters_conflicting)}) {
864+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
865+
"replacement-adds-unconfirmed", *err_string);
866+
}
867+
// Check if it's economically rational to mine this transaction rather than the ones it
868+
// replaces and pays for its own relay fees. Enforce BIP125 Rules #3 and #4.
869+
for (CTxMemPool::txiter it : ws.m_all_conflicting) {
870+
ws.m_conflicting_fees += it->GetModifiedFee();
871+
ws.m_conflicting_size += it->GetTxSize();
872+
}
873+
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
874+
::incrementalRelayFee, hash)}) {
875+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
859876
}
860877
return true;
861878
}
862879

880+
bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txns,
881+
PackageValidationState& package_state)
882+
{
883+
AssertLockHeld(cs_main);
884+
AssertLockHeld(m_pool.cs);
885+
886+
std::string err_string;
887+
if (!m_pool.CheckPackageLimits(txns, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants,
888+
m_limit_descendant_size, err_string)) {
889+
// This is a package-wide error, separate from an individual transaction error.
890+
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", err_string);
891+
}
892+
return true;
893+
}
894+
863895
bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
864896
{
865897
const CTransaction& tx = *ws.m_ptx;
@@ -966,6 +998,8 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
966998

967999
if (!PreChecks(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
9681000

1001+
if (m_rbf && !ReplacementChecks(ws)) return MempoolAcceptResult::Failure(ws.m_state);
1002+
9691003
// Perform the inexpensive checks first and avoid hashing and signature verification unless
9701004
// those checks pass, to mitigate CPU exhaustion denial-of-service attacks.
9711005
if (!PolicyScriptChecks(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
@@ -1020,12 +1054,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
10201054
// because it's unnecessary. Also, CPFP carve out can increase the limit for individual
10211055
// transactions, but this exemption is not extended to packages in CheckPackageLimits().
10221056
std::string err_string;
1023-
if (txns.size() > 1 &&
1024-
!m_pool.CheckPackageLimits(txns, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants,
1025-
m_limit_descendant_size, err_string)) {
1026-
// All transactions must have individually passed mempool ancestor and descendant limits
1027-
// inside of PreChecks(), so this is separate from an individual transaction error.
1028-
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", err_string);
1057+
if (txns.size() > 1 && !PackageMempoolChecks(txns, package_state)) {
10291058
return PackageMempoolAcceptResult(package_state, std::move(results));
10301059
}
10311060

0 commit comments

Comments
 (0)