Bitcoin Core  24.1.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  size_t count{0};
69  if (wallet) return wallet;
70 
71  if (count == 0) {
72  throw JSONRPCError(
73  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)");
74  }
76  "Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
77 }
78 
80 {
81  if (wallet.IsLocked()) {
82  throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
83  }
84 }
85 
87 {
88  auto wallet_context = util::AnyPtr<WalletContext>(context);
89  if (!wallet_context) {
90  throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet context not found");
91  }
92  return *wallet_context;
93 }
94 
95 // 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
97 {
98  LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
99  if (!spk_man && also_create) {
100  spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
101  }
102  if (!spk_man) {
103  throw JSONRPCError(RPC_WALLET_ERROR, "Only legacy wallets are supported by this command");
104  }
105  return *spk_man;
106 }
107 
109 {
110  const LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
111  if (!spk_man) {
112  throw JSONRPCError(RPC_WALLET_ERROR, "Only legacy wallets are supported by this command");
113  }
114  return *spk_man;
115 }
116 
117 std::string LabelFromValue(const UniValue& value)
118 {
119  std::string label = value.get_str();
120  if (label == "*")
121  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
122  return label;
123 }
124 
125 void PushParentDescriptors(const CWallet& wallet, const CScript& script_pubkey, UniValue& entry)
126 {
127  UniValue parent_descs(UniValue::VARR);
128  for (const auto& desc: wallet.GetWalletDescriptors(script_pubkey)) {
129  parent_descs.push_back(desc.descriptor->ToString());
130  }
131  entry.pushKV("parent_descs", parent_descs);
132 }
133 
134 void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error)
135 {
136  if (!wallet) {
137  // Map bad format to not found, since bad format is returned when the
138  // wallet directory exists, but doesn't contain a data file.
140  switch (status) {
143  code = RPC_WALLET_NOT_FOUND;
144  break;
147  break;
150  break;
152  code = RPC_INVALID_PARAMETER;
153  break;
154  default: // RPC_WALLET_ERROR is returned for all other cases.
155  break;
156  }
157  throw JSONRPCError(code, error.original);
158  }
159 }
160 } // namespace wallet
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:81
void push_back(UniValue val)
Definition: univalue.cpp:104
std::any context
Definition: request.h:38
Enter the wallet passphrase with walletpassphrase first.
Definition: protocol.h:75
bool get_bool() const
Bilingual messages:
Definition: translation.h:18
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:47
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:34
const std::string & get_str() const
This same wallet is already loaded.
Definition: protocol.h:82
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:134
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:56
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:117
enum JSONRPCRequest::Mode mode
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:86
WalletContext context
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:235
Invalid wallet specified.
Definition: protocol.h:80
Definition: node.h:39
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:17
bool isNull() const
Definition: univalue.h:74
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:96
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:161
DatabaseStatus
Definition: db.h:219
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:410
std::string URI
Definition: request.h:35
WalletContext struct containing references to state shared between CWallet instances, like the reference to the chain interface, and the list of opened wallets.
Definition: context.h:35
static int count
Definition: tests.c:33
UrlDecodeFn *const URL_DECODE
Definition: bitcoin-cli.cpp:50
bool GetAvoidReuseFlag(const CWallet &wallet, const UniValue &param)
Definition: util.cpp:19
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:79
Wallet errors.
Definition: protocol.h:71
std::shared_ptr< CWallet > wallet
There is already a wallet with the same name.
Definition: protocol.h:83
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:23
void PushParentDescriptors(const CWallet &wallet, const CScript &script_pubkey, UniValue &entry)
Fetch parent descriptors of this scriptPubKey.
Definition: util.cpp:125
const LegacyScriptPubKeyMan & EnsureConstLegacyScriptPubKeyMan(const CWallet &wallet)
Definition: util.cpp:108
std::shared_ptr< CWallet > GetDefaultWallet(WalletContext &context, size_t &count)
Definition: wallet.cpp:154
bool error(const char *fmt, const Args &... args)
Definition: system.h:48
Invalid label name.
Definition: protocol.h:73
static const std::string WALLET_ENDPOINT_BASE
Definition: util.cpp:16
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:55
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:45