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