aboutsummaryrefslogtreecommitdiff
path: root/src/policy
diff options
context:
space:
mode:
authorGreg Sanders <gsanders87@gmail.com>2024-01-19 15:20:33 -0500
committerGreg Sanders <gsanders87@gmail.com>2024-03-18 10:32:00 -0400
commit2079b80854e2595f6f696e7c13a56c7f2a7da9f4 (patch)
treeab42fae71ea1aa30bccdc9598aa02284a3f93d98 /src/policy
parent66d966dcfaad3638f84654e710f403cb0a0a2ac7 (diff)
downloadbitcoin-2079b80854e2595f6f696e7c13a56c7f2a7da9f4.tar.xz
Implement ImprovesFeerateDiagram
This new function takes the populated sets of direct and all conflicts computed in the current mempool, assuming the replacements are a single chunk, and computes a diagram check. The diagram check only works against cluster sizes of 2 or less, and fails if it encounters a different topology. Co-authored-by: Suhas Daftuar <sdaftuar@chaincode.com>
Diffstat (limited to 'src/policy')
-rw-r--r--src/policy/rbf.cpp23
-rw-r--r--src/policy/rbf.h26
2 files changed, 49 insertions, 0 deletions
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index f0830d8f22..a2c6990657 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -19,6 +19,8 @@
#include <limits>
#include <vector>
+#include <compare>
+
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
{
AssertLockHeld(pool.cs);
@@ -181,3 +183,24 @@ std::optional<std::string> PaysForRBF(CAmount original_fees,
}
return std::nullopt;
}
+
+std::optional<std::pair<DiagramCheckError, std::string>> ImprovesFeerateDiagram(CTxMemPool& pool,
+ const CTxMemPool::setEntries& direct_conflicts,
+ const CTxMemPool::setEntries& all_conflicts,
+ CAmount replacement_fees,
+ int64_t replacement_vsize)
+{
+ // Require that the replacement strictly improve the mempool's feerate diagram.
+ std::vector<FeeFrac> old_diagram, new_diagram;
+
+ const auto diagram_results{pool.CalculateFeerateDiagramsForRBF(replacement_fees, replacement_vsize, direct_conflicts, all_conflicts)};
+
+ if (!diagram_results.has_value()) {
+ return std::make_pair(DiagramCheckError::UNCALCULABLE, util::ErrorString(diagram_results).original);
+ }
+
+ if (!std::is_gt(CompareFeerateDiagram(diagram_results.value().second, diagram_results.value().first))) {
+ return std::make_pair(DiagramCheckError::FAILURE, "insufficient feerate: does not improve feerate diagram");
+ }
+ return std::nullopt;
+}
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index 5a33ed64a3..252fbec8e3 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -9,7 +9,9 @@
#include <primitives/transaction.h>
#include <threadsafety.h>
#include <txmempool.h>
+#include <util/feefrac.h>
+#include <compare>
#include <cstddef>
#include <cstdint>
#include <optional>
@@ -33,6 +35,13 @@ enum class RBFTransactionState {
FINAL,
};
+enum class DiagramCheckError {
+ /** Unable to calculate due to topology or other reason */
+ UNCALCULABLE,
+ /** New diagram wasn't strictly superior */
+ FAILURE,
+};
+
/**
* Determine whether an unconfirmed transaction is signaling opt-in to RBF
* according to BIP 125
@@ -106,4 +115,21 @@ std::optional<std::string> PaysForRBF(CAmount original_fees,
CFeeRate relay_fee,
const uint256& txid);
+/**
+ * The replacement transaction must improve the feerate diagram of the mempool.
+ * @param[in] pool The mempool.
+ * @param[in] direct_conflicts Set of in-mempool txids corresponding to the direct conflicts i.e.
+ * input double-spends with the proposed transaction
+ * @param[in] all_conflicts Set of mempool entries corresponding to all transactions to be evicted
+ * @param[in] replacement_fees Fees of proposed replacement package
+ * @param[in] replacement_vsize Size of proposed replacement package
+ * @returns error type and string if mempool diagram doesn't improve, otherwise std::nullopt.
+ */
+std::optional<std::pair<DiagramCheckError, std::string>> ImprovesFeerateDiagram(CTxMemPool& pool,
+ const CTxMemPool::setEntries& direct_conflicts,
+ const CTxMemPool::setEntries& all_conflicts,
+ CAmount replacement_fees,
+ int64_t replacement_vsize)
+ EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
+
#endif // BITCOIN_POLICY_RBF_H