LCOV - code coverage report
Current view: top level - src/policy - rbf.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 83.8 % 74 62
Test Date: 2024-11-04 04:45:35 Functions: 75.0 % 8 6
Branches: 61.9 % 84 52

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

Generated by: LCOV version 2.0-1