Skip to content

Commit b54b2e7

Browse files
committed
Move external signer out of wallet module
This commit moves the ExternalSigner class and RPC methods out of the wallet module. The enumeratesigners RPC can be used without a wallet since #21417. With additional modifications external signers could be used without a wallet in general, e.g. via signrawtransaction. The signerdisplayaddress RPC is ranamed to walletdisplayaddress because it requires wallet context. A future displayaddress RPC call without wallet context could take a descriptor argument. This commit fixes a rpc_help.py failure when configured with --disable-wallet.
1 parent 6664211 commit b54b2e7

15 files changed

+160
-134
lines changed

doc/external-signer.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Display an address on the device:
4646

4747
```sh
4848
$ bitcoin-cli -rpcwallet=<wallet> getnewaddress
49-
$ bitcoin-cli -rpcwallet=<wallet> signerdisplayaddress <address>
49+
$ bitcoin-cli -rpcwallet=<wallet> walletdisplayaddress <address>
5050
```
5151

5252
Replace `<address>` with the result of `getnewaddress`.
@@ -166,6 +166,6 @@ The `createwallet` RPC calls:
166166

167167
It then imports descriptors for all support address types, in a BIP44/49/84 compatible manner.
168168

169-
The `displayaddress` RPC reuses some code from `getaddressinfo` on the provided address and obtains the inferred descriptor. It then calls `<cmd> --fingerprint=00000000 displayaddress --desc=<descriptor>`.
169+
The `walletdisplayaddress` RPC reuses some code from `getaddressinfo` on the provided address and obtains the inferred descriptor. It then calls `<cmd> --fingerprint=00000000 displayaddress --desc=<descriptor>`.
170170

171171
`sendtoaddress` and `sendmany` check `inputs->bip32_derivs` to see if any inputs have the same `master_fingerprint` as the signer. If so, it calls `<cmd> --fingerprint=00000000 signtransaction <psbt>`. It waits for the device to return a (partially) signed psbt, tries to finalize it and broadcasts the transaction.

src/Makefile.am

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ BITCOIN_CORE_H = \
144144
core_memusage.h \
145145
cuckoocache.h \
146146
dbwrapper.h \
147+
external_signer.h \
147148
flatfile.h \
148149
fs.h \
149150
httprpc.h \
@@ -267,13 +268,11 @@ BITCOIN_CORE_H = \
267268
wallet/crypter.h \
268269
wallet/db.h \
269270
wallet/dump.h \
270-
wallet/external_signer.h \
271271
wallet/external_signer_scriptpubkeyman.h \
272272
wallet/feebumper.h \
273273
wallet/fees.h \
274274
wallet/ismine.h \
275275
wallet/load.h \
276-
wallet/rpcsigner.h \
277276
wallet/rpcwallet.h \
278277
wallet/salvage.h \
279278
wallet/scriptpubkeyman.h \
@@ -387,13 +386,11 @@ libbitcoin_wallet_a_SOURCES = \
387386
wallet/db.cpp \
388387
wallet/dump.cpp \
389388
wallet/external_signer_scriptpubkeyman.cpp \
390-
wallet/external_signer.cpp \
391389
wallet/feebumper.cpp \
392390
wallet/fees.cpp \
393391
wallet/interfaces.cpp \
394392
wallet/load.cpp \
395393
wallet/rpcdump.cpp \
396-
wallet/rpcsigner.cpp \
397394
wallet/rpcwallet.cpp \
398395
wallet/scriptpubkeyman.cpp \
399396
wallet/wallet.cpp \
@@ -520,6 +517,7 @@ libbitcoin_common_a_SOURCES = \
520517
compressor.cpp \
521518
core_read.cpp \
522519
core_write.cpp \
520+
external_signer.cpp \
523521
key.cpp \
524522
key_io.cpp \
525523
merkleblock.cpp \
@@ -532,6 +530,7 @@ libbitcoin_common_a_SOURCES = \
532530
protocol.cpp \
533531
psbt.cpp \
534532
rpc/rawtransaction_util.cpp \
533+
rpc/external_signer.cpp \
535534
rpc/util.cpp \
536535
scheduler.cpp \
537536
script/descriptor.cpp \

src/wallet/external_signer.cpp renamed to src/external_signer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <psbt.h>
88
#include <util/strencodings.h>
99
#include <util/system.h>
10-
#include <wallet/external_signer.h>
10+
#include <external_signer.h>
1111

1212
ExternalSigner::ExternalSigner(const std::string& command, const std::string& fingerprint, std::string chain, std::string name): m_command(command), m_fingerprint(fingerprint), m_chain(chain), m_name(name) {}
1313

src/wallet/external_signer.h renamed to src/external_signer.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#ifndef BITCOIN_WALLET_EXTERNAL_SIGNER_H
6-
#define BITCOIN_WALLET_EXTERNAL_SIGNER_H
5+
#ifndef BITCOIN_EXTERNAL_SIGNER_H
6+
#define BITCOIN_EXTERNAL_SIGNER_H
77

88
#include <stdexcept>
99
#include <string>
@@ -48,7 +48,7 @@ class ExternalSigner
4848
//! @param[in] command the command which handles interaction with the external signer
4949
//! @param[in,out] signers vector to which new signers (with a unique master key fingerprint) are added
5050
//! @param chain "main", "test", "regtest" or "signet"
51-
//! @param[out] success Boolean
51+
//! @returns success
5252
static bool Enumerate(const std::string& command, std::vector<ExternalSigner>& signers, std::string chain, bool ignore_errors = false);
5353

5454
//! Display address on the device. Calls `<command> displayaddress --desc <descriptor>`.
@@ -59,7 +59,7 @@ class ExternalSigner
5959
//! Get receive and change Descriptor(s) from device for a given account.
6060
//! Calls `<command> getdescriptors --account <account>`
6161
//! @param[in] account which BIP32 account to use (e.g. `m/44'/0'/account'`)
62-
//! @param[out] UniValue see doc/external-signer.md
62+
//! @returns see doc/external-signer.md
6363
UniValue GetDescriptors(int account);
6464

6565
//! Sign PartiallySignedTransaction on the device.
@@ -70,4 +70,4 @@ class ExternalSigner
7070
#endif
7171
};
7272

73-
#endif // BITCOIN_WALLET_EXTERNAL_SIGNER_H
73+
#endif // BITCOIN_EXTERNAL_SIGNER_H

src/wallet/rpcsigner.cpp renamed to src/rpc/external_signer.cpp

Lines changed: 8 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <chainparamsbase.h>
6-
#include <key_io.h>
6+
#include <external_signer.h>
77
#include <rpc/server.h>
88
#include <rpc/util.h>
99
#include <util/strencodings.h>
10-
#include <wallet/rpcsigner.h>
11-
#include <wallet/rpcwallet.h>
12-
#include <wallet/wallet.h>
10+
#include <rpc/protocol.h>
1311

1412
#ifdef ENABLE_EXTERNAL_SIGNER
1513

@@ -33,7 +31,7 @@ static RPCHelpMan enumeratesigners()
3331
RPCExamples{""},
3432
[](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
3533
const std::string command = gArgs.GetArg("-signer", "");
36-
if (command == "") throw JSONRPCError(RPC_WALLET_ERROR, "Error: restart bitcoind with -signer=<cmd>");
34+
if (command == "") throw JSONRPCError(RPC_MISC_ERROR, "Error: restart bitcoind with -signer=<cmd>");
3735
std::string chain = gArgs.GetChainName();
3836
UniValue signers_res = UniValue::VARR;
3937
try {
@@ -46,7 +44,7 @@ static RPCHelpMan enumeratesigners()
4644
signers_res.push_back(signer_res);
4745
}
4846
} catch (const ExternalSignerException& e) {
49-
throw JSONRPCError(RPC_WALLET_ERROR, e.what());
47+
throw JSONRPCError(RPC_MISC_ERROR, e.what());
5048
}
5149
UniValue result(UniValue::VOBJ);
5250
result.pushKV("signers", signers_res);
@@ -55,54 +53,18 @@ static RPCHelpMan enumeratesigners()
5553
};
5654
}
5755

58-
static RPCHelpMan signerdisplayaddress()
56+
void RegisterSignerRPCCommands(CRPCTable &t)
5957
{
60-
return RPCHelpMan{
61-
"signerdisplayaddress",
62-
"Display address on an external signer for verification.\n",
63-
{
64-
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, /* default_val */ "", "bitcoin address to display"},
65-
},
66-
RPCResult{RPCResult::Type::NONE,"",""},
67-
RPCExamples{""},
68-
[](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
69-
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
70-
if (!wallet) return NullUniValue;
71-
CWallet* const pwallet = wallet.get();
72-
73-
LOCK(pwallet->cs_wallet);
74-
75-
CTxDestination dest = DecodeDestination(request.params[0].get_str());
76-
77-
// Make sure the destination is valid
78-
if (!IsValidDestination(dest)) {
79-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
80-
}
81-
82-
if (!pwallet->DisplayAddress(dest)) {
83-
throw JSONRPCError(RPC_WALLET_ERROR, "Failed to display address");
84-
}
85-
86-
UniValue result(UniValue::VOBJ);
87-
result.pushKV("address", request.params[0].get_str());
88-
return result;
89-
}
90-
};
91-
}
92-
93-
Span<const CRPCCommand> GetSignerRPCCommands()
94-
{
95-
9658
// clang-format off
9759
static const CRPCCommand commands[] =
9860
{ // category actor (function)
9961
// --------------------- ------------------------
10062
{ "signer", &enumeratesigners, },
101-
{ "signer", &signerdisplayaddress, },
10263
};
10364
// clang-format on
104-
return MakeSpan(commands);
65+
for (const auto& c : commands) {
66+
t.appendCommand(c.name, &c);
67+
}
10568
}
10669

107-
10870
#endif // ENABLE_EXTERNAL_SIGNER

src/rpc/register.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ void RegisterMiscRPCCommands(CRPCTable &tableRPC);
1919
void RegisterMiningRPCCommands(CRPCTable &tableRPC);
2020
/** Register raw transaction RPC commands */
2121
void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
22+
/** Register raw transaction RPC commands */
23+
void RegisterSignerRPCCommands(CRPCTable &tableRPC);
2224

2325
static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
2426
{
@@ -27,6 +29,9 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
2729
RegisterMiscRPCCommands(t);
2830
RegisterMiningRPCCommands(t);
2931
RegisterRawTransactionRPCCommands(t);
32+
#ifdef ENABLE_EXTERNAL_SIGNER
33+
RegisterSignerRPCCommands(t);
34+
#endif // ENABLE_EXTERNAL_SIGNER
3035
}
3136

3237
#endif // BITCOIN_RPC_REGISTER_H

src/wallet/external_signer_scriptpubkeyman.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <chainparams.h>
6-
#include <wallet/external_signer.h>
6+
#include <external_signer.h>
77
#include <wallet/external_signer_scriptpubkeyman.h>
88

99
#ifdef ENABLE_EXTERNAL_SIGNER

src/wallet/interfaces.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <wallet/fees.h>
2323
#include <wallet/ismine.h>
2424
#include <wallet/load.h>
25-
#include <wallet/rpcsigner.h>
2625
#include <wallet/rpcwallet.h>
2726
#include <wallet/wallet.h>
2827

@@ -520,17 +519,6 @@ class WalletClientImpl : public WalletClient
520519
}, command.argNames, command.unique_id);
521520
m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back()));
522521
}
523-
524-
#ifdef ENABLE_EXTERNAL_SIGNER
525-
for (const CRPCCommand& command : GetSignerRPCCommands()) {
526-
m_rpc_commands.emplace_back(command.category, command.name, [this, &command](const JSONRPCRequest& request, UniValue& result, bool last_handler) {
527-
JSONRPCRequest wallet_request = request;
528-
wallet_request.context = &m_context;
529-
return command.actor(wallet_request, result, last_handler);
530-
}, command.argNames, command.unique_id);
531-
m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back()));
532-
}
533-
#endif
534522
}
535523
bool verify() override { return VerifyWallets(*m_context.chain); }
536524
bool load() override { return LoadWallets(*m_context.chain); }

src/wallet/rpcsigner.h

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/wallet/rpcwallet.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4526,6 +4526,48 @@ static RPCHelpMan upgradewallet()
45264526
};
45274527
}
45284528

4529+
#ifdef ENABLE_EXTERNAL_SIGNER
4530+
static RPCHelpMan walletdisplayaddress()
4531+
{
4532+
return RPCHelpMan{
4533+
"walletdisplayaddress",
4534+
"Display address on an external signer for verification.\n",
4535+
{
4536+
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, /* default_val */ "", "bitcoin address to display"},
4537+
},
4538+
RPCResult{
4539+
RPCResult::Type::OBJ,"","",
4540+
{
4541+
{RPCResult::Type::STR, "address", "The address as confirmed by the signer"},
4542+
}
4543+
},
4544+
RPCExamples{""},
4545+
[](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
4546+
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
4547+
if (!wallet) return NullUniValue;
4548+
CWallet* const pwallet = wallet.get();
4549+
4550+
LOCK(pwallet->cs_wallet);
4551+
4552+
CTxDestination dest = DecodeDestination(request.params[0].get_str());
4553+
4554+
// Make sure the destination is valid
4555+
if (!IsValidDestination(dest)) {
4556+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
4557+
}
4558+
4559+
if (!pwallet->DisplayAddress(dest)) {
4560+
throw JSONRPCError(RPC_MISC_ERROR, "Failed to display address");
4561+
}
4562+
4563+
UniValue result(UniValue::VOBJ);
4564+
result.pushKV("address", request.params[0].get_str());
4565+
return result;
4566+
}
4567+
};
4568+
}
4569+
#endif // ENABLE_EXTERNAL_SIGNER
4570+
45294571
RPCHelpMan abortrescan();
45304572
RPCHelpMan dumpprivkey();
45314573
RPCHelpMan importprivkey();
@@ -4602,6 +4644,9 @@ static const CRPCCommand commands[] =
46024644
{ "wallet", &unloadwallet, },
46034645
{ "wallet", &upgradewallet, },
46044646
{ "wallet", &walletcreatefundedpsbt, },
4647+
#ifdef ENABLE_EXTERNAL_SIGNER
4648+
{ "wallet", &walletdisplayaddress, },
4649+
#endif // ENABLE_EXTERNAL_SIGNER
46054650
{ "wallet", &walletlock, },
46064651
{ "wallet", &walletpassphrase, },
46074652
{ "wallet", &walletpassphrasechange, },

0 commit comments

Comments
 (0)