rbf.cpp
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 }