| 149 | } |
| 150 | |
| 151 | std::optional<std::string> PaysForRBF(CAmount original_fees, |
| 152 | CAmount replacement_fees, |
| 153 | size_t replacement_vsize, |
| 154 | CFeeRate relay_fee, |
| 155 | const uint256& txid) |
| 156 | { |
| 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. |
| 160 | if (replacement_fees < original_fees) { |
| 161 | return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s", |
| 162 | txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees)); |
| 163 | } |
| 164 | |
| 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. |
| 168 | CAmount additional_fees = replacement_fees - original_fees; |
| 169 | if (additional_fees < relay_fee.GetFee(replacement_vsize)) { |
| 170 | return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s", |
| 171 | txid.ToString(), |
| 172 | FormatMoney(additional_fees), |
| 173 | FormatMoney(relay_fee.GetFee(replacement_vsize))); |
| 174 | } |
| 175 | return std::nullopt; |
| 176 | } |
no test coverage detected