Bitcoin Core  22.99.0
P2P Digital Currency
util.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2021 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 #include <wallet/rpc/util.h>
6 
7 #include <rpc/util.h>
8 #include <util/translation.h>
9 #include <util/url.h>
10 #include <wallet/context.h>
11 #include <wallet/wallet.h>
12 
13 #include <univalue.h>
14 
15 namespace wallet {
16 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
17 const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"};
18 
19 bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param) {
20  bool can_avoid_reuse = wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
21  bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool();
22 
23  if (avoid_reuse && !can_avoid_reuse) {
24  throw JSONRPCError(RPC_WALLET_ERROR, "wallet does not have the \"avoid reuse\" feature enabled");
25  }
26 
27  return avoid_reuse;
28 }
29 
34 bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet)
35 {
36  if (include_watchonly.isNull()) {
37  // if include_watchonly isn't explicitly set, then check if we have a watchonly wallet
38  return wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
39  }
40 
41  // otherwise return whatever include_watchonly was set to
42  return include_watchonly.get_bool();
43 }
44 
45 bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
46 {
47  if (URL_DECODE && request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
48  // wallet endpoint was used
49  wallet_name = URL_DECODE(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
50  return true;
51  }
52  return false;
53 }
54 
55 std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
56 {
59 
60  std::string wallet_name;
61  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
62  const std::shared_ptr<CWallet> pwallet = GetWallet(context, wallet_name);
63  if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
64  return pwallet;
65  }
66 
67  std::vector<std::shared_ptr<CWallet>> wallets = GetWallets(context);
68  if (wallets.size() == 1) {
69  return wallets[0];
70  }
71 
72  if (wallets.empty()) {
73  throw JSONRPCError(
74  RPC_WALLET_NOT_FOUND, "No wallet is loaded. Load a wallet using loadwallet or create a new one with createwallet. (Note: A default wallet is no longer automatically created)");
75  }
77  "Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
78 }
79 
81 {
82  if (wallet.IsLocked()) {
83  throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
84  }
85 }
86 
88 {
89  auto wallet_context = util::AnyPtr<WalletContext>(context);
90  if (!wallet_context) {
91  throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet context not found");
92  }
93  return *wallet_context;
94 }
95 
96 // also_create should only be set to true only when the RPC is expected to add things to a blank wallet and make it no longer blank
98 {
99  LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
100  if (!spk_man && also_create) {
101  spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
102  }
103  if (!spk_man) {
104  throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
105  }
106  return *spk_man;
107 }
108 
110 {
111  const LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
112  if (!spk_man) {
113  throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
114  }
115  return *spk_man;
116 }
117 
118 std::string LabelFromValue(const UniValue& value)
119 {
120  std::string label = value.get_str();
121  if (label == "*")
122  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
123  return label;
124 }
125 
126 void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error)
127 {
128  if (!wallet) {
129  // Map bad format to not found, since bad format is returned when the
130  // wallet directory exists, but doesn't contain a data file.
132  switch (status) {
135  code = RPC_WALLET_NOT_FOUND;
136  break;
139  break;
142  break;
144  code = RPC_INVALID_PARAMETER;
145  break;
146  default: // RPC_WALLET_ERROR is returned for all other cases.
147  break;
148  }
149  throw JSONRPCError(code, error.original);
150  }
151 }
152 } // namespace wallet
UniValue::get_bool
bool get_bool() const
Definition: univalue_get.cpp:91
RPC_INTERNAL_ERROR
@ RPC_INTERNAL_ERROR
Definition: protocol.h:35
wallet.h
CHECK_NONFATAL
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
Definition: check.h:32
JSONRPCRequest::context
std::any context
Definition: request.h:38
wallet::DatabaseStatus
DatabaseStatus
Definition: db.h:213
wallet::EnsureConstLegacyScriptPubKeyMan
const LegacyScriptPubKeyMan & EnsureConstLegacyScriptPubKeyMan(const CWallet &wallet)
Definition: util.cpp:109
bilingual_str
Bilingual messages:
Definition: translation.h:16
RPC_INVALID_PARAMETER
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
wallet::GetWalletForJSONRPCRequest
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:55
wallet
Definition: node.h:38
UniValue::isNull
bool isNull() const
Definition: univalue.h:75
wallet::DatabaseStatus::FAILED_ALREADY_LOADED
@ FAILED_ALREADY_LOADED
UniValue
Definition: univalue.h:17
wallet::GetWallets
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:148
wallet::HELP_REQUIRING_PASSPHRASE
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:17
UniValue::get_str
const std::string & get_str() const
Definition: univalue_get.cpp:98
util.h
wallet::LegacyScriptPubKeyMan
Definition: scriptpubkeyman.h:264
RPC_WALLET_NOT_FOUND
@ RPC_WALLET_NOT_FOUND
Invalid wallet specified.
Definition: protocol.h:80
wallet::CWallet
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:232
RPC_WALLET_INVALID_LABEL_NAME
@ RPC_WALLET_INVALID_LABEL_NAME
Invalid label name.
Definition: protocol.h:73
wallet::WALLET_FLAG_DISABLE_PRIVATE_KEYS
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
univalue.h
wallet::WALLET_ENDPOINT_BASE
static const std::string WALLET_ENDPOINT_BASE
Definition: util.cpp:16
wallet::GetWallet
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:154
RPC_WALLET_UNLOCK_NEEDED
@ RPC_WALLET_UNLOCK_NEEDED
Enter the wallet passphrase with walletpassphrase first.
Definition: protocol.h:75
context
WalletContext context
Definition: notifications.cpp:37
RPC_WALLET_ALREADY_EXISTS
@ RPC_WALLET_ALREADY_EXISTS
There is already a wallet with the same name.
Definition: protocol.h:83
wallet::WALLET_FLAG_AVOID_REUSE
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:42
wallet::HandleWalletError
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:126
JSONRPCRequest::mode
enum JSONRPCRequest::Mode mode
RPC_WALLET_ERROR
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
wallet::DatabaseStatus::FAILED_INVALID_BACKUP_FILE
@ FAILED_INVALID_BACKUP_FILE
wallet::DatabaseStatus::FAILED_BAD_FORMAT
@ FAILED_BAD_FORMAT
wallet::DatabaseStatus::FAILED_NOT_FOUND
@ FAILED_NOT_FOUND
RPC_WALLET_NOT_SPECIFIED
@ RPC_WALLET_NOT_SPECIFIED
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:81
translation.h
url.h
JSONRPCError
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:56
RPCErrorCode
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:23
RPC_WALLET_ALREADY_LOADED
@ RPC_WALLET_ALREADY_LOADED
This same wallet is already loaded.
Definition: protocol.h:82
wallet::GetWalletNameFromJSONRPCRequest
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:45
context.h
JSONRPCRequest::URI
std::string URI
Definition: request.h:35
JSONRPCRequest
Definition: request.h:28
URL_DECODE
UrlDecodeFn *const URL_DECODE
Definition: bitcoin-cli.cpp:44
wallet::WalletContext
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:35
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
wallet::DatabaseStatus::FAILED_ALREADY_EXISTS
@ FAILED_ALREADY_EXISTS
wallet::EnsureLegacyScriptPubKeyMan
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:97
JSONRPCRequest::EXECUTE
@ EXECUTE
Definition: request.h:34
wallet::ParseIncludeWatchonly
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:34
wallet::GetAvoidReuseFlag
bool GetAvoidReuseFlag(const CWallet &wallet, const UniValue &param)
Definition: util.cpp:19
wallet::EnsureWalletIsUnlocked
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:80
wallet::EnsureWalletContext
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:87
wallet::LabelFromValue
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:118