1 // Copyright (c) 2016-2022 The Limenka 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 <policy/policy.h>
11 #include <primitives/transaction.h>
12 #include <sync.h>
13 #include <tinyformat.h>
14 #include <txmempool.h>
15 #include <uint256.h>
16 #include <util/check.h>
17 #include <util/moneystr.h>
18 #include <util/rbf.h>
19 20 #include <limits>
21 #include <vector>
22 23 #include <compare>
24 25 RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
26 {
27 AssertLockHeld(pool.cs);
28 29 // First check the transaction itself.
30 if (SignalsOptInRBF(tx)) {
31 return RBFTransactionState::REPLACEABLE_BIP125;
32 }
33 34 // If this transaction is not in our mempool, then we can't be sure
35 // we will know about all its inputs.
36 if (!pool.exists(GenTxid::Txid(tx.GetHash()))) {
37 return RBFTransactionState::UNKNOWN;
38 }
39 40 // If all the inputs have nSequence >= maxint-1, it still might be
41 // signaled for RBF if any unconfirmed parents have signaled.
42 const auto& entry{*Assert(pool.GetEntry(tx.GetHash()))};
43 auto ancestors{pool.AssumeCalculateMemPoolAncestors(__func__, entry, CTxMemPool::Limits::NoLimits(),
44 /*fSearchForParents=*/false)};
45 46 for (CTxMemPool::txiter it : ancestors) {
47 if (SignalsOptInRBF(it->GetTx())) {
48 return RBFTransactionState::REPLACEABLE_BIP125;
49 }
50 }
51 return RBFTransactionState::FINAL;
52 }
53 54 RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
55 {
56 // If we don't have a local mempool we can only check the transaction itself.
57 return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
58 }
59 60 std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
61 CTxMemPool& pool,
62 const CTxMemPool::setEntries& iters_conflicting,
63 CTxMemPool::setEntries& all_conflicts,
64 const ignore_rejects_type& ignore_rejects)
65 {
66 AssertLockHeld(pool.cs);
67 const uint256 txid = tx.GetHash();
68 uint64_t nConflictingCount = 0;
69 for (const auto& mi : iters_conflicting) {
70 nConflictingCount += mi->GetCountWithDescendants();
71 // Rule #5: don't consider replacing more than MAX_REPLACEMENT_CANDIDATES
72 // entries from the mempool. This potentially overestimates the number of actual
73 // descendants (i.e. if multiple conflicts share a descendant, it will be counted multiple
74 // times), but we just want to be conservative to avoid doing too much work.
75 if (nConflictingCount > MAX_REPLACEMENT_CANDIDATES && !ignore_rejects.count("too-many-replacements") && !ignore_rejects.count("too many potential replacements")) {
76 return strprintf("rejecting replacement %s; too many potential replacements (%d > %d)",
77 txid.ToString(),
78 nConflictingCount,
79 MAX_REPLACEMENT_CANDIDATES);
80 }
81 }
82 // Calculate the set of all transactions that would have to be evicted.
83 for (CTxMemPool::txiter it : iters_conflicting) {
84 pool.CalculateDescendants(it, all_conflicts);
85 }
86 return std::nullopt;
87 }
88 89 std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
90 const CTxMemPool& pool,
91 const CTxMemPool::setEntries& iters_conflicting)
92 {
93 AssertLockHeld(pool.cs);
94 std::set<uint256> parents_of_conflicts;
95 for (const auto& mi : iters_conflicting) {
96 for (const CTxIn& txin : mi->GetTx().vin) {
97 parents_of_conflicts.insert(txin.prevout.hash);
98 }
99 }
100 101 for (unsigned int j = 0; j < tx.vin.size(); j++) {
102 // Rule #2: We don't want to accept replacements that require low feerate junk to be
103 // mined first. Ideally we'd keep track of the ancestor feerates and make the decision
104 // based on that, but for now requiring all new inputs to be confirmed works.
105 //
106 // Note that if you relax this to make RBF a little more useful, this may break the
107 // CalculateMempoolAncestors RBF relaxation which subtracts the conflict count/size from the
108 // descendant limit.
109 if (!parents_of_conflicts.count(tx.vin[j].prevout.hash)) {
110 // Rather than check the UTXO set - potentially expensive - it's cheaper to just check
111 // if the new input refers to a tx that's in the mempool.
112 if (pool.exists(GenTxid::Txid(tx.vin[j].prevout.hash))) {
113 return strprintf("replacement %s adds unconfirmed input, idx %d",
114 tx.GetHash().ToString(), j);
115 }
116 }
117 }
118 return std::nullopt;
119 }
120 121 std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries& ancestors,
122 const std::map<Txid, bool>& direct_conflicts,
123 const uint256& txid, bool* const out_violates_policy)
124 {
125 for (CTxMemPool::txiter ancestorIt : ancestors) {
126 const Txid& hashAncestor = ancestorIt->GetTx().GetHash();
127 const auto& conflictit = direct_conflicts.find(hashAncestor);
128 if (conflictit != direct_conflicts.end()) {
129 if (!conflictit->second /* mere SPK conflict, NOT invalid */) {
130 if (out_violates_policy) *out_violates_policy = true;
131 continue;
132 }
133 return strprintf("%s spends conflicting transaction %s",
134 txid.ToString(),
135 hashAncestor.ToString());
136 }
137 }
138 return std::nullopt;
139 }
140 141 std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& iters_conflicting,
142 CFeeRate replacement_feerate,
143 const uint256& txid)
144 {
145 for (const auto& mi : iters_conflicting) {
146 // Don't allow the replacement to reduce the feerate of the mempool.
147 //
148 // We usually don't want to accept replacements with lower feerates than what they replaced
149 // as that would lower the feerate of the next block. Requiring that the feerate always be
150 // increased is also an easy-to-reason about way to prevent DoS attacks via replacements.
151 //
152 // We only consider the feerates of transactions being directly replaced, not their indirect
153 // descendants. While that does mean high feerate children are ignored when deciding whether
154 // or not to replace, we do require the replacement to pay more overall fees too, mitigating
155 // most cases.
156 CFeeRate original_feerate(mi->GetModifiedFee(), mi->GetTxSize());
157 if (replacement_feerate <= original_feerate) {
158 return strprintf("rejecting replacement %s; new feerate %s <= old feerate %s",
159 txid.ToString(),
160 replacement_feerate.ToString(),
161 original_feerate.ToString());
162 }
163 }
164 return std::nullopt;
165 }
166 167 std::optional<std::string> PaysForRBF(CAmount original_fees,
168 CAmount replacement_fees,
169 size_t replacement_vsize,
170 CFeeRate relay_fee,
171 const uint256& txid)
172 {
173 // Rule #3: The replacement fees must be greater than or equal to fees of the
174 // transactions it replaces, otherwise the bandwidth used by those conflicting transactions
175 // would not be paid for.
176 if (replacement_fees < original_fees) {
177 return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
178 txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees));
179 }
180 181 // Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
182 // vector where attackers can cause a transaction to be replaced (and relayed) repeatedly by
183 // increasing the fee by tiny amounts.
184 CAmount additional_fees = replacement_fees - original_fees;
185 if (additional_fees < relay_fee.GetFee(replacement_vsize)) {
186 return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
187 txid.ToString(),
188 FormatMoney(additional_fees),
189 FormatMoney(relay_fee.GetFee(replacement_vsize)));
190 }
191 return std::nullopt;
192 }
193 194 std::optional<std::pair<DiagramCheckError, std::string>> ImprovesFeerateDiagram(CTxMemPool::ChangeSet& changeset)
195 {
196 // Require that the replacement strictly improves the mempool's feerate diagram.
197 const auto chunk_results{changeset.CalculateChunksForRBF()};
198 199 if (!chunk_results.has_value()) {
200 return std::make_pair(DiagramCheckError::UNCALCULABLE, util::ErrorString(chunk_results).original);
201 }
202 203 if (!std::is_gt(CompareChunks(chunk_results.value().second, chunk_results.value().first))) {
204 return std::make_pair(DiagramCheckError::FAILURE, "insufficient feerate: does not improve feerate diagram");
205 }
206 return std::nullopt;
207 }
208