Skip to content

Commit af1067c

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#23640: MOVEONLY: Move helper functions from rpcwallet to wallet/rpc/util
ff945e5 MOVEONLY: Move utility functions from rpcwallet to wallet/rpc/util (Samuel Dobson) 7b04a06 Introduce wallet/rpc/util (Samuel Dobson) Pull request description: This is part one of multiple to split up rpcwallet.cpp into smaller, more logical units. See #23622 for context and overall plan. I'll open PRs in stages to hopefully minimise conflicts. Can be reviewed with `--color-moved=dimmed-zebra` The end goal can be seen here: https://github.com/meshcollider/bitcoin/tree/202111_split_walletrpc ACKs for top commit: MarcoFalke: nice, ACK ff945e5 🐰 shaavan: ACK ff945e5 Tree-SHA512: 6e3d1de6db770fe2fca540c8c4f30183ab8258c26e3a1fb46937714d28818a52933eafbfcafe2995f6a6e2551a3f3dd3ec93363b81de7912c0d81f5749d1c86d
2 parents a377510 + ff945e5 commit af1067c

File tree

7 files changed

+165
-139
lines changed

7 files changed

+165
-139
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ BITCOIN_CORE_H = \
283283
wallet/load.h \
284284
wallet/receive.h \
285285
wallet/rpcwallet.h \
286+
wallet/rpc/util.h \
286287
wallet/salvage.h \
287288
wallet/scriptpubkeyman.h \
288289
wallet/spend.h \
@@ -410,6 +411,7 @@ libbitcoin_wallet_a_SOURCES = \
410411
wallet/load.cpp \
411412
wallet/receive.cpp \
412413
wallet/rpc/signmessage.cpp \
414+
wallet/rpc/util.cpp \
413415
wallet/rpcdump.cpp \
414416
wallet/rpcwallet.cpp \
415417
wallet/scriptpubkeyman.cpp \

src/wallet/rpc/signmessage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <key_io.h>
66
#include <rpc/util.h>
77
#include <util/message.h>
8-
#include <wallet/rpcwallet.h>
8+
#include <wallet/rpc/util.h>
99
#include <wallet/wallet.h>
1010

1111
#include <univalue.h>

src/wallet/rpc/util.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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/url.h>
9+
#include <wallet/context.h>
10+
#include <wallet/wallet.h>
11+
12+
#include <univalue.h>
13+
14+
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
15+
const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"};
16+
17+
bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param) {
18+
bool can_avoid_reuse = wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
19+
bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool();
20+
21+
if (avoid_reuse && !can_avoid_reuse) {
22+
throw JSONRPCError(RPC_WALLET_ERROR, "wallet does not have the \"avoid reuse\" feature enabled");
23+
}
24+
25+
return avoid_reuse;
26+
}
27+
28+
/** Used by RPC commands that have an include_watchonly parameter.
29+
* We default to true for watchonly wallets if include_watchonly isn't
30+
* explicitly set.
31+
*/
32+
bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet)
33+
{
34+
if (include_watchonly.isNull()) {
35+
// if include_watchonly isn't explicitly set, then check if we have a watchonly wallet
36+
return wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
37+
}
38+
39+
// otherwise return whatever include_watchonly was set to
40+
return include_watchonly.get_bool();
41+
}
42+
43+
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
44+
{
45+
if (URL_DECODE && request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
46+
// wallet endpoint was used
47+
wallet_name = URL_DECODE(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
48+
return true;
49+
}
50+
return false;
51+
}
52+
53+
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
54+
{
55+
CHECK_NONFATAL(request.mode == JSONRPCRequest::EXECUTE);
56+
WalletContext& context = EnsureWalletContext(request.context);
57+
58+
std::string wallet_name;
59+
if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
60+
const std::shared_ptr<CWallet> pwallet = GetWallet(context, wallet_name);
61+
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
62+
return pwallet;
63+
}
64+
65+
std::vector<std::shared_ptr<CWallet>> wallets = GetWallets(context);
66+
if (wallets.size() == 1) {
67+
return wallets[0];
68+
}
69+
70+
if (wallets.empty()) {
71+
throw JSONRPCError(
72+
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)");
73+
}
74+
throw JSONRPCError(RPC_WALLET_NOT_SPECIFIED,
75+
"Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
76+
}
77+
78+
void EnsureWalletIsUnlocked(const CWallet& wallet)
79+
{
80+
if (wallet.IsLocked()) {
81+
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
82+
}
83+
}
84+
85+
WalletContext& EnsureWalletContext(const std::any& context)
86+
{
87+
auto wallet_context = util::AnyPtr<WalletContext>(context);
88+
if (!wallet_context) {
89+
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet context not found");
90+
}
91+
return *wallet_context;
92+
}
93+
94+
// 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
95+
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create)
96+
{
97+
LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
98+
if (!spk_man && also_create) {
99+
spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
100+
}
101+
if (!spk_man) {
102+
throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
103+
}
104+
return *spk_man;
105+
}
106+
107+
const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wallet)
108+
{
109+
const LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
110+
if (!spk_man) {
111+
throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
112+
}
113+
return *spk_man;
114+
}
115+
116+
std::string LabelFromValue(const UniValue& value)
117+
{
118+
std::string label = value.get_str();
119+
if (label == "*")
120+
throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
121+
return label;
122+
}

src/wallet/rpc/util.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (c) 2017-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+
#ifndef BITCOIN_WALLET_RPC_UTIL_H
6+
#define BITCOIN_WALLET_RPC_UTIL_H
7+
8+
#include <any>
9+
#include <memory>
10+
#include <string>
11+
12+
class CWallet;
13+
class JSONRPCRequest;
14+
class LegacyScriptPubKeyMan;
15+
class UniValue;
16+
struct WalletContext;
17+
18+
extern const std::string HELP_REQUIRING_PASSPHRASE;
19+
20+
/**
21+
* Figures out what wallet, if any, to use for a JSONRPCRequest.
22+
*
23+
* @param[in] request JSONRPCRequest that wishes to access a wallet
24+
* @return nullptr if no wallet should be used, or a pointer to the CWallet
25+
*/
26+
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
27+
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name);
28+
29+
void EnsureWalletIsUnlocked(const CWallet&);
30+
WalletContext& EnsureWalletContext(const std::any& context);
31+
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create = false);
32+
const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wallet);
33+
34+
bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param);
35+
bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet);
36+
std::string LabelFromValue(const UniValue& value);
37+
38+
#endif // BITCOIN_WALLET_RPC_UTIL_H

src/wallet/rpcdump.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <util/system.h>
1818
#include <util/time.h>
1919
#include <util/translation.h>
20-
#include <wallet/rpcwallet.h>
20+
#include <wallet/rpc/util.h>
2121
#include <wallet/wallet.h>
2222

2323
#include <stdint.h>

src/wallet/rpcwallet.cpp

Lines changed: 1 addition & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <wallet/load.h>
3333
#include <wallet/receive.h>
3434
#include <wallet/rpcwallet.h>
35+
#include <wallet/rpc/util.h>
3536
#include <wallet/spend.h>
3637
#include <wallet/wallet.h>
3738
#include <wallet/walletdb.h>
@@ -46,36 +47,6 @@
4647

4748
using interfaces::FoundBlock;
4849

49-
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
50-
const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"};
51-
52-
static inline bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param) {
53-
bool can_avoid_reuse = wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
54-
bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool();
55-
56-
if (avoid_reuse && !can_avoid_reuse) {
57-
throw JSONRPCError(RPC_WALLET_ERROR, "wallet does not have the \"avoid reuse\" feature enabled");
58-
}
59-
60-
return avoid_reuse;
61-
}
62-
63-
64-
/** Used by RPC commands that have an include_watchonly parameter.
65-
* We default to true for watchonly wallets if include_watchonly isn't
66-
* explicitly set.
67-
*/
68-
static bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet)
69-
{
70-
if (include_watchonly.isNull()) {
71-
// if include_watchonly isn't explicitly set, then check if we have a watchonly wallet
72-
return wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
73-
}
74-
75-
// otherwise return whatever include_watchonly was set to
76-
return include_watchonly.get_bool();
77-
}
78-
7950

8051
/** Checks if a CKey is in the given CWallet compressed or otherwise*/
8152
bool HaveKey(const SigningProvider& wallet, const CKey& key)
@@ -85,79 +56,6 @@ bool HaveKey(const SigningProvider& wallet, const CKey& key)
8556
return wallet.HaveKey(key.GetPubKey().GetID()) || wallet.HaveKey(key2.GetPubKey().GetID());
8657
}
8758

88-
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
89-
{
90-
if (URL_DECODE && request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
91-
// wallet endpoint was used
92-
wallet_name = URL_DECODE(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
93-
return true;
94-
}
95-
return false;
96-
}
97-
98-
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
99-
{
100-
CHECK_NONFATAL(request.mode == JSONRPCRequest::EXECUTE);
101-
WalletContext& context = EnsureWalletContext(request.context);
102-
103-
std::string wallet_name;
104-
if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
105-
const std::shared_ptr<CWallet> pwallet = GetWallet(context, wallet_name);
106-
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
107-
return pwallet;
108-
}
109-
110-
std::vector<std::shared_ptr<CWallet>> wallets = GetWallets(context);
111-
if (wallets.size() == 1) {
112-
return wallets[0];
113-
}
114-
115-
if (wallets.empty()) {
116-
throw JSONRPCError(
117-
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)");
118-
}
119-
throw JSONRPCError(RPC_WALLET_NOT_SPECIFIED,
120-
"Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
121-
}
122-
123-
void EnsureWalletIsUnlocked(const CWallet& wallet)
124-
{
125-
if (wallet.IsLocked()) {
126-
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
127-
}
128-
}
129-
130-
WalletContext& EnsureWalletContext(const std::any& context)
131-
{
132-
auto wallet_context = util::AnyPtr<WalletContext>(context);
133-
if (!wallet_context) {
134-
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet context not found");
135-
}
136-
return *wallet_context;
137-
}
138-
139-
// 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
140-
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create)
141-
{
142-
LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
143-
if (!spk_man && also_create) {
144-
spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
145-
}
146-
if (!spk_man) {
147-
throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
148-
}
149-
return *spk_man;
150-
}
151-
152-
const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wallet)
153-
{
154-
const LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
155-
if (!spk_man) {
156-
throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
157-
}
158-
return *spk_man;
159-
}
160-
16159
static void WalletTxToJSON(const CWallet& wallet, const CWalletTx& wtx, UniValue& entry)
16260
{
16361
interfaces::Chain& chain = wallet.chain();
@@ -200,13 +98,6 @@ static void WalletTxToJSON(const CWallet& wallet, const CWalletTx& wtx, UniValue
20098
entry.pushKV(item.first, item.second);
20199
}
202100

203-
static std::string LabelFromValue(const UniValue& value)
204-
{
205-
std::string label = value.get_str();
206-
if (label == "*")
207-
throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
208-
return label;
209-
}
210101

211102
/**
212103
* Update coin control with fee estimation based on the given parameters

src/wallet/rpcwallet.h

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,10 @@
77

88
#include <span.h>
99

10-
#include <any>
11-
#include <memory>
12-
#include <string>
13-
#include <vector>
14-
1510
class CRPCCommand;
16-
class CWallet;
17-
class JSONRPCRequest;
18-
class LegacyScriptPubKeyMan;
19-
class UniValue;
20-
class CTransaction;
21-
struct PartiallySignedTransaction;
22-
struct WalletContext;
23-
24-
extern const std::string HELP_REQUIRING_PASSPHRASE;
2511

2612
Span<const CRPCCommand> GetWalletRPCCommands();
2713

28-
/**
29-
* Figures out what wallet, if any, to use for a JSONRPCRequest.
30-
*
31-
* @param[in] request JSONRPCRequest that wishes to access a wallet
32-
* @return nullptr if no wallet should be used, or a pointer to the CWallet
33-
*/
34-
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
35-
36-
void EnsureWalletIsUnlocked(const CWallet&);
37-
WalletContext& EnsureWalletContext(const std::any& context);
38-
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create = false);
39-
const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wallet);
40-
4114
RPCHelpMan getaddressinfo();
4215
RPCHelpMan signrawtransactionwithwallet();
4316
#endif // BITCOIN_WALLET_RPCWALLET_H

0 commit comments

Comments
 (0)