messages.cpp raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Bitcoin Core 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 <common/messages.h>
   7  #include <common/types.h>
   8  #include <node/types.h>
   9  #include <policy/fees/block_policy_estimator.h>
  10  #include <tinyformat.h>
  11  #include <util/fees.h>
  12  #include <util/strencodings.h>
  13  #include <util/string.h>
  14  #include <util/translation.h>
  15  
  16  #include <cassert>
  17  #include <map>
  18  #include <string>
  19  #include <string_view>
  20  #include <utility>
  21  #include <vector>
  22  
  23  using node::TransactionError;
  24  using util::Join;
  25  
  26  namespace common {
  27  std::string StringForFeeReason(FeeReason reason)
  28  {
  29      static const std::map<FeeReason, std::string> fee_reason_strings = {
  30          {FeeReason::NONE, "None"},
  31          {FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"},
  32          {FeeReason::FULL_ESTIMATE, "Target 85% Threshold"},
  33          {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
  34          {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
  35          {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
  36          {FeeReason::FALLBACK, "Fallback fee"},
  37          {FeeReason::REQUIRED, "Minimum Required Fee"},
  38      };
  39      auto reason_string = fee_reason_strings.find(reason);
  40  
  41      if (reason_string == fee_reason_strings.end()) return "Unknown";
  42  
  43      return reason_string->second;
  44  }
  45  
  46  const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap()
  47  {
  48      static const std::vector<std::pair<std::string, FeeEstimateMode>> FEE_MODES = {
  49          {"unset", FeeEstimateMode::UNSET},
  50          {"economical", FeeEstimateMode::ECONOMICAL},
  51          {"conservative", FeeEstimateMode::CONSERVATIVE},
  52      };
  53      return FEE_MODES;
  54  }
  55  
  56  std::string FeeModeInfo(const std::pair<std::string, FeeEstimateMode>& mode, std::string& default_info)
  57  {
  58      switch (mode.second) {
  59          case FeeEstimateMode::UNSET:
  60              return strprintf("%s means no mode set (%s). \n", mode.first, default_info);
  61          case FeeEstimateMode::ECONOMICAL:
  62              return strprintf("%s estimates use a shorter time horizon, making them more\n"
  63                     "responsive to short-term drops in the prevailing fee market. This mode\n"
  64                     "potentially returns a lower fee rate estimate.\n", mode.first);
  65          case FeeEstimateMode::CONSERVATIVE:
  66              return strprintf("%s estimates use a longer time horizon, making them\n"
  67                     "less responsive to short-term drops in the prevailing fee market. This mode\n"
  68                     "potentially returns a higher fee rate estimate.\n", mode.first);
  69      } // no default case, so the compiler can warn about missing cases
  70      assert(false);
  71  }
  72  
  73  std::string FeeModesDetail(std::string default_info)
  74  {
  75      std::string info;
  76      for (const auto& fee_mode : FeeModeMap()) {
  77          info += FeeModeInfo(fee_mode, default_info);
  78      }
  79      return strprintf("%s \n%s", FeeModes(", "), info);
  80  }
  81  
  82  std::string FeeModes(const std::string& delimiter)
  83  {
  84      return Join(FeeModeMap(), delimiter, [&](const std::pair<std::string, FeeEstimateMode>& i) { return i.first; });
  85  }
  86  
  87  std::string InvalidEstimateModeErrorMessage()
  88  {
  89      return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\"";
  90  }
  91  
  92  bool FeeModeFromString(std::string_view mode_string, FeeEstimateMode& fee_estimate_mode)
  93  {
  94      auto searchkey = ToUpper(mode_string);
  95      for (const auto& pair : FeeModeMap()) {
  96          if (ToUpper(pair.first) == searchkey) {
  97              fee_estimate_mode = pair.second;
  98              return true;
  99          }
 100      }
 101      return false;
 102  }
 103  
 104  bilingual_str PSBTErrorString(PSBTError err)
 105  {
 106      switch (err) {
 107          case PSBTError::MISSING_INPUTS:
 108              return Untranslated("Inputs missing or spent");
 109          case PSBTError::SIGHASH_MISMATCH:
 110              return Untranslated("Specified sighash value does not match value stored in PSBT");
 111          case PSBTError::EXTERNAL_SIGNER_NOT_FOUND:
 112              return Untranslated("External signer not found");
 113          case PSBTError::EXTERNAL_SIGNER_FAILED:
 114              return Untranslated("External signer failed to sign");
 115          case PSBTError::UNSUPPORTED:
 116              return Untranslated("Signer does not support PSBT");
 117          case PSBTError::INCOMPLETE:
 118              return Untranslated("Input needs additional signatures or other data");
 119          case PSBTError::INVALID_TX:
 120              return Untranslated("The transaction cannot be valid");
 121          case PSBTError::OK:
 122              return Untranslated("No errors");
 123      } // no default case, so the compiler can warn about missing cases
 124      assert(false);
 125  }
 126  
 127  bilingual_str TransactionErrorString(const TransactionError err)
 128  {
 129      switch (err) {
 130          case TransactionError::OK:
 131              return Untranslated("No error");
 132          case TransactionError::MISSING_INPUTS:
 133              return Untranslated("Inputs missing or spent");
 134          case TransactionError::ALREADY_IN_UTXO_SET:
 135              return Untranslated("Transaction outputs already in utxo set");
 136          case TransactionError::MEMPOOL_REJECTED:
 137              return Untranslated("Transaction rejected by mempool");
 138          case TransactionError::MEMPOOL_ERROR:
 139              return Untranslated("Mempool internal error");
 140          case TransactionError::MAX_FEE_EXCEEDED:
 141              return Untranslated("Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)");
 142          case TransactionError::MAX_BURN_EXCEEDED:
 143              return Untranslated("Unspendable output exceeds maximum configured by user (maxburnamount)");
 144          case TransactionError::INVALID_PACKAGE:
 145              return Untranslated("Transaction rejected due to invalid package");
 146          case TransactionError::PRIVATE_BROADCAST_FULL:
 147              return Untranslated("Private broadcast queue is full");
 148      } // no default case, so the compiler can warn about missing cases
 149      assert(false);
 150  }
 151  
 152  bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBind)
 153  {
 154      return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind);
 155  }
 156  
 157  bilingual_str InvalidPortErrMsg(const std::string& optname, const std::string& invalid_value)
 158  {
 159      return strprintf(_("Invalid port specified in %s: '%s'"), optname, invalid_value);
 160  }
 161  
 162  bilingual_str AmountHighWarn(const std::string& optname)
 163  {
 164      return strprintf(_("%s is set very high!"), optname);
 165  }
 166  
 167  bilingual_str AmountErrMsg(const std::string& optname, const std::string& strValue)
 168  {
 169      return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
 170  }
 171  } // namespace common
 172