Bitcoin Core  31.0.0
P2P Digital Currency
rbf.cpp
Go to the documentation of this file.
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 
25 {
26  AssertLockHeld(pool.cs);
27 
28  // First check the transaction itself.
29  if (SignalsOptInRBF(tx)) {
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())) {
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())) {
47  }
48  }
50 }
51 
53 {
54  // If we don't have a local mempool we can only check the transaction itself.
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,
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 }
AssertLockHeld(pool.cs)
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
Definition: txmempool.h:265
std::optional< std::string > EntriesAndTxidsDisjoint(const CTxMemPool::setEntries &ancestors, const std::set< Txid > &direct_conflicts, const Txid &txid)
Check the intersection between two sets of transactions (a set of mempool entries and a set of txids)...
Definition: rbf.cpp:85
RBFTransactionState IsRBFOptIn(const CTransaction &tx, const CTxMemPool &pool)
Determine whether an unconfirmed transaction is signaling opt-in to RBF according to BIP 125 This inv...
Definition: rbf.cpp:24
static constexpr uint32_t MAX_REPLACEMENT_CANDIDATES
Maximum number of unique clusters that can be affected by an RBF (Rule #5); see GetEntriesForConflict...
Definition: rbf.h:26
Either this tx or a mempool ancestor signals rbf.
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
Unconfirmed tx that does not signal rbf and is not in the mempool.
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of given transaction.
Definition: txmempool.cpp:309
std::set< txiter, CompareIteratorByHash > setEntries
Definition: txmempool.h:268
bool SignalsOptInRBF(const CTransaction &tx)
Check whether the sequence numbers on this transaction are signaling opt-in to replace-by-fee, according to BIP 125.
Definition: rbf.cpp:9
Unable to calculate due to topology or other reason.
RBFTransactionState
The rbf state of unconfirmed transactions.
Definition: rbf.h:29
size_t GetUniqueClusterCount(const setEntries &iters_conflicting) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:413
std::optional< std::string > GetEntriesForConflicts(const CTransaction &tx, CTxMemPool &pool, const CTxMemPool::setEntries &iters_conflicting, CTxMemPool::setEntries &all_conflicts)
Get all descendants of iters_conflicting.
Definition: rbf.cpp:58
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
std::partial_ordering CompareChunks(std::span< const FeeFrac > chunks0, std::span< const FeeFrac > chunks1)
Compare the feerate diagrams implied by the provided sorted chunks data.
Definition: feefrac.cpp:10
util::Result< std::pair< std::vector< FeeFrac >, std::vector< FeeFrac > > > CalculateChunksForRBF()
Calculate the sorted chunks for the old and new mempool relating to the clusters that would be affect...
Definition: txmempool.cpp:994
std::optional< std::string > PaysForRBF(CAmount original_fees, CAmount replacement_fees, size_t replacement_vsize, CFeeRate relay_fee, const Txid &txid)
The replacement transaction must pay more fees than the original transactions.
Definition: rbf.cpp:100
RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction &tx)
Definition: rbf.cpp:52
setEntries CalculateMemPoolAncestors(const CTxMemPoolEntry &entry) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Calculate all in-mempool ancestors of entry (not including the tx itself)
Definition: txmempool.cpp:130
std::string ToString() const
bool exists(const Txid &txid) const
Definition: txmempool.h:503
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
Definition: moneystr.cpp:19
const CTxMemPoolEntry * GetEntry(const Txid &txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:614
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:186
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac...
Definition: feerate.h:31
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:280
std::optional< std::pair< DiagramCheckError, std::string > > ImprovesFeerateDiagram(CTxMemPool::ChangeSet &changeset)
The replacement transaction must improve the feerate diagram of the mempool.
Definition: rbf.cpp:127
CAmount GetFee(int32_t virtual_bytes) const
Return the fee in satoshis for the given vsize in vbytes.
Definition: feerate.cpp:20
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
Definition: txmempool.h:260
#define Assert(val)
Identity function.
Definition: check.h:113
const Txid & GetHash() const LIFETIMEBOUND
Definition: transaction.h:328
Neither this tx nor a mempool ancestor signals rbf.
New diagram wasn&#39;t strictly superior.