Bitcoin ABC  0.26.3
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/any.h>
9 #include <util/translation.h>
10 #include <util/url.h>
11 #include <wallet/context.h>
12 #include <wallet/wallet.h>
13 
14 #include <univalue.h>
15 
16 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
17 const std::string HELP_REQUIRING_PASSPHRASE{
18  "\nRequires wallet passphrase to be set with walletpassphrase call if "
19  "wallet is encrypted.\n"};
20 
21 bool GetAvoidReuseFlag(const CWallet *const pwallet, const UniValue &param) {
22  bool can_avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
23  bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool();
24 
25  if (avoid_reuse && !can_avoid_reuse) {
26  throw JSONRPCError(
28  "wallet does not have the \"avoid reuse\" feature enabled");
29  }
30 
31  return avoid_reuse;
32 }
33 
38 bool ParseIncludeWatchonly(const UniValue &include_watchonly,
39  const CWallet &pwallet) {
40  if (include_watchonly.isNull()) {
41  // if include_watchonly isn't explicitly set, then check if we have a
42  // watchonly wallet
44  }
45 
46  // otherwise return whatever include_watchonly was set to
47  return include_watchonly.get_bool();
48 }
49 
51  std::string &wallet_name) {
52  if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) ==
54  // wallet endpoint was used
55  wallet_name =
56  urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
57  return true;
58  }
59  return false;
60 }
61 
62 std::shared_ptr<CWallet>
65  std::string wallet_name;
66  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
67  std::shared_ptr<CWallet> pwallet = GetWallet(wallet_name);
68  if (!pwallet) {
69  throw JSONRPCError(
71  "Requested wallet does not exist or is not loaded");
72  }
73  return pwallet;
74  }
75 
76  std::vector<std::shared_ptr<CWallet>> wallets = GetWallets();
77  if (wallets.size() == 1) {
78  return wallets[0];
79  }
80 
81  if (wallets.empty()) {
82  throw JSONRPCError(
84  "No wallet is loaded. Load a wallet using loadwallet or create a "
85  "new one with createwallet. (Note: A default wallet is no longer "
86  "automatically created)");
87  }
88 
90  "Wallet file not specified (must request wallet RPC "
91  "through /wallet/<filename> uri-path).");
92 }
93 
94 void EnsureWalletIsUnlocked(const CWallet *pwallet) {
95  if (pwallet->IsLocked()) {
97  "Error: Please enter the wallet passphrase with "
98  "walletpassphrase first.");
99  }
100 }
101 
102 WalletContext &EnsureWalletContext(const std::any &context) {
103  auto wallet_context = util::AnyPtr<WalletContext>(context);
104  if (!wallet_context) {
105  throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet context not found");
106  }
107  return *wallet_context;
108 }
109 
110 // also_create should only be set to true only when the RPC is expected to add
111 // things to a blank wallet and make it no longer blank
113  bool also_create) {
114  LegacyScriptPubKeyMan *spk_man = wallet.GetLegacyScriptPubKeyMan();
115  if (!spk_man && also_create) {
116  spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
117  }
118  if (!spk_man) {
120  "This type of wallet does not support this command");
121  }
122  return *spk_man;
123 }
124 
125 std::string LabelFromValue(const UniValue &value) {
126  std::string label = value.get_str();
127  if (label == "*") {
128  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
129  }
130  return label;
131 }
132 
133 std::tuple<std::shared_ptr<CWallet>, std::vector<bilingual_str>>
134 LoadWalletHelper(WalletContext &context, UniValue load_on_start_param,
135  const std::string wallet_name) {
136  DatabaseOptions options;
137  DatabaseStatus status;
138  options.require_existing = true;
140  std::vector<bilingual_str> warnings;
141  std::optional<bool> load_on_start =
142  load_on_start_param.isNull()
143  ? std::nullopt
144  : std::make_optional<bool>(load_on_start_param.get_bool());
145  std::shared_ptr<CWallet> const wallet =
146  LoadWallet(*context.chain, wallet_name, load_on_start, options, status,
147  error, warnings);
148  if (!wallet) {
149  // Map bad format to not found, since bad format is returned
150  // when the wallet directory exists, but doesn't contain a data
151  // file.
156  throw JSONRPCError(code, error.original);
157  }
158 
159  return {wallet, warnings};
160 }
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:53
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:254
bool IsLocked() const override
Definition: wallet.cpp:3147
enum JSONRPCRequest::Mode mode
std::string URI
Definition: request.h:36
const std::string & get_str() const
bool isNull() const
Definition: univalue.h:104
bool get_bool() const
bool IsWalletFlagSet(uint64_t flag) const override
Check if a certain wallet flag is set.
Definition: wallet.cpp:1517
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:22
@ RPC_WALLET_NOT_SPECIFIED
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:111
@ RPC_WALLET_INVALID_LABEL_NAME
Invalid label name.
Definition: protocol.h:94
@ RPC_WALLET_UNLOCK_NEEDED
Enter the wallet passphrase with walletpassphrase first.
Definition: protocol.h:98
@ RPC_WALLET_ERROR
Wallet errors Unspecified problem with wallet (key not found etc.)
Definition: protocol.h:90
@ RPC_WALLET_NOT_FOUND
Invalid wallet specified.
Definition: protocol.h:109
@ RPC_INTERNAL_ERROR
Definition: protocol.h:33
bool require_existing
Definition: db.h:222
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:23
interfaces::Chain * chain
Definition: context.h:24
Bilingual messages:
Definition: translation.h:17
std::string urlDecode(const std::string &urlEncoded)
Definition: url.cpp:10
DatabaseStatus
Definition: db.h:229
void EnsureWalletIsUnlocked(const CWallet *pwallet)
Definition: util.cpp:94
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:63
static const std::string WALLET_ENDPOINT_BASE
Definition: util.cpp:16
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:112
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:102
bool GetAvoidReuseFlag(const CWallet *const pwallet, const UniValue &param)
Definition: util.cpp:21
std::tuple< std::shared_ptr< CWallet >, std::vector< bilingual_str > > LoadWalletHelper(WalletContext &context, UniValue load_on_start_param, const std::string wallet_name)
Definition: util.cpp:134
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &pwallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:38
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:17
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:125
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:50
std::shared_ptr< CWallet > LoadWallet(interfaces::Chain &chain, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:265
std::shared_ptr< CWallet > GetWallet(const std::string &name)
Definition: wallet.cpp:156
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: wallet.cpp:151
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:55
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:47