Branch data Line data Source code
1 : : // Copyright (c) 2016-2022 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 : 9350 : RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
25 : : {
26 : 9350 : AssertLockHeld(pool.cs);
27 : :
28 : : // First check the transaction itself.
29 [ + + ]: 9350 : 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 [ + + ]: 1527 : 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 [ - + ]: 1315 : const auto& entry{*Assert(pool.GetEntry(tx.GetHash()))};
42 : 1315 : auto ancestors{pool.CalculateMemPoolAncestors(entry)};
43 : :
44 [ + + ]: 1327 : for (CTxMemPool::txiter it : ancestors) {
45 [ + - + + ]: 14 : if (SignalsOptInRBF(it->GetTx())) {
46 : : return RBFTransactionState::REPLACEABLE_BIP125;
47 : : }
48 : : }
49 : : return RBFTransactionState::FINAL;
50 : 1315 : }
51 : :
52 : 0 : RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
53 : : {
54 : : // If we don't have a local mempool we can only check the transaction itself.
55 [ # # ]: 0 : return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
56 : : }
57 : :
58 : 1329 : std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
59 : : CTxMemPool& pool,
60 : : const CTxMemPool::setEntries& iters_conflicting,
61 : : CTxMemPool::setEntries& all_conflicts)
62 : : {
63 : 1329 : 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 : 1329 : auto num_clusters = pool.GetUniqueClusterCount(iters_conflicting);
70 [ + + ]: 1329 : if (num_clusters > MAX_REPLACEMENT_CANDIDATES) {
71 : 5 : return strprintf("rejecting replacement %s; too many conflicting clusters (%u > %d)",
72 [ + - ]: 10 : tx.GetHash().ToString(),
73 : : num_clusters,
74 : 5 : MAX_REPLACEMENT_CANDIDATES);
75 : : }
76 : : // Calculate the set of all transactions that would have to be evicted.
77 [ + + ]: 3403 : 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 : 2079 : pool.CalculateDescendants(it, all_conflicts);
81 : : }
82 : 1324 : return std::nullopt;
83 : : }
84 : :
85 : 1259 : std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries& ancestors,
86 : : const std::set<Txid>& direct_conflicts,
87 : : const Txid& txid)
88 : : {
89 [ + + ]: 1738 : for (CTxMemPool::txiter ancestorIt : ancestors) {
90 : 487 : const Txid& hashAncestor = ancestorIt->GetTx().GetHash();
91 [ + + ]: 487 : if (direct_conflicts.count(hashAncestor)) {
92 : 16 : return strprintf("%s spends conflicting transaction %s",
93 [ + - ]: 16 : txid.ToString(),
94 [ + - ]: 24 : hashAncestor.ToString());
95 : : }
96 : : }
97 : 1251 : return std::nullopt;
98 : : }
99 : :
100 : 1330 : 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 [ + + ]: 1330 : if (replacement_fees < original_fees) {
110 : 29 : return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
111 [ + - + - ]: 116 : 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 : 1301 : CAmount additional_fees = replacement_fees - original_fees;
118 [ + + ]: 1301 : if (additional_fees < relay_fee.GetFee(replacement_vsize)) {
119 : 18 : return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
120 [ + - ]: 36 : txid.ToString(),
121 [ + - ]: 36 : FormatMoney(additional_fees),
122 : 54 : FormatMoney(relay_fee.GetFee(replacement_vsize)));
123 : : }
124 : 1283 : return std::nullopt;
125 : : }
126 : :
127 : 1273 : 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 : 1273 : const auto chunk_results{changeset.CalculateChunksForRBF()};
131 : :
132 [ - + ]: 1273 : if (!chunk_results.has_value()) {
133 [ # # ]: 0 : return std::make_pair(DiagramCheckError::UNCALCULABLE, util::ErrorString(chunk_results).original);
134 : : }
135 : :
136 [ - + - + : 1273 : if (!std::is_gt(CompareChunks(chunk_results.value().second, chunk_results.value().first))) {
+ - + + ]
137 [ + - ]: 7 : return std::make_pair(DiagramCheckError::FAILURE, "insufficient feerate: does not improve feerate diagram");
138 : : }
139 : 1266 : return std::nullopt;
140 : 1273 : }
|