aboutsummaryrefslogtreecommitdiff
path: root/src/policy/rbf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/policy/rbf.cpp')
-rw-r--r--src/policy/rbf.cpp32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index 95b74123c9..5d1db6b58d 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -129,3 +129,35 @@ std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries&
}
return std::nullopt;
}
+
+std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& setIterConflicting,
+ CFeeRate newFeeRate,
+ const uint256& hash)
+{
+ for (const auto& mi : setIterConflicting) {
+ // Don't allow the replacement to reduce the feerate of the
+ // mempool.
+ //
+ // We usually don't want to accept replacements with lower
+ // feerates than what they replaced as that would lower the
+ // feerate of the next block. Requiring that the feerate always
+ // be increased is also an easy-to-reason about way to prevent
+ // DoS attacks via replacements.
+ //
+ // We only consider the feerates of transactions being directly
+ // replaced, not their indirect descendants. While that does
+ // mean high feerate children are ignored when deciding whether
+ // or not to replace, we do require the replacement to pay more
+ // overall fees too, mitigating most cases.
+ CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
+ if (newFeeRate <= oldFeeRate)
+ {
+ return strprintf("rejecting replacement %s; new feerate %s <= old feerate %s",
+ hash.ToString(),
+ newFeeRate.ToString(),
+ oldFeeRate.ToString());
+ }
+ }
+ return std::nullopt;
+}
+