LCOV - code coverage report
Current view: top level - src/policy - rbf.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 93 96 96.9 %
Date: 2022-04-21 14:51:19 Functions: 6 7 85.7 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 36 38 94.7 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2016-2021 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 <policy/settings.h>
#       8                 :            : #include <tinyformat.h>
#       9                 :            : #include <util/moneystr.h>
#      10                 :            : #include <util/rbf.h>
#      11                 :            : 
#      12                 :            : RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
#      13                 :       2377 : {
#      14                 :       2377 :     AssertLockHeld(pool.cs);
#      15                 :            : 
#      16                 :       2377 :     CTxMemPool::setEntries ancestors;
#      17                 :            : 
#      18                 :            :     // First check the transaction itself.
#      19         [ +  + ]:       2377 :     if (SignalsOptInRBF(tx)) {
#      20                 :       1137 :         return RBFTransactionState::REPLACEABLE_BIP125;
#      21                 :       1137 :     }
#      22                 :            : 
#      23                 :            :     // If this transaction is not in our mempool, then we can't be sure
#      24                 :            :     // we will know about all its inputs.
#      25         [ +  + ]:       1240 :     if (!pool.exists(GenTxid::Txid(tx.GetHash()))) {
#      26                 :        469 :         return RBFTransactionState::UNKNOWN;
#      27                 :        469 :     }
#      28                 :            : 
#      29                 :            :     // If all the inputs have nSequence >= maxint-1, it still might be
#      30                 :            :     // signaled for RBF if any unconfirmed parents have signaled.
#      31                 :        771 :     uint64_t noLimit = std::numeric_limits<uint64_t>::max();
#      32                 :        771 :     std::string dummy;
#      33                 :        771 :     CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
#      34                 :        771 :     pool.CalculateMemPoolAncestors(entry, ancestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
#      35                 :            : 
#      36         [ +  + ]:       6757 :     for (CTxMemPool::txiter it : ancestors) {
#      37         [ +  + ]:       6757 :         if (SignalsOptInRBF(it->GetTx())) {
#      38                 :          6 :             return RBFTransactionState::REPLACEABLE_BIP125;
#      39                 :          6 :         }
#      40                 :       6757 :     }
#      41                 :        765 :     return RBFTransactionState::FINAL;
#      42                 :        771 : }
#      43                 :            : 
#      44                 :            : RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
#      45                 :          0 : {
#      46                 :            :     // If we don't have a local mempool we can only check the transaction itself.
#      47         [ #  # ]:          0 :     return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
#      48                 :          0 : }
#      49                 :            : 
#      50                 :            : std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
#      51                 :            :                                                   CTxMemPool& pool,
#      52                 :            :                                                   const CTxMemPool::setEntries& iters_conflicting,
#      53                 :            :                                                   CTxMemPool::setEntries& all_conflicts)
#      54                 :       1451 : {
#      55                 :       1451 :     AssertLockHeld(pool.cs);
#      56                 :       1451 :     const uint256 txid = tx.GetHash();
#      57                 :       1451 :     uint64_t nConflictingCount = 0;
#      58         [ +  + ]:       1849 :     for (const auto& mi : iters_conflicting) {
#      59                 :       1849 :         nConflictingCount += mi->GetCountWithDescendants();
#      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.
#      64         [ +  + ]:       1849 :         if (nConflictingCount > MAX_BIP125_REPLACEMENT_CANDIDATES) {
#      65                 :          6 :             return strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
#      66                 :          6 :                              txid.ToString(),
#      67                 :          6 :                              nConflictingCount,
#      68                 :          6 :                              MAX_BIP125_REPLACEMENT_CANDIDATES);
#      69                 :          6 :         }
#      70                 :       1849 :     }
#      71                 :            :     // Calculate the set of all transactions that would have to be evicted.
#      72         [ +  + ]:       1643 :     for (CTxMemPool::txiter it : iters_conflicting) {
#      73                 :       1643 :         pool.CalculateDescendants(it, all_conflicts);
#      74                 :       1643 :     }
#      75                 :       1445 :     return std::nullopt;
#      76                 :       1451 : }
#      77                 :            : 
#      78                 :            : std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
#      79                 :            :                                                const CTxMemPool& pool,
#      80                 :            :                                                const CTxMemPool::setEntries& iters_conflicting)
#      81                 :       1445 : {
#      82                 :       1445 :     AssertLockHeld(pool.cs);
#      83                 :       1445 :     std::set<uint256> parents_of_conflicts;
#      84         [ +  + ]:       1643 :     for (const auto& mi : iters_conflicting) {
#      85         [ +  + ]:       1653 :         for (const CTxIn& txin : mi->GetTx().vin) {
#      86                 :       1653 :             parents_of_conflicts.insert(txin.prevout.hash);
#      87                 :       1653 :         }
#      88                 :       1643 :     }
#      89                 :            : 
#      90         [ +  + ]:       3104 :     for (unsigned int j = 0; j < tx.vin.size(); j++) {
#      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.
#      94                 :            :         //
#      95                 :            :         // Note that if you relax this to make RBF a little more useful, this may break the
#      96                 :            :         // CalculateMempoolAncestors RBF relaxation which subtracts the conflict count/size from the
#      97                 :            :         // descendant limit.
#      98         [ +  + ]:       1661 :         if (!parents_of_conflicts.count(tx.vin[j].prevout.hash)) {
#      99                 :            :             // Rather than check the UTXO set - potentially expensive - it's cheaper to just check
#     100                 :            :             // if the new input refers to a tx that's in the mempool.
#     101         [ +  + ]:          6 :             if (pool.exists(GenTxid::Txid(tx.vin[j].prevout.hash))) {
#     102                 :          2 :                 return strprintf("replacement %s adds unconfirmed input, idx %d",
#     103                 :          2 :                                  tx.GetHash().ToString(), j);
#     104                 :          2 :             }
#     105                 :          6 :         }
#     106                 :       1661 :     }
#     107                 :       1443 :     return std::nullopt;
#     108                 :       1445 : }
#     109                 :            : 
#     110                 :            : std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries& ancestors,
#     111                 :            :                                                    const std::set<uint256>& direct_conflicts,
#     112                 :            :                                                    const uint256& txid)
#     113                 :      28034 : {
#     114         [ +  + ]:      28034 :     for (CTxMemPool::txiter ancestorIt : ancestors) {
#     115                 :      17831 :         const uint256& hashAncestor = ancestorIt->GetTx().GetHash();
#     116         [ +  + ]:      17831 :         if (direct_conflicts.count(hashAncestor)) {
#     117                 :          4 :             return strprintf("%s spends conflicting transaction %s",
#     118                 :          4 :                              txid.ToString(),
#     119                 :          4 :                              hashAncestor.ToString());
#     120                 :          4 :         }
#     121                 :      17831 :     }
#     122                 :      28030 :     return std::nullopt;
#     123                 :      28034 : }
#     124                 :            : 
#     125                 :            : std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& iters_conflicting,
#     126                 :            :                                                  CFeeRate replacement_feerate,
#     127                 :            :                                                  const uint256& txid)
#     128                 :       1463 : {
#     129         [ +  + ]:       1861 :     for (const auto& mi : iters_conflicting) {
#     130                 :            :         // Don't allow the replacement to reduce the feerate of the mempool.
#     131                 :            :         //
#     132                 :            :         // We usually don't want to accept replacements with lower feerates than what they replaced
#     133                 :            :         // as that would lower the feerate of the next block. Requiring that the feerate always be
#     134                 :            :         // increased is also an easy-to-reason about way to prevent DoS attacks via replacements.
#     135                 :            :         //
#     136                 :            :         // We only consider the feerates of transactions being directly replaced, not their indirect
#     137                 :            :         // descendants. While that does mean high feerate children are ignored when deciding whether
#     138                 :            :         // or not to replace, we do require the replacement to pay more overall fees too, mitigating
#     139                 :            :         // most cases.
#     140                 :       1861 :         CFeeRate original_feerate(mi->GetModifiedFee(), mi->GetTxSize());
#     141         [ +  + ]:       1861 :         if (replacement_feerate <= original_feerate) {
#     142                 :         12 :             return strprintf("rejecting replacement %s; new feerate %s <= old feerate %s",
#     143                 :         12 :                              txid.ToString(),
#     144                 :         12 :                              replacement_feerate.ToString(),
#     145                 :         12 :                              original_feerate.ToString());
#     146                 :         12 :         }
#     147                 :       1861 :     }
#     148                 :       1451 :     return std::nullopt;
#     149                 :       1463 : }
#     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                 :       1443 : {
#     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         [ +  + ]:       1443 :     if (replacement_fees < original_fees) {
#     161                 :          4 :         return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
#     162                 :          4 :                          txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees));
#     163                 :          4 :     }
#     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                 :       1439 :     CAmount additional_fees = replacement_fees - original_fees;
#     169         [ +  + ]:       1439 :     if (additional_fees < relay_fee.GetFee(replacement_vsize)) {
#     170                 :          2 :         return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
#     171                 :          2 :                          txid.ToString(),
#     172                 :          2 :                          FormatMoney(additional_fees),
#     173                 :          2 :                          FormatMoney(relay_fee.GetFee(replacement_vsize)));
#     174                 :          2 :     }
#     175                 :       1437 :     return std::nullopt;
#     176                 :       1439 : }

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a