Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
6edefe5
wallet: don't import external keys at creation if blank
Sjors Aug 1, 2025
507292e
wallet: avoid signing via createTransaction() with external signer
Sjors Aug 1, 2025
b66b41c
wallet: make watch-only optional for external signer
Sjors Aug 1, 2025
3aa88b4
wallet: make external_signer flag mutable
Sjors Aug 1, 2025
e13c29f
test: move mock signer path helper to the test framework
Sjors May 6, 2026
10aa223
test: add MuSig2 external signer wallet test
Sjors May 1, 2026
3dfe347
wallet: add option to avoid script path spends
Sjors Jul 4, 2025
5e312ff
rpc: add keypath_only to walletprocesspsbt
Sjors Jul 3, 2025
9460402
test: cover keypath_only in wallet_taproot.py
Sjors Jul 3, 2025
201da29
rpc: add keypath_only to send and sendall
Sjors Jul 3, 2025
0a89ada
rpc: add keypath_only to descriptorprocesspsbt
Sjors Jun 8, 2026
d04ee75
test: cover keypath_only in wallet_musig.py
Sjors Jun 9, 2026
1070ba8
doc: add release note for keypath_only
Sjors Jun 16, 2026
707b613
test: remove unused wallet_taproot init_wallet
Sjors Jun 29, 2026
fdfb6ca
key: add DeriveExtKey() helper
Sjors Jun 20, 2025
ceb7d6b
test: move parse_hd_keypath test to bip32_tests
Sjors Jul 1, 2026
a88d85f
Have ParseHDKeypath handle h derivation marker
Sjors Jun 20, 2025
c4a8c49
fuzz: check ParseHDKeypath/WriteHDKeypath round-trip
Sjors Jul 1, 2026
84b22f3
util: reject out-of-range BIP32 keypath indices
Sjors Jul 1, 2026
a57ee7e
rpc: ParsePathBIP32 helper
Sjors Jun 16, 2025
a0466ae
refactor: add hardened derivation helper
Sjors Jun 24, 2026
d38eb35
wallet: generalize GetActiveHDPubKeys helper
Sjors Jun 26, 2026
c8b66d9
wallet: add GetExtKey helper
Sjors Jun 26, 2026
97e1757
rpc: add derivehdkey
Sjors Jun 26, 2026
1d25ae2
test: use derivehdkey in M-of-N multisig demo
Sjors Jun 26, 2025
3ebd59e
doc: use derivehdkey in multisig tutorial
Sjors Jun 24, 2026
814586f
test: check unused xprv descriptor pubkeys
Sjors May 14, 2026
945074c
wallet: reject duplicate addhdkey xprvs
Sjors May 14, 2026
874c497
wallet: add GetScriptlessSPKMs() helper
Sjors Jul 3, 2025
c4249c0
rpc: make createwalletdescriptor smarter
Sjors Jul 3, 2025
0b0afe0
Merge remote-tracking branch 'sjors/2025/06/gethdkey' into HEAD
Sjors Jul 3, 2026
fbb2870
Merge remote-tracking branch 'sjors/2025/07/smart-createwalletdescrip…
Sjors Jul 3, 2026
78c4aa9
Merge remote-tracking branch 'sjors/2025/07/no_script_path' into HEAD
Sjors Jul 3, 2026
37dbcf5
Merge remote-tracking branch 'sjors/2025/07/external-signer-relax' in…
Sjors Jul 3, 2026
f436a6f
wallet: add bip388_hmac record
Sjors Jul 21, 2025
a44ef3f
wallet: add RegisterPolicy to external signer
Sjors Jul 21, 2025
6453623
wallet: add RegisterPolicy to signer SPKM
Sjors Jul 21, 2025
f52a951
refactor: avoid std::regex in ReplaceAll
Sjors Aug 5, 2025
7334514
wallet: add registerPolicy()
Sjors Jul 21, 2025
9a33c79
wallet: don't Assume() in DerivePolicy spk_man search
Sjors Apr 28, 2026
dc1922b
wallet: upgrade to ExternalSignerScriptPubKeyMan in AddWalletDescriptor
Sjors Apr 29, 2026
d8b0e4e
rpc: add registerpolicy
Sjors Jul 21, 2025
bb1cf0a
external signer: add displayaddress policy command
Sjors Apr 28, 2026
f32077e
wallet: add BIP388 display address helpers
Sjors Apr 28, 2026
9b821cf
wallet: display registered BIP388 policy addresses
Sjors Apr 28, 2026
112f0fb
test: cover BIP388 MuSig2 displayaddress with mock signer
Sjors Apr 29, 2026
1f28368
external signer: add policy signtx command
Sjors Apr 28, 2026
3396533
wallet: add BIP388 policy PSBT signer
Sjors Apr 28, 2026
85aaf2f
wallet: route PSBT signing through BIP388 policy
Sjors Apr 28, 2026
3e38ce5
wallet: retry FillPSBT for MuSig2 round 2
Sjors Apr 28, 2026
2639485
test: cover BIP388 MuSig2 signing dance with mock signer
Sjors Apr 29, 2026
8b03655
external signer: surface SignTransactionPolicy crash as signer error
Sjors Apr 29, 2026
cef5646
test: add MuSig2 signer subprocess crash hook
Sjors Apr 29, 2026
9ecf6e2
wallet: preserve local MuSig2 contribution when policy signer fails
Sjors Apr 29, 2026
fe0d3aa
descriptor: add Descriptor::GetKeyOrigins API
Sjors Apr 29, 2026
34487e1
wallet: add CWallet::GetHDSeeds helper
Sjors Apr 29, 2026
b1a29bf
wallet: auto-bind known xprvs in importdescriptors
Sjors Apr 29, 2026
d9e2a4d
test: cover importdescriptors xprv autobind
Sjors Apr 29, 2026
2c9dd9b
wallet: fan BIP388 policy RPCs out to all signers
Sjors May 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 22 additions & 36 deletions doc/multisig-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,16 @@ This tutorial uses [jq](https://github.com/stedolan/jq) JSON processor to proces
Before starting this tutorial, start the bitcoin node on the signet network.

```bash
./build/bin/bitcoind -signet -daemon
./build/bin/bitcoin node -signet -daemon
```

This tutorial also uses the default WPKH derivation path to get the xpubs and does not conform to [BIP 45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) or [BIP 87](https://github.com/bitcoin/bips/blob/master/bip-0087.mediawiki).

At the time of writing, there is no way to extract a specific path from wallets in Bitcoin Core. For this, an external signer/xpub can be used.
This tutorial also uses the default PKH derivation path to get the xpubs and does not conform to [BIP 45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) or [BIP 87](https://github.com/bitcoin/bips/blob/master/bip-0087.mediawiki).

## 1.1 Basic Multisig Workflow

### 1.1 Create the Descriptor Wallets

For a 2-of-3 multisig, create 3 descriptor wallets. It is important that they are of the descriptor type in order to retrieve the wallet descriptors. These wallets contain HD seed and private keys, which will be used to sign the PSBTs and derive the xpub.
For a 2-of-3 multisig, create 3 wallets. These wallets contain HD seed and private keys, which will be used to sign the PSBTs and derive the xpub.

These three wallets should not be used directly for privacy reasons (public key reuse). They should only be used to sign transactions for the (watch-only) multisig wallet.

Expand All @@ -31,16 +29,7 @@ do
done
```

Extract the xpub of each wallet. To do this, the `listdescriptors` RPC is used. By default, Bitcoin Core single-sig wallets are created using path `m/44'/1'/0'` for PKH, `m/84'/1'/0'` for WPKH, `m/49'/1'/0'` for P2WPKH-nested-in-P2SH and `m/86'/1'/0'` for P2TR based accounts. Each of them uses the chain 0 for external addresses and chain 1 for internal ones, as shown in the example below.

```
wpkh([1004658e/84'/1'/0']tpubDCBEcmVKbfC9KfdydyLbJ2gfNL88grZu1XcWSW9ytTM6fitvaRmVyr8Ddf7SjZ2ZfMx9RicjYAXhuh3fmLiVLPodPEqnQQURUfrBKiiVZc8/0/*)#g8l47ngv

wpkh([1004658e/84'/1'/0']tpubDCBEcmVKbfC9KfdydyLbJ2gfNL88grZu1XcWSW9ytTM6fitvaRmVyr8Ddf7SjZ2ZfMx9RicjYAXhuh3fmLiVLPodPEqnQQURUfrBKiiVZc8/1/*)#en65rxc5
```

The suffix (after #) is the checksum. Descriptors can optionally be suffixed with a checksum to protect against typos or copy-paste errors.
All RPCs in Bitcoin Core will include the checksum in their output.
Extract the xpub of each wallet. To do this, the `derivehdkey` RPC is used.

Note that previously at least two descriptors were usually used, one for external derivation paths and one for internal ones. Since https://github.com/bitcoin/bitcoin/pull/22838 this redundancy has been eliminated by a multipath descriptor with <code><0;1></code> at the [BIP-44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#change) change level expanding to external and internal descriptors when imported.

Expand All @@ -49,66 +38,63 @@ declare -A xpubs

for ((n=1;n<=3;n++))
do
xpubs["xpub_${n}"]=$(./build/bin/bitcoin rpc -signet -rpcwallet="participant_${n}" listdescriptors | jq '.descriptors | [.[] | select(.desc | startswith("wpkh") and contains("/0/*") )][0] | .desc' | grep -Po '(?<=\().*(?=\))' | sed 's /0/\* /<0;1>/* ')
xpubs["xpub_${n}"]=$(./build/bin/bitcoin rpc -signet -rpcwallet="participant_${n}" derivehdkey "m/44h/1h/0h" | jq -r '.origin + .xpub')
done
```

`jq` is used to extract the xpub from the `wpkh` descriptor.

The following command can be used to verify if the xpub was generated correctly.
The following command can be used to verify if the xpubs were obtained successfully:

```bash
for x in "${!xpubs[@]}"; do printf "[%s]=%s\n" "$x" "${xpubs[$x]}" ; done
```

As previously mentioned, this step extracts the `m/84'/1'/0'` account instead of the path defined in [BIP 45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) or [BIP 87](https://github.com/bitcoin/bips/blob/master/bip-0087.mediawiki), since there is no way to extract a specific path in Bitcoin Core at the time of writing.
As previously mentioned, this step extracts the `m/44'/1'/0'` account instead of the path defined in [BIP 45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) or [BIP 87](https://github.com/bitcoin/bips/blob/master/bip-0087.mediawiki), because the wallet currently can't sign for a derivation path that's not used in one of its descriptors.

### 1.2 Define the Multisig Descriptor

Define the multisig descriptor, add the checksum and then, wrap it in a JSON array.
Define the multisig descriptors.

All RPCs in Bitcoin Core will include the checksum in their output.

```bash
desc="wsh(sortedmulti(2,${xpubs["xpub_1"]},${xpubs["xpub_2"]},${xpubs["xpub_3"]}))"
desc="wsh(sortedmulti(2,${xpubs["xpub_1"]}/<0;1>/*,${xpubs["xpub_2"]}/<0;1>/*,${xpubs["xpub_3"]}/<0;1>/*))"

checksum=$(./build/bin/bitcoin rpc -signet getdescriptorinfo $desc | jq -r '.checksum')
desc_sum=$(./build/bin/bitcoin rpc -signet getdescriptorinfo $desc | jq -r '.checksum')

multisig_desc="[{\"desc\": \"${desc}#${checksum}\", \"active\": true, \"timestamp\": \"now\"}]"
multisig_desc="[{\"desc\": \"$desc#$desc_sum\", \"active\": true, \"timestamp\": \"now\"}]"
```

`desc` specifies the output type (`wsh`, in this case) and the xpubs involved. It also uses BIP 67 (`sortedmulti`), so the wallet can be recreated without worrying about the order of xpubs. Conceptually, descriptors describe a list of scriptPubKey (along with information for spending from it) [[source](https://github.com/bitcoin/bitcoin/issues/21199#issuecomment-780772418)].

After creating the descriptor, it is necessary to add the checksum, which is required by the `importdescriptors` RPC.
The checksum for a descriptor without one can be computed using the `getdescriptorinfo` RPC. The response has a `checksum` field, which is appended to the descriptor after `#` to protect against typos or copy-paste errors.

The checksum for a descriptor without one can be computed using the `getdescriptorinfo` RPC. The response has the `checksum` field, which is the checksum for the input descriptor, append "#" and this checksum to the input descriptor.

There are other fields that can be added to the descriptor:
There are other fields that can be added to the descriptors:

* `active`: Sets the descriptor to be the active one for the corresponding output type (`wsh`, in this case).
* `internal`: Indicates whether matching outputs should be treated as something other than incoming payments (e.g. change).
* `timestamp`: Sets the time from which to start rescanning the blockchain for the descriptor, in UNIX epoch time.

Note: when a multipath descriptor is imported, it is expanded into two descriptors which are imported separately, with the second implicitly used for internal (change) addresses.

Documentation for these and other parameters can be found by typing `./build/bin/bitcoin rpc -signet help importdescriptors`.

`multisig_desc` wraps the descriptor in a JSON array and will be used to create the multisig wallet.
`multisig_desc` concatenates the descriptor in a JSON array and then it will be used to create the multisig wallet.

### 1.3 Create the Multisig Wallet

To create the multisig wallet, first create an empty one (no keys, HD seed and private keys disabled).

Then import the descriptor created in the previous step using the `importdescriptors` RPC.

After that, `getwalletinfo` can be used to check if the wallet was created successfully.
After that, `listdescriptors` can be used to check if the wallet was created successfully.

```bash
./build/bin/bitcoin rpc -signet createwallet "multisig_wallet_01" disable_private_keys=true blank=true
./build/bin/bitcoin rpc -signet -named createwallet wallet_name="multisig_wallet_01" disable_private_keys=true blank=true

./build/bin/bitcoin rpc -signet -rpcwallet="multisig_wallet_01" importdescriptors "$multisig_desc"

./build/bin/bitcoin rpc -signet -rpcwallet="multisig_wallet_01" getwalletinfo
./build/bin/bitcoin rpc -signet -rpcwallet="multisig_wallet_01" listdescriptors
```

The `<0;1>` notation in `desc` caused the creation of two descriptors. One uses the chain 0 for external addresses, and the other uses chain 1 for internal ones (change).

Once the wallets have already been created and this tutorial needs to be repeated or resumed, it is not necessary to recreate them, just load them with the command below:

```bash
Expand Down Expand Up @@ -199,7 +185,7 @@ psbt_2=$(./build/bin/bitcoin rpc -signet -rpcwallet="participant_2" walletproces
The PSBT, if signed separately by the co-signers, must be combined into one transaction before being finalized. This is done by `combinepsbt` RPC.

```bash
combined_psbt=$(./build/bin/bitcoin rpc -signet combinepsbt "[$psbt_1, $psbt_2]")
combined_psbt=$(./build/bin/bitcoin rpc -signet combinepsbt txs="[$psbt_1, $psbt_2]")
```

There is an RPC called `joinpsbts`, but it has a different purpose than `combinepsbt`. `joinpsbts` joins the inputs from multiple distinct PSBTs into one PSBT.
Expand Down
9 changes: 9 additions & 0 deletions doc/release-notes-32784.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Wallet
------

- A new `derivehdkey` RPC is available to obtain an xpub or xprv for a
derivation path with at least one hardened step from an HD key known to the
wallet. This can be used to coordinate a multisig setup, where each signer
shares an xpub using a
different derivation path than the default single-signature descriptors. The
example in `doc/multisig-tutorial.md` is updated to use this RPC. (#32784)
6 changes: 6 additions & 0 deletions doc/release-notes-32857.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Updated RPCs
------------

- The `send`, `sendall`, `walletprocesspsbt`, and `descriptorprocesspsbt` RPCs
now accept a `keypath_only` option that only signs the key path for taproot
inputs. (#32857)
5 changes: 5 additions & 0 deletions src/common/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ struct PSBTFillOptions {
* Whether to fill in bip32 derivation information if available.
*/
bool bip32_derivs{true};

/**
* Only sign the key path (for taproot inputs).
*/
bool taproot_keypath_only{false};
};

} // namespace common
Expand Down
91 changes: 91 additions & 0 deletions src/external_signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,40 @@ UniValue ExternalSigner::GetDescriptors(const int account)
return RunCommandParseJSON(Cat(m_command, Cat(Cat({"--fingerprint", m_fingerprint}, NetworkArg()), {"getdescriptors", "--account", strprintf("%d", account)})), "");
}

UniValue ExternalSigner::RegisterPolicy(const std::string& name, const std::string& descriptor_template, const std::vector<std::string>& keys_info) const
{
std::vector<std::string> command = Cat(m_command, Cat(Cat({"--fingerprint", m_fingerprint}, NetworkArg()), {"register", "--name", name, "--desc", descriptor_template}));
for (const std::string& key_info : keys_info) {
command.emplace_back("--key");
command.emplace_back(key_info);
}
return RunCommandParseJSON(command, "");
}

UniValue ExternalSigner::DisplayAddressPolicy(const std::string& name,
const std::string& descriptor_template,
const std::vector<std::string>& keys_info,
const std::optional<std::string>& hmac,
bool change,
uint32_t index) const
{
std::vector<std::string> command = Cat(m_command, Cat(Cat({"--fingerprint", m_fingerprint}, NetworkArg()),
{"displayaddress",
"--policy-name", name,
"--policy-desc", descriptor_template,
"--index", strprintf("%u", index)}));
if (hmac) {
command.emplace_back("--hmac");
command.emplace_back(*hmac);
}
for (const std::string& key_info : keys_info) {
command.emplace_back("--key");
command.emplace_back(key_info);
}
if (change) command.emplace_back("--change");
return RunCommandParseJSON(command, "");
}

bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::string& error)
{
// Serialize the PSBT
Expand Down Expand Up @@ -122,3 +156,60 @@ bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::str

return true;
}

bool ExternalSigner::SignTransactionPolicy(PartiallySignedTransaction& psbtx,
const std::string& name,
const std::string& descriptor_template,
const std::vector<std::string>& keys_info,
const std::optional<std::string>& hmac,
std::string& error)
{
// Serialize the PSBT
DataStream ssTx{};
ssTx << psbtx;

const std::vector<std::string> command = Cat(m_command, Cat({"--stdin", "--fingerprint", m_fingerprint}, NetworkArg()));

// Policy args travel on the same stdin line as `signtx <base64>`.
// HWI re-parses that line with shlex, which treats the apostrophes
// in hardened derivation markers (e.g. [f5acc2fd/87'/1'/0']xpub...)
// as quote characters, silently corrupting the keys and thereby the
// wallet policy id. Wrap each value in double quotes so it survives
// shlex intact; none of these values may themselves contain a double
// quote or backslash.
const auto quoted = [](const std::string& s) {
if (s.find_first_of("\"\\") != std::string::npos) {
throw std::runtime_error("Policy argument contains unsupported character: " + s);
}
return " \"" + s + "\"";
};
std::string stdinStr = "signtx " + EncodeBase64(ssTx.str())
+ " --policy-name" + quoted(name)
+ " --policy-desc" + quoted(descriptor_template);
if (hmac) {
stdinStr += " --hmac" + quoted(*hmac);
}
for (const std::string& key_info : keys_info) {
stdinStr += " --key" + quoted(key_info);
}

const UniValue signer_result = RunCommandParseJSON(command, stdinStr);

if (signer_result.find_value("error").isStr()) {
error = signer_result.find_value("error").get_str();
return false;
}
if (!signer_result.find_value("psbt").isStr()) {
error = "Unexpected result from signer";
return false;
}

util::Result<PartiallySignedTransaction> signer_psbtx = DecodeBase64PSBT(signer_result.find_value("psbt").get_str());
if (!signer_psbtx) {
error = strprintf("TX decode failed %s", util::ErrorString(signer_psbtx).original);
return false;
}

psbtx = *signer_psbtx;
return true;
}
48 changes: 48 additions & 0 deletions src/external_signer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <common/system.h>
#include <univalue.h>

#include <optional>
#include <string>
#include <vector>

Expand Down Expand Up @@ -52,18 +53,65 @@ class ExternalSigner
//! Must include a public key or xpub, as well as key origin.
UniValue DisplayAddress(const std::string& descriptor) const;

//! Display an address from a previously-registered BIP388 wallet policy.
//! Calls `<command> displayaddress --policy-name <name> --policy-desc <template>
//! --key <k> ... [--hmac <hex>] --index <index> [--change]`.
//! @param[in] name policy name to display on the signer
//! @param[in] descriptor_template BIP388 descriptor template (with @N placeholders)
//! @param[in] keys_info key with origin for each @N participant
//! @param[in] hmac optional hex hmac the device returned at registration time
//! @param[in] change whether to show the change-chain address
//! @param[in] index address index within the chain
//! @returns signer reply, expected to contain `address`
UniValue DisplayAddressPolicy(const std::string& name,
const std::string& descriptor_template,
const std::vector<std::string>& keys_info,
const std::optional<std::string>& hmac,
bool change,
uint32_t index) const;

//! Get receive and change Descriptor(s) from device for a given account.
//! Calls `<command> --fingerprint <fingerprint> --chain <chain> getdescriptors
//! --account <account>`.
//! @param[in] account which BIP32 account to use (e.g. `m/44'/0'/account'`)
//! @returns see doc/external-signer.md
UniValue GetDescriptors(int account);

//! Register BIP388 policy on the device.
//! Calls `<command> register` and passes the name, policy and key info
//! @param[in] name policy name to display on the signer
//! @param[in] descriptor_template BIP388 descriptor template
//! @param[in] keys_info key with origin for each participant
//! @returns optional hmac provided by the signer
UniValue RegisterPolicy(const std::string& name, const std::string& descriptor_template, const std::vector<std::string>& keys_info) const;

//! Sign PartiallySignedTransaction on the device.
//! Calls `<command> --stdin --fingerprint <fingerprint> --chain <chain>` and passes the
//! `signtx` command and PSBT via stdin.
//! @param[in,out] psbt PartiallySignedTransaction to be signed
bool SignTransaction(PartiallySignedTransaction& psbt, std::string& error);

//! Sign PartiallySignedTransaction on the device, scoped to a
//! previously registered BIP388 wallet policy. Used for non-default
//! descriptors (e.g. MuSig2) that require an on-device policy
//! registration before signing.
//!
//! Pipes `signtx <base64> --policy-name <name> --policy-desc <t>
//! [--hmac <hex>] --key <k> ...` to the signer's stdin (the leading
//! `signtx <base64>` matches `SignTransaction`).
//!
//! @param[in,out] psbt PSBT to be signed
//! @param[in] name policy name shown on the signer
//! @param[in] descriptor_template BIP388 descriptor template
//! @param[in] keys_info key with origin for each `@N`
//! @param[in] hmac optional hex hmac returned at registration
//! @param[out] error populated on failure
bool SignTransactionPolicy(PartiallySignedTransaction& psbt,
const std::string& name,
const std::string& descriptor_template,
const std::vector<std::string>& keys_info,
const std::optional<std::string>& hmac,
std::string& error);
};

#endif // BITCOIN_EXTERNAL_SIGNER_H
4 changes: 4 additions & 0 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <type_traits>
Expand Down Expand Up @@ -131,6 +132,9 @@ class Wallet
//! Display address on external signer
virtual util::Result<void> displayAddress(const CTxDestination& dest) = 0;

//! Register BIP388 policy on external signer, store and return optional hmac
virtual util::Result<std::optional<std::string>> registerPolicy(const std::optional<std::string>& name) = 0;

//! Lock coin.
virtual bool lockCoin(const COutPoint& output, bool write_to_db) = 0;

Expand Down
Loading
Loading