@@ -48,26 +48,27 @@ RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
48
48
}
49
49
50
50
std::optional<std::string> GetEntriesForConflicts (const CTransaction& tx,
51
- CTxMemPool& pool,
52
- const CTxMemPool::setEntries& iters_conflicting,
53
- CTxMemPool::setEntries& all_conflicts)
51
+ CTxMemPool& pool,
52
+ const CTxMemPool::setEntries& iters_conflicting,
53
+ CTxMemPool::setEntries& all_conflicts)
54
54
{
55
55
AssertLockHeld (pool.cs );
56
56
const uint256 txid = tx.GetHash ();
57
57
uint64_t nConflictingCount = 0 ;
58
58
for (const auto & mi : iters_conflicting) {
59
59
nConflictingCount += mi->GetCountWithDescendants ();
60
- // This potentially overestimates the number of actual descendants but we just want to be
61
- // conservative to avoid doing too much work.
60
+ // BIP125 Rule #5: don't consider replacing more than MAX_BIP125_REPLACEMENT_CANDIDATES
61
+ // entries from the mempool. This potentially overestimates the number of actual
62
+ // descendants (i.e. if multiple conflicts share a descendant, it will be counted multiple
63
+ // times), but we just want to be conservative to avoid doing too much work.
62
64
if (nConflictingCount > MAX_BIP125_REPLACEMENT_CANDIDATES) {
63
65
return strprintf (" rejecting replacement %s; too many potential replacements (%d > %d)\n " ,
64
66
txid.ToString (),
65
67
nConflictingCount,
66
68
MAX_BIP125_REPLACEMENT_CANDIDATES);
67
69
}
68
70
}
69
- // If not too many to replace, then calculate the set of
70
- // transactions that would have to be evicted
71
+ // Calculate the set of all transactions that would have to be evicted.
71
72
for (CTxMemPool::txiter it : iters_conflicting) {
72
73
pool.CalculateDescendants (it, all_conflicts);
73
74
}
@@ -81,19 +82,19 @@ std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
81
82
AssertLockHeld (pool.cs );
82
83
std::set<uint256> parents_of_conflicts;
83
84
for (const auto & mi : iters_conflicting) {
84
- for (const CTxIn & txin : mi->GetTx ().vin ) {
85
+ for (const CTxIn& txin : mi->GetTx ().vin ) {
85
86
parents_of_conflicts.insert (txin.prevout .hash );
86
87
}
87
88
}
88
89
89
90
for (unsigned int j = 0 ; j < tx.vin .size (); j++) {
90
- // We don't want to accept replacements that require low feerate junk to be mined first.
91
- // Ideally we'd keep track of the ancestor feerates and make the decision based on that, but
92
- // for now requiring all new inputs to be confirmed works.
91
+ // BIP125 Rule #2: We don't want to accept replacements that require low feerate junk to be
92
+ // mined first. Ideally we'd keep track of the ancestor feerates and make the decision
93
+ // based on that, but for now requiring all new inputs to be confirmed works.
93
94
//
94
95
// Note that if you relax this to make RBF a little more useful, this may break the
95
- // CalculateMempoolAncestors RBF relaxation, above. See the comment above the first
96
- // CalculateMempoolAncestors call for more info .
96
+ // CalculateMempoolAncestors RBF relaxation which subtracts the conflict count/size from the
97
+ // descendant limit .
97
98
if (!parents_of_conflicts.count (tx.vin [j].prevout .hash )) {
98
99
// Rather than check the UTXO set - potentially expensive - it's cheaper to just check
99
100
// if the new input refers to a tx that's in the mempool.
@@ -111,7 +112,7 @@ std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries&
111
112
const uint256& txid)
112
113
{
113
114
for (CTxMemPool::txiter ancestorIt : ancestors) {
114
- const uint256 & hashAncestor = ancestorIt->GetTx ().GetHash ();
115
+ const uint256& hashAncestor = ancestorIt->GetTx ().GetHash ();
115
116
if (direct_conflicts.count (hashAncestor)) {
116
117
return strprintf (" %s spends conflicting transaction %s" ,
117
118
txid.ToString (),
@@ -150,24 +151,26 @@ std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& i
150
151
std::optional<std::string> PaysForRBF (CAmount original_fees,
151
152
CAmount replacement_fees,
152
153
size_t replacement_vsize,
154
+ CFeeRate relay_fee,
153
155
const uint256& txid)
154
156
{
155
- // The replacement must pay greater fees than the transactions it
156
- // replaces - if we did the bandwidth used by those conflicting
157
- // transactions would not be paid for.
157
+ // BIP125 Rule #3: The replacement fees must be greater than or equal to fees of the
158
+ // transactions it replaces, otherwise the bandwidth used by those conflicting transactions
159
+ // would not be paid for.
158
160
if (replacement_fees < original_fees) {
159
161
return strprintf (" rejecting replacement %s, less fees than conflicting txs; %s < %s" ,
160
162
txid.ToString (), FormatMoney (replacement_fees), FormatMoney (original_fees));
161
163
}
162
164
163
- // Finally in addition to paying more fees than the conflicts the
164
- // new transaction must pay for its own bandwidth.
165
+ // BIP125 Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
166
+ // vector where attackers can cause a transaction to be replaced (and relayed) repeatedly by
167
+ // increasing the fee by tiny amounts.
165
168
CAmount additional_fees = replacement_fees - original_fees;
166
- if (additional_fees < ::incrementalRelayFee .GetFee (replacement_vsize)) {
169
+ if (additional_fees < relay_fee .GetFee (replacement_vsize)) {
167
170
return strprintf (" rejecting replacement %s, not enough additional fees to relay; %s < %s" ,
168
171
txid.ToString (),
169
172
FormatMoney (additional_fees),
170
- FormatMoney (::incrementalRelayFee .GetFee (replacement_vsize)));
173
+ FormatMoney (relay_fee .GetFee (replacement_vsize)));
171
174
}
172
175
return std::nullopt;
173
176
}
0 commit comments