feebumper.h raw

   1  // Copyright (c) 2017-present 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  #ifndef BITCOIN_WALLET_FEEBUMPER_H
   6  #define BITCOIN_WALLET_FEEBUMPER_H
   7  
   8  #include <consensus/consensus.h>
   9  #include <script/interpreter.h>
  10  #include <primitives/transaction.h>
  11  
  12  class uint256;
  13  enum class FeeEstimateMode;
  14  struct bilingual_str;
  15  
  16  namespace wallet {
  17  class CCoinControl;
  18  class CWallet;
  19  class CWalletTx;
  20  
  21  namespace feebumper {
  22  
  23  enum class Result
  24  {
  25      OK,
  26      INVALID_ADDRESS_OR_KEY,
  27      INVALID_REQUEST,
  28      INVALID_PARAMETER,
  29      WALLET_ERROR,
  30      MISC_ERROR,
  31  };
  32  
  33  //! Return whether transaction can be bumped.
  34  bool TransactionCanBeBumped(const CWallet& wallet, const Txid& txid);
  35  
  36  /** Create bumpfee transaction based on feerate estimates.
  37   *
  38   * @param[in] wallet The wallet to use for this bumping
  39   * @param[in] txid The txid of the transaction to bump
  40   * @param[in] coin_control A CCoinControl object which provides feerates and other information used for coin selection
  41   * @param[out] errors Errors
  42   * @param[out] old_fee The fee the original transaction pays
  43   * @param[out] new_fee the fee that the bump transaction pays
  44   * @param[out] mtx The bump transaction itself
  45   * @param[in] require_mine Whether the original transaction must consist of inputs that can be spent by the wallet
  46   * @param[in] outputs Vector of new outputs to replace the bumped transaction's outputs
  47   * @param[in] original_change_index The position of the change output to deduct the fee from in the transaction being bumped
  48   */
  49  Result CreateRateBumpTransaction(CWallet& wallet,
  50      const Txid& txid,
  51      const CCoinControl& coin_control,
  52      std::vector<bilingual_str>& errors,
  53      CAmount& old_fee,
  54      CAmount& new_fee,
  55      CMutableTransaction& mtx,
  56      bool require_mine,
  57      const std::vector<CTxOut>& outputs,
  58      std::optional<uint32_t> original_change_index = std::nullopt);
  59  
  60  //! Sign the new transaction,
  61  //! @return false if the tx couldn't be found or if it was
  62  //! impossible to create the signature(s)
  63  bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx);
  64  
  65  //! Commit the bumpfee transaction.
  66  //! @return success in case of CWallet::CommitTransaction was successful,
  67  //! but sets errors if the tx could not be added to the mempool (will try later)
  68  //! or if the old transaction could not be marked as replaced.
  69  Result CommitTransaction(CWallet& wallet,
  70      const Txid& txid,
  71      CMutableTransaction&& mtx,
  72      std::vector<bilingual_str>& errors,
  73      Txid& bumped_txid);
  74  
  75  struct SignatureWeights
  76  {
  77  private:
  78      int m_sigs_count{0};
  79      int64_t m_sigs_weight{0};
  80  
  81  public:
  82      void AddSigWeight(const size_t weight, const SigVersion sigversion)
  83      {
  84          switch (sigversion) {
  85          case SigVersion::BASE:
  86              m_sigs_weight += weight * WITNESS_SCALE_FACTOR;
  87              m_sigs_count += 1 * WITNESS_SCALE_FACTOR;
  88              break;
  89          case SigVersion::WITNESS_V0:
  90              m_sigs_weight += weight;
  91              m_sigs_count++;
  92              break;
  93          case SigVersion::TAPROOT:
  94          case SigVersion::TAPSCRIPT:
  95              assert(false);
  96          }
  97      }
  98  
  99      int64_t GetWeightDiffToMax() const
 100      {
 101          // Note: the witness scaling factor is already accounted for because the count is multiplied by it.
 102          return (/* max signature size=*/ 72 * m_sigs_count) - m_sigs_weight;
 103      }
 104  };
 105  
 106  class SignatureWeightChecker : public DeferringSignatureChecker
 107  {
 108  private:
 109      SignatureWeights& m_weights;
 110  
 111  public:
 112      SignatureWeightChecker(SignatureWeights& weights, const BaseSignatureChecker& checker) : DeferringSignatureChecker(checker), m_weights(weights) {}
 113  
 114      bool CheckECDSASignature(const std::vector<unsigned char>& sig, const std::vector<unsigned char>& pubkey, const CScript& script, SigVersion sigversion) const override
 115      {
 116          if (m_checker.CheckECDSASignature(sig, pubkey, script, sigversion)) {
 117              m_weights.AddSigWeight(sig.size(), sigversion);
 118              return true;
 119          }
 120          return false;
 121      }
 122  };
 123  
 124  } // namespace feebumper
 125  } // namespace wallet
 126  
 127  #endif // BITCOIN_WALLET_FEEBUMPER_H
 128