1 // Copyright (c) 2016-present The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 5 #include <policy/rbf.h>
6 7 #include <consensus/amount.h>
8 #include <kernel/mempool_entry.h>
9 #include <policy/feerate.h>
10 #include <primitives/transaction.h>
11 #include <sync.h>
12 #include <tinyformat.h>
13 #include <txmempool.h>
14 #include <uint256.h>
15 #include <util/check.h>
16 #include <util/moneystr.h>
17 #include <util/rbf.h>
18 19 #include <limits>
20 #include <vector>
21 22 #include <compare>
23 24 RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
25 {
26 AssertLockHeld(pool.cs);
27 28 // First check the transaction itself.
29 if (SignalsOptInRBF(tx)) {
30 return RBFTransactionState::REPLACEABLE_BIP125;
31 }
32 33 // If this transaction is not in our mempool, then we can't be sure
34 // we will know about all its inputs.
35 if (!pool.exists(tx.GetHash())) {
36 return RBFTransactionState::UNKNOWN;
37 }
38 39 // If all the inputs have nSequence >= maxint-1, it still might be
40 // signaled for RBF if any unconfirmed parents have signaled.
41 const auto& entry{*Assert(pool.GetEntry(tx.GetHash()))};
42 auto ancestors{pool.CalculateMemPoolAncestors(entry)};
43 44 for (CTxMemPool::txiter it : ancestors) {
45 if (SignalsOptInRBF(it->GetTx())) {
46 return RBFTransactionState::REPLACEABLE_BIP125;
47 }
48 }
49 return RBFTransactionState::FINAL;
50 }
51 52 RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
53 {
54 // If we don't have a local mempool we can only check the transaction itself.
55 return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
56 }
57 58 std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
59 CTxMemPool& pool,
60 const CTxMemPool::setEntries& iters_conflicting,
61 CTxMemPool::setEntries& all_conflicts)
62 {
63 AssertLockHeld(pool.cs);
64 // Rule #5: don't consider replacements that conflict directly with more
65 // than MAX_REPLACEMENT_CANDIDATES distinct clusters. This implies a bound
66 // on how many mempool clusters might need to be re-sorted in order to
67 // process the replacement (though the actual number of clusters we
68 // relinearize may be greater than this number, due to cluster splitting).
69 auto num_clusters = pool.GetUniqueClusterCount(iters_conflicting);
70 if (num_clusters > MAX_REPLACEMENT_CANDIDATES) {
71 return strprintf("rejecting replacement %s; too many conflicting clusters (%u > %d)",
72 tx.GetHash().ToString(),
73 num_clusters,
74 MAX_REPLACEMENT_CANDIDATES);
75 }
76 // Calculate the set of all transactions that would have to be evicted.
77 for (CTxMemPool::txiter it : iters_conflicting) {
78 // The cluster count limit ensures that we won't do too much work on a
79 // single invocation of this function.
80 pool.CalculateDescendants(it, all_conflicts);
81 }
82 return std::nullopt;
83 }
84 85 std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries& ancestors,
86 const std::set<Txid>& direct_conflicts,
87 const Txid& txid)
88 {
89 for (CTxMemPool::txiter ancestorIt : ancestors) {
90 const Txid& hashAncestor = ancestorIt->GetTx().GetHash();
91 if (direct_conflicts.contains(hashAncestor)) {
92 return strprintf("%s spends conflicting transaction %s",
93 txid.ToString(),
94 hashAncestor.ToString());
95 }
96 }
97 return std::nullopt;
98 }
99 100 std::optional<std::string> PaysForRBF(CAmount original_fees,
101 CAmount replacement_fees,
102 size_t replacement_vsize,
103 CFeeRate relay_fee,
104 const Txid& txid)
105 {
106 // Rule #3: The replacement fees must be greater than or equal to fees of the
107 // transactions it replaces, otherwise the bandwidth used by those conflicting transactions
108 // would not be paid for.
109 if (replacement_fees < original_fees) {
110 return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
111 txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees));
112 }
113 114 // Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
115 // vector where attackers can cause a transaction to be replaced (and relayed) repeatedly by
116 // increasing the fee by tiny amounts.
117 CAmount additional_fees = replacement_fees - original_fees;
118 if (additional_fees < relay_fee.GetFee(replacement_vsize)) {
119 return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
120 txid.ToString(),
121 FormatMoney(additional_fees),
122 FormatMoney(relay_fee.GetFee(replacement_vsize)));
123 }
124 return std::nullopt;
125 }
126 127 std::optional<std::pair<DiagramCheckError, std::string>> ImprovesFeerateDiagram(CTxMemPool::ChangeSet& changeset)
128 {
129 // Require that the replacement strictly improves the mempool's feerate diagram.
130 const auto chunk_results{changeset.CalculateChunksForRBF()};
131 132 if (!chunk_results.has_value()) {
133 return std::make_pair(DiagramCheckError::UNCALCULABLE, util::ErrorString(chunk_results).original);
134 }
135 136 if (!std::is_gt(CompareChunks(chunk_results.value().second, chunk_results.value().first))) {
137 return std::make_pair(DiagramCheckError::FAILURE, "insufficient feerate: does not improve feerate diagram");
138 }
139 return std::nullopt;
140 }
141