LCOV - code coverage report
Current view: top level - src/policy - rbf.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 49 77 63.6 %
Date: 2023-09-26 12:08:55 Functions: 8 10 80.0 %

          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/moneystr.h>
      16             : #include <util/rbf.h>
      17           2 : 
      18           2 : #include <limits>
      19             : #include <vector>
      20             : 
      21           0 : RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
      22             : {
      23           0 :     AssertLockHeld(pool.cs);
      24             : 
      25             :     // First check the transaction itself.
      26           0 :     if (SignalsOptInRBF(tx)) {
      27           0 :         return RBFTransactionState::REPLACEABLE_BIP125;
      28             :     }
      29             : 
      30             :     // If this transaction is not in our mempool, then we can't be sure
      31             :     // we will know about all its inputs.
      32           0 :     if (!pool.exists(GenTxid::Txid(tx.GetHash()))) {
      33           0 :         return RBFTransactionState::UNKNOWN;
      34             :     }
      35             : 
      36             :     // If all the inputs have nSequence >= maxint-1, it still might be
      37             :     // signaled for RBF if any unconfirmed parents have signaled.
      38           0 :     const CTxMemPoolEntry entry{*pool.mapTx.find(tx.GetHash())};
      39           0 :     auto ancestors{pool.AssumeCalculateMemPoolAncestors(__func__, entry, CTxMemPool::Limits::NoLimits(),
      40             :                                                         /*fSearchForParents=*/false)};
      41             : 
      42           0 :     for (CTxMemPool::txiter it : ancestors) {
      43           0 :         if (SignalsOptInRBF(it->GetTx())) {
      44           0 :             return RBFTransactionState::REPLACEABLE_BIP125;
      45             :         }
      46             :     }
      47           0 :     return RBFTransactionState::FINAL;
      48           0 : }
      49             : 
      50           0 : RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
      51             : {
      52             :     // If we don't have a local mempool we can only check the transaction itself.
      53           0 :     return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
      54             : }
      55             : 
      56           9 : std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
      57             :                                                   CTxMemPool& pool,
      58             :                                                   const CTxMemPool::setEntries& iters_conflicting,
      59             :                                                   CTxMemPool::setEntries& all_conflicts)
      60             : {
      61           9 :     AssertLockHeld(pool.cs);
      62           9 :     const uint256 txid = tx.GetHash();
      63           9 :     uint64_t nConflictingCount = 0;
      64          18 :     for (const auto& mi : iters_conflicting) {
      65           9 :         nConflictingCount += mi->GetCountWithDescendants();
      66             :         // Rule #5: don't consider replacing more than MAX_REPLACEMENT_CANDIDATES
      67             :         // entries from the mempool. This potentially overestimates the number of actual
      68             :         // descendants (i.e. if multiple conflicts share a descendant, it will be counted multiple
      69             :         // times), but we just want to be conservative to avoid doing too much work.
      70           9 :         if (nConflictingCount > MAX_REPLACEMENT_CANDIDATES) {
      71           0 :             return strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
      72           0 :                              txid.ToString(),
      73             :                              nConflictingCount,
      74           2 :                              MAX_REPLACEMENT_CANDIDATES);
      75             :         }
      76             :     }
      77             :     // Calculate the set of all transactions that would have to be evicted.
      78          18 :     for (CTxMemPool::txiter it : iters_conflicting) {
      79           9 :         pool.CalculateDescendants(it, all_conflicts);
      80             :     }
      81           9 :     return std::nullopt;
      82           9 : }
      83             : 
      84           9 : std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
      85             :                                                const CTxMemPool& pool,
      86             :                                                const CTxMemPool::setEntries& iters_conflicting)
      87             : {
      88           9 :     AssertLockHeld(pool.cs);
      89           9 :     std::set<uint256> parents_of_conflicts;
      90          18 :     for (const auto& mi : iters_conflicting) {
      91          27 :         for (const CTxIn& txin : mi->GetTx().vin) {
      92          18 :             parents_of_conflicts.insert(txin.prevout.hash);
      93             :         }
      94             :     }
      95             : 
      96          26 :     for (unsigned int j = 0; j < tx.vin.size(); j++) {
      97             :         // Rule #2: We don't want to accept replacements that require low feerate junk to be
      98             :         // mined first.  Ideally we'd keep track of the ancestor feerates and make the decision
      99             :         // based on that, but for now requiring all new inputs to be confirmed works.
     100             :         //
     101             :         // Note that if you relax this to make RBF a little more useful, this may break the
     102             :         // CalculateMempoolAncestors RBF relaxation which subtracts the conflict count/size from the
     103             :         // descendant limit.
     104          17 :         if (!parents_of_conflicts.count(tx.vin[j].prevout.hash)) {
     105             :             // Rather than check the UTXO set - potentially expensive - it's cheaper to just check
     106             :             // if the new input refers to a tx that's in the mempool.
     107           5 :             if (pool.exists(GenTxid::Txid(tx.vin[j].prevout.hash))) {
     108           0 :                 return strprintf("replacement %s adds unconfirmed input, idx %d",
     109           0 :                                  tx.GetHash().ToString(), j);
     110             :             }
     111           5 :         }
     112          17 :     }
     113           9 :     return std::nullopt;
     114           9 : }
     115             : 
     116        3820 : std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries& ancestors,
     117             :                                                    const std::set<uint256>& direct_conflicts,
     118             :                                                    const uint256& txid)
     119             : {
     120        4303 :     for (CTxMemPool::txiter ancestorIt : ancestors) {
     121         483 :         const uint256& hashAncestor = ancestorIt->GetTx().GetHash();
     122         483 :         if (direct_conflicts.count(hashAncestor)) {
     123           0 :             return strprintf("%s spends conflicting transaction %s",
     124           0 :                              txid.ToString(),
     125           0 :                              hashAncestor.ToString());
     126             :         }
     127             :     }
     128        3820 :     return std::nullopt;
     129        3820 : }
     130             : 
     131         132 : std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& iters_conflicting,
     132             :                                                  CFeeRate replacement_feerate,
     133             :                                                  const uint256& txid)
     134             : {
     135         141 :     for (const auto& mi : iters_conflicting) {
     136             :         // Don't allow the replacement to reduce the feerate of the mempool.
     137             :         //
     138             :         // We usually don't want to accept replacements with lower feerates than what they replaced
     139             :         // as that would lower the feerate of the next block. Requiring that the feerate always be
     140             :         // increased is also an easy-to-reason about way to prevent DoS attacks via replacements.
     141             :         //
     142             :         // We only consider the feerates of transactions being directly replaced, not their indirect
     143             :         // descendants. While that does mean high feerate children are ignored when deciding whether
     144             :         // or not to replace, we do require the replacement to pay more overall fees too, mitigating
     145             :         // most cases.
     146         132 :         CFeeRate original_feerate(mi->GetModifiedFee(), mi->GetTxSize());
     147         132 :         if (replacement_feerate <= original_feerate) {
     148         123 :             return strprintf("rejecting replacement %s; new feerate %s <= old feerate %s",
     149         123 :                              txid.ToString(),
     150         123 :                              replacement_feerate.ToString(),
     151         123 :                              original_feerate.ToString());
     152             :         }
     153             :     }
     154           9 :     return std::nullopt;
     155         132 : }
     156             : 
     157           9 : std::optional<std::string> PaysForRBF(CAmount original_fees,
     158             :                                       CAmount replacement_fees,
     159             :                                       size_t replacement_vsize,
     160             :                                       CFeeRate relay_fee,
     161             :                                       const uint256& txid)
     162             : {
     163             :     // Rule #3: The replacement fees must be greater than or equal to fees of the
     164             :     // transactions it replaces, otherwise the bandwidth used by those conflicting transactions
     165             :     // would not be paid for.
     166           9 :     if (replacement_fees < original_fees) {
     167           0 :         return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
     168           0 :                          txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees));
     169             :     }
     170             : 
     171             :     // Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
     172             :     // vector where attackers can cause a transaction to be replaced (and relayed) repeatedly by
     173             :     // increasing the fee by tiny amounts.
     174           9 :     CAmount additional_fees = replacement_fees - original_fees;
     175           9 :     if (additional_fees < relay_fee.GetFee(replacement_vsize)) {
     176           0 :         return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
     177           0 :                          txid.ToString(),
     178           0 :                          FormatMoney(additional_fees),
     179           0 :                          FormatMoney(relay_fee.GetFee(replacement_vsize)));
     180             :     }
     181           9 :     return std::nullopt;
     182           9 : }

Generated by: LCOV version 1.14