Skip to content

Commit 0d64290

Browse files
committed
refactor: separate out Dash-specific RPCs that rely on wallet logic
In an upcoming commit, wallet variables will be deglobalized. This means that RPCs that use wallet logic need to get ahold of WalletContext, which only happens if they're registered as a wallet RPC (i.e. registered through WalletLoader). The downside of being registered as a wallet RPC is that you lose access to NodeContext. For now, we will work around this by giving WalletContext access to NodeContext and modify EnsureAnyNodeContext to pull it from WalletContext.
1 parent 1548058 commit 0d64290

16 files changed

+205
-52
lines changed

src/dummywallet.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet)
9191
throw std::logic_error("Wallet function called in non-wallet build.");
9292
}
9393

94-
std::unique_ptr<WalletClient> MakeWalletLoader(Chain& chain, ArgsManager& args, interfaces::CoinJoin::Loader& coinjoin_loader)
94+
std::unique_ptr<WalletClient> MakeWalletLoader(Chain& chain, ArgsManager& args, NodeContext& node_context,
95+
interfaces::CoinJoin::Loader& coinjoin_loader)
9596
{
9697
throw std::logic_error("Wallet function called in non-wallet build.");
9798
}

src/init.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <index/txindex.h>
3232
#include <interfaces/init.h>
3333
#include <interfaces/node.h>
34+
#include <interfaces/wallet.h>
3435
#include <mapport.h>
3536
#include <node/miner.h>
3637
#include <net.h>
@@ -1516,6 +1517,23 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15161517
for (const auto& client : node.chain_clients) {
15171518
client->registerRpcs();
15181519
}
1520+
#ifdef ENABLE_WALLET
1521+
// Register non-core wallet-only RPC commands. These are commands that
1522+
// aren't a part of the wallet library but heavily rely on wallet logic.
1523+
// TODO: Move them to chain client interfaces so they can be called
1524+
// with registerRpcs()
1525+
if (!args.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
1526+
for (const auto& commands : {
1527+
GetWalletCoinJoinRPCCommands(),
1528+
GetWalletEvoRPCCommands(),
1529+
GetWalletGovernanceRPCCommands(),
1530+
GetWalletMasternodeRPCCommands(),
1531+
}) {
1532+
node.wallet_loader->registerOtherRpcs(commands);
1533+
}
1534+
}
1535+
#endif // ENABLE_WALLET
1536+
15191537
#if ENABLE_ZMQ
15201538
RegisterZMQRPCCommands(tableRPC);
15211539
#endif

src/init/bitcoin-node.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class BitcoinNodeInit : public interfaces::Init
3737
}
3838
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader) override
3939
{
40-
return MakeWalletLoader(chain, *Assert(m_node.args), coinjoin_loader);
40+
return MakeWalletLoader(chain, *Assert(m_node.args), m_node, coinjoin_loader);
4141
}
4242
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
4343
interfaces::Ipc* ipc() override { return m_ipc.get(); }

src/init/bitcoind.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class BitcoindInit : public interfaces::Init
3232
}
3333
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader) override
3434
{
35-
return MakeWalletLoader(chain, *Assert(m_node.args), coinjoin_loader);
35+
return MakeWalletLoader(chain, *Assert(m_node.args), m_node, coinjoin_loader);
3636
}
3737
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
3838
NodeContext& m_node;

src/interfaces/wallet.h

+12-4
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,22 @@
2828
class CCoinControl;
2929
class CFeeRate;
3030
class CKey;
31+
class CRPCCommand;
3132
class CWallet;
3233
class UniValue;
3334
enum class FeeReason;
3435
enum class TransactionError;
3536
enum isminetype : unsigned int;
36-
struct bilingual_str;
3737
struct CRecipient;
38+
struct NodeContext;
3839
struct PartiallySignedTransaction;
3940
struct WalletContext;
4041
struct bilingual_str;
4142
using isminefilter = std::underlying_type<isminetype>::type;
4243

44+
template <typename T>
45+
class Span;
46+
4347
namespace interfaces {
4448

4549
class Handler;
@@ -335,8 +339,11 @@ class Wallet
335339
class WalletLoader : public ChainClient
336340
{
337341
public:
338-
//! Create new wallet.
339-
virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
342+
//! Register non-core wallet RPCs
343+
virtual void registerOtherRpcs(const Span<const CRPCCommand>& commands) = 0;
344+
345+
//! Create new wallet.
346+
virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
340347

341348
//! Load existing wallet.
342349
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
@@ -450,7 +457,8 @@ std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
450457

451458
//! Return implementation of ChainClient interface for a wallet loader. This
452459
//! function will be undefined in builds where ENABLE_WALLET is false.
453-
std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args, CoinJoin::Loader& coinjoin_loader);
460+
std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args, NodeContext& node_context,
461+
CoinJoin::Loader& coinjoin_loader);
454462

455463
} // namespace interfaces
456464

src/rpc/coinjoin.cpp

+35-10
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22
// Distributed under the MIT/X11 software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#include <node/context.h>
6-
#include <validation.h>
75
#include <coinjoin/context.h>
86
#include <coinjoin/server.h>
7+
#include <node/context.h>
98
#include <rpc/blockchain.h>
109
#include <rpc/server.h>
1110
#include <rpc/server_util.h>
12-
#include <util/check.h>
1311
#include <rpc/util.h>
12+
#include <util/check.h>
1413
#include <util/strencodings.h>
14+
#include <validation.h>
1515
#include <wallet/rpc/util.h>
16+
#include <walletinitinterface.h>
1617

1718
#ifdef ENABLE_WALLET
1819
#include <coinjoin/client.h>
@@ -485,14 +486,13 @@ static RPCHelpMan getcoinjoininfo()
485486
};
486487
}
487488

488-
void RegisterCoinJoinRPCCommands(CRPCTable &t)
489+
#ifdef ENABLE_WALLET
490+
Span<const CRPCCommand> GetWalletCoinJoinRPCCommands()
489491
{
490492
// clang-format off
491493
static const CRPCCommand commands[] =
492-
{ // category actor (function)
493-
// --------------------- -----------------------
494-
{ "dash", &getcoinjoininfo, },
495-
#ifdef ENABLE_WALLET
494+
{ // category actor (function)
495+
// --------------------- -----------------------
496496
{ "dash", &coinjoin, },
497497
{ "dash", &coinjoin_reset, },
498498
{ "dash", &coinjoin_start, },
@@ -502,10 +502,35 @@ static const CRPCCommand commands[] =
502502
{ "dash", &coinjoinsalt_generate, },
503503
{ "dash", &coinjoinsalt_get, },
504504
{ "dash", &coinjoinsalt_set, },
505+
{ "dash", &getcoinjoininfo, },
506+
};
507+
// clang-format on
508+
return commands;
509+
}
505510
#endif // ENABLE_WALLET
511+
512+
void RegisterCoinJoinRPCCommands(CRPCTable& t)
513+
{
514+
// clang-format off
515+
static const CRPCCommand commands_wallet[] =
516+
{ // category actor (function)
517+
// --------------------- -----------------------
518+
{ "dash", &getcoinjoininfo, },
506519
};
507520
// clang-format on
508-
for (const auto& command : commands) {
509-
t.appendCommand(command.name, &command);
521+
// If we aren't compiling with wallet support, we still need to register RPCs that are
522+
// capable of working without wallet support. We have to do this even if wallet support
523+
// is compiled in but is disabled at runtime because runtime disablement prohibits
524+
// registering wallet RPCs. We still want the reduced functionality RPC to be registered.
525+
// TODO: Spin off these hybrid RPCs into dedicated wallet-only and/or wallet-free RPCs
526+
// and get rid of this workaround.
527+
if (!g_wallet_init_interface.HasWalletSupport()
528+
#ifdef ENABLE_WALLET
529+
|| gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)
530+
#endif // ENABLE_WALLET
531+
) {
532+
for (const auto& command : commands_wallet) {
533+
tableRPC.appendCommand(command.name, &command);
534+
}
510535
}
511536
}

src/rpc/evo.cpp

+41-9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <util/translation.h>
3232
#include <validation.h>
3333
#include <wallet/rpc/util.h>
34+
#include <walletinitinterface.h>
3435

3536
#ifdef ENABLE_WALLET
3637
#include <wallet/coincontrol.h>
@@ -1777,17 +1778,15 @@ static RPCHelpMan bls_help()
17771778
};
17781779
}
17791780

1780-
void RegisterEvoRPCCommands(CRPCTable &tableRPC)
1781+
#ifdef ENABLE_WALLET
1782+
Span<const CRPCCommand> GetWalletEvoRPCCommands()
17811783
{
17821784
// clang-format off
17831785
static const CRPCCommand commands[] =
17841786
{ // category actor (function)
17851787
// --------------------- -----------------------
1786-
{ "evo", &bls_help, },
1787-
{ "evo", &bls_generate, },
1788-
{ "evo", &bls_fromsecret, },
1789-
{ "evo", &protx_help, },
1790-
#ifdef ENABLE_WALLET
1788+
{ "evo", &protx_list, },
1789+
{ "evo", &protx_info, },
17911790
{ "evo", &protx_register, },
17921791
{ "evo", &protx_register_evo, },
17931792
{ "evo", &protx_register_legacy, },
@@ -1803,14 +1802,47 @@ static const CRPCCommand commands[] =
18031802
{ "evo", &protx_update_registrar, },
18041803
{ "evo", &protx_update_registrar_legacy, },
18051804
{ "evo", &protx_revoke, },
1806-
#endif
1807-
{ "evo", &protx_list, },
1808-
{ "evo", &protx_info, },
1805+
};
1806+
// clang-format on
1807+
return commands;
1808+
}
1809+
#endif // ENABLE_WALLET
1810+
1811+
void RegisterEvoRPCCommands(CRPCTable& tableRPC)
1812+
{
1813+
// clang-format off
1814+
static const CRPCCommand commands[] =
1815+
{ // category actor (function)
1816+
// --------------------- -----------------------
1817+
{ "evo", &bls_help, },
1818+
{ "evo", &bls_generate, },
1819+
{ "evo", &bls_fromsecret, },
1820+
{ "evo", &protx_help, },
18091821
{ "evo", &protx_diff, },
18101822
{ "evo", &protx_listdiff, },
18111823
};
1824+
static const CRPCCommand commands_wallet[] =
1825+
{
1826+
{ "evo", &protx_list, },
1827+
{ "evo", &protx_info, },
1828+
};
18121829
// clang-format on
18131830
for (const auto& command : commands) {
18141831
tableRPC.appendCommand(command.name, &command);
18151832
}
1833+
// If we aren't compiling with wallet support, we still need to register RPCs that are
1834+
// capable of working without wallet support. We have to do this even if wallet support
1835+
// is compiled in but is disabled at runtime because runtime disablement prohibits
1836+
// registering wallet RPCs. We still want the reduced functionality RPC to be registered.
1837+
// TODO: Spin off these hybrid RPCs into dedicated wallet-only and/or wallet-free RPCs
1838+
// and get rid of this workaround.
1839+
if (!g_wallet_init_interface.HasWalletSupport()
1840+
#ifdef ENABLE_WALLET
1841+
|| gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)
1842+
#endif // ENABLE_WALLET
1843+
) {
1844+
for (const auto& command : commands_wallet) {
1845+
tableRPC.appendCommand(command.name, &command);
1846+
}
1847+
}
18161848
}

src/rpc/governance.cpp

+17-6
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,23 @@ static RPCHelpMan getsuperblockbudget()
10711071
};
10721072
}
10731073

1074+
#ifdef ENABLE_WALLET
1075+
Span<const CRPCCommand> GetWalletGovernanceRPCCommands()
1076+
{
1077+
// clang-format off
1078+
static const CRPCCommand commands[] =
1079+
{ // category actor (function)
1080+
// --------------------- -----------------------
1081+
{ "dash", &gobject_prepare, },
1082+
{ "dash", &gobject_list_prepared, },
1083+
{ "dash", &gobject_vote_many, },
1084+
{ "dash", &gobject_vote_alias, },
1085+
};
1086+
// clang-format on
1087+
return commands;
1088+
}
1089+
#endif // ENABLE_WALLET
1090+
10741091
void RegisterGovernanceRPCCommands(CRPCTable &t)
10751092
{
10761093
// clang-format off
@@ -1084,12 +1101,6 @@ static const CRPCCommand commands[] =
10841101
{ "dash", &gobject_count, },
10851102
{ "dash", &gobject_deserialize, },
10861103
{ "dash", &gobject_check, },
1087-
#ifdef ENABLE_WALLET
1088-
{ "dash", &gobject_prepare, },
1089-
{ "dash", &gobject_list_prepared, },
1090-
{ "dash", &gobject_vote_many, },
1091-
{ "dash", &gobject_vote_alias, },
1092-
#endif
10931104
{ "dash", &gobject_submit, },
10941105
{ "dash", &gobject_list, },
10951106
{ "dash", &gobject_diff, },

src/rpc/masternode.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,20 @@ static RPCHelpMan masternodelist_composite()
671671
return masternodelist_helper(true);
672672
}
673673

674+
#ifdef ENABLE_WALLET
675+
Span<const CRPCCommand> GetWalletMasternodeRPCCommands()
676+
{
677+
// clang-format off
678+
static const CRPCCommand commands[] =
679+
{ // category actor (function)
680+
// --------------------- -----------------------
681+
{ "dash", &masternode_outputs, },
682+
};
683+
// clang-format on
684+
return commands;
685+
}
686+
#endif // ENABLE_WALLET
687+
674688
void RegisterMasternodeRPCCommands(CRPCTable &t)
675689
{
676690
// clang-format off
@@ -682,9 +696,6 @@ static const CRPCCommand commands[] =
682696
{ "dash", &masternodelist, },
683697
{ "dash", &masternode_connect, },
684698
{ "dash", &masternode_count, },
685-
#ifdef ENABLE_WALLET
686-
{ "dash", &masternode_outputs, },
687-
#endif // ENABLE_WALLET
688699
{ "dash", &masternode_status, },
689700
{ "dash", &masternode_payments, },
690701
{ "dash", &masternode_winners, },

src/rpc/register.h

+12
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77

88
/** These are in one header file to avoid creating tons of single-function
99
* headers for everything under src/rpc/ */
10+
class CRPCCommand;
1011
class CRPCTable;
1112

13+
template <typename T>
14+
class Span;
15+
1216
void RegisterBlockchainRPCCommands(CRPCTable &tableRPC);
1317
void RegisterFeeRPCCommands(CRPCTable&);
1418
void RegisterMempoolRPCCommands(CRPCTable&);
@@ -24,6 +28,14 @@ void RegisterGovernanceRPCCommands(CRPCTable &tableRPC);
2428
void RegisterEvoRPCCommands(CRPCTable &tableRPC);
2529
void RegisterQuorumsRPCCommands(CRPCTable &tableRPC);
2630

31+
#ifdef ENABLE_WALLET
32+
// Dash-specific wallet-only RPC commands
33+
Span<const CRPCCommand> GetWalletCoinJoinRPCCommands();
34+
Span<const CRPCCommand> GetWalletEvoRPCCommands();
35+
Span<const CRPCCommand> GetWalletGovernanceRPCCommands();
36+
Span<const CRPCCommand> GetWalletMasternodeRPCCommands();
37+
#endif // ENABLE_WALLET
38+
2739
static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
2840
{
2941
RegisterBlockchainRPCCommands(t);

src/rpc/server_util.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,29 @@
1313
#include <util/system.h>
1414
#include <validation.h>
1515

16+
#ifdef ENABLE_WALLET
17+
#include <wallet/context.h>
18+
#endif // ENABLE_WALLET
19+
1620
#include <any>
1721

1822
NodeContext& EnsureAnyNodeContext(const CoreContext& context)
1923
{
2024
auto* const node_context = GetContext<NodeContext>(context);
21-
if (!node_context) {
22-
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node context not found");
25+
if (node_context) {
26+
return *node_context;
27+
}
28+
#ifdef ENABLE_WALLET
29+
// We're now going to try our luck with WalletContext on the off chance
30+
// we're being called by a wallet RPC that's trying to access NodeContext
31+
// See comment on WalletContext::node_context for more information.
32+
// TODO: Find a solution that removes the need for this workaround
33+
auto* const wallet_context = GetContext<WalletContext>(context);
34+
if (wallet_context && wallet_context->node_context) {
35+
return *wallet_context->node_context;
2336
}
24-
return *node_context;
37+
#endif // ENABLE_WALLET
38+
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node context not found");
2539
}
2640

2741
CTxMemPool& EnsureMemPool(const NodeContext& node)

0 commit comments

Comments
 (0)