fees.cpp raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-2022 The Limenka developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #include <wallet/fees.h>
   7  
   8  #include <wallet/coincontrol.h>
   9  #include <wallet/wallet.h>
  10  
  11  
  12  namespace wallet {
  13  CAmount GetRequiredFee(const CWallet& wallet, unsigned int nTxBytes)
  14  {
  15      return GetRequiredFeeRate(wallet).GetFee(nTxBytes);
  16  }
  17  
  18  
  19  CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, FeeCalculation* feeCalc)
  20  {
  21      return GetMinimumFeeRate(wallet, coin_control, feeCalc).GetFee(nTxBytes);
  22  }
  23  
  24  CFeeRate GetRequiredFeeRate(const CWallet& wallet)
  25  {
  26      return std::max(wallet.m_min_fee, wallet.chain().relayMinFee());
  27  }
  28  
  29  CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, FeeCalculation* feeCalc)
  30  {
  31      /* User control of how to calculate fee uses the following parameter precedence:
  32         1. coin_control.m_feerate
  33         2. coin_control.m_confirm_target
  34         3. m_pay_tx_fee (user-set member variable of wallet)
  35         4. m_confirm_target (user-set member variable of wallet)
  36         The first parameter that is set is used.
  37      */
  38      CFeeRate feerate_needed;
  39      if (coin_control.m_feerate) { // 1.
  40          feerate_needed = *(coin_control.m_feerate);
  41          if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE;
  42          // Allow to override automatic min/max check over coin control instance
  43          if (coin_control.fOverrideFeeRate) return feerate_needed;
  44      }
  45      else if (!coin_control.m_confirm_target && wallet.m_pay_tx_fee != CFeeRate(0)) { // 3. TODO: remove magic value of 0 for wallet member m_pay_tx_fee
  46          feerate_needed = wallet.m_pay_tx_fee;
  47          if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE;
  48      }
  49      else { // 2. or 4.
  50          // We will use smart fee estimation
  51          unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : wallet.m_confirm_target;
  52          // By default estimates are economical iff we are signaling opt-in-RBF
  53          bool conservative_estimate = !coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf);
  54          // Allow to override the default fee estimate mode over the CoinControl instance
  55          if (coin_control.m_fee_mode == FeeEstimateMode::CONSERVATIVE) conservative_estimate = true;
  56          else if (coin_control.m_fee_mode == FeeEstimateMode::ECONOMICAL) conservative_estimate = false;
  57  
  58          feerate_needed = wallet.chain().estimateSmartFee(target, conservative_estimate, feeCalc);
  59          if (feerate_needed == CFeeRate(0)) {
  60              // if we don't have enough data for estimateSmartFee, then use fallback fee
  61              feerate_needed = wallet.m_fallback_fee;
  62              if (feeCalc) feeCalc->reason = FeeReason::FALLBACK;
  63  
  64              // directly return if fallback fee is disabled (feerate 0 == disabled)
  65              if (wallet.m_fallback_fee == CFeeRate(0)) return feerate_needed;
  66          }
  67          // Obey mempool min fee when using smart fee estimation
  68          CFeeRate min_mempool_feerate = wallet.chain().mempoolMinFee();
  69          if (feerate_needed < min_mempool_feerate) {
  70              feerate_needed = min_mempool_feerate;
  71              if (feeCalc) feeCalc->reason = FeeReason::MEMPOOL_MIN;
  72          }
  73      }
  74  
  75      // prevent user from paying a fee below the required fee rate
  76      CFeeRate required_feerate = GetRequiredFeeRate(wallet);
  77      if (required_feerate > feerate_needed) {
  78          feerate_needed = required_feerate;
  79          if (feeCalc) feeCalc->reason = FeeReason::REQUIRED;
  80      }
  81      return feerate_needed;
  82  }
  83  
  84  CFeeRate GetDiscardRate(const CWallet& wallet)
  85  {
  86      unsigned int highest_target = wallet.chain().estimateMaxBlocks();
  87      CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, /*conservative=*/false);
  88      // Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
  89      discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate);
  90      // Discard rate must be at least dust relay feerate
  91      discard_rate = std::max(discard_rate, wallet.chain().relayDustFee());
  92      return discard_rate;
  93  }
  94  } // namespace wallet
  95