rbf.cpp raw

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