Skip to content

Commit dc55531

Browse files
committed
wallet: compare address returned by displayaddress
Update external signer documentation to reflect this requirement, which HWI already implements.
1 parent 6c1a2cc commit dc55531

File tree

7 files changed

+28
-16
lines changed

7 files changed

+28
-16
lines changed

doc/external-signer.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ Example, display the first native SegWit receive address on Testnet:
150150

151151
The command MUST be able to figure out the address type from the descriptor.
152152

153+
The command MUST return an object containing `{"address": "[the address]"}`.
154+
As a sanity check, for devices that support this, it SHOULD ask the device to derive the address.
155+
153156
If <descriptor> contains a master key fingerprint, the command MUST fail if it does not match the fingerprint known by the device.
154157

155158
If <descriptor> contains an xpub, the command MUST fail if it does not match the xpub known by the device.

src/wallet/external_signer_scriptpubkeyman.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <wallet/external_signer_scriptpubkeyman.h>
1010

1111
#include <iostream>
12+
#include <key_io.h>
1213
#include <memory>
1314
#include <stdexcept>
1415
#include <string>
@@ -51,15 +52,19 @@ ExternalSigner ExternalSignerScriptPubKeyMan::GetExternalSigner() {
5152
return signers[0];
5253
}
5354

54-
bool ExternalSignerScriptPubKeyMan::DisplayAddress(const CScript scriptPubKey, const ExternalSigner &signer) const
55+
bool ExternalSignerScriptPubKeyMan::DisplayAddress(const CTxDestination& dest, const ExternalSigner &signer) const
5556
{
5657
// TODO: avoid the need to infer a descriptor from inside a descriptor wallet
58+
const CScript& scriptPubKey = GetScriptForDestination(dest);
5759
auto provider = GetSolvingProvider(scriptPubKey);
5860
auto descriptor = InferDescriptor(scriptPubKey, *provider);
5961

60-
signer.DisplayAddress(descriptor->ToString());
61-
// TODO inspect result
62-
return true;
62+
const UniValue& result = signer.DisplayAddress(descriptor->ToString());
63+
64+
const UniValue& ret_address = result.find_value("address");
65+
if (!ret_address.isStr()) return false;
66+
67+
return ret_address.getValStr() == EncodeDestination(dest);
6368
}
6469

6570
// If sign is true, transaction must previously have been filled

src/wallet/external_signer_scriptpubkeyman.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class ExternalSignerScriptPubKeyMan : public DescriptorScriptPubKeyMan
2727

2828
static ExternalSigner GetExternalSigner();
2929

30-
bool DisplayAddress(const CScript scriptPubKey, const ExternalSigner &signer) const;
30+
bool DisplayAddress(const CTxDestination& dest, const ExternalSigner &signer) const;
3131

3232
TransactionError FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr, bool finalize = true) const override;
3333
};

src/wallet/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2676,7 +2676,7 @@ bool CWallet::DisplayAddress(const CTxDestination& dest)
26762676
continue;
26772677
}
26782678
ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
2679-
return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2679+
return signer_spk_man->DisplayAddress(dest, signer);
26802680
}
26812681
return false;
26822682
}

src/wallet/wallet.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,10 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
537537
bool IsSpentKey(const CScript& scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
538538
void SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
539539

540-
/** Display address on an external signer. Returns false if external signer support is not compiled */
540+
/** Display address on an external signer.
541+
* Returns false if the signer does not respond with a matching address.
542+
* Returns false if external signer support is not compiled.
543+
*/
541544
bool DisplayAddress(const CTxDestination& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
542545

543546
bool IsLockedCoin(const COutPoint& output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);

test/functional/mocks/signer.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,19 @@ def getdescriptors(args):
4141

4242

4343
def displayaddress(args):
44-
# Several descriptor formats are acceptable, so allowing for potential
45-
# changes to InferDescriptor:
4644
if args.fingerprint != "00000001":
4745
return sys.stdout.write(json.dumps({"error": "Unexpected fingerprint", "fingerprint": args.fingerprint}))
4846

49-
expected_desc = [
50-
"wpkh([00000001/84h/1h/0h/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#3te6hhy7",
51-
"tr([00000001/86h/1h/0h/0/0]c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#puqqa90m",
52-
]
47+
expected_desc = {
48+
"wpkh([00000001/84h/1h/0h/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#3te6hhy7": "bcrt1qm90ugl4d48jv8n6e5t9ln6t9zlpm5th68x4f8g",
49+
"sh(wpkh([00000001/49h/1h/0h/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7))#kz9y5w82": "2N2gQKzjUe47gM8p1JZxaAkTcoHPXV6YyVp",
50+
"pkh([00000001/44h/1h/0h/0/0]02c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#q3pqd8wh": "n1LKejAadN6hg2FrBXoU1KrwX4uK16mco9",
51+
"tr([00000001/86h/1h/0h/0/0]c97dc3f4420402e01a113984311bf4a1b8de376cac0bdcfaf1b3ac81f13433c7)#puqqa90m": "tb1phw4cgpt6cd30kz9k4wkpwm872cdvhss29jga2xpmftelhqll62mscq0k4g",
52+
}
5353
if args.desc not in expected_desc:
5454
return sys.stdout.write(json.dumps({"error": "Unexpected descriptor", "desc": args.desc}))
5555

56-
return sys.stdout.write(json.dumps({"address": "bcrt1qm90ugl4d48jv8n6e5t9ln6t9zlpm5th68x4f8g"}))
56+
return sys.stdout.write(json.dumps({"address": expected_desc[args.desc]}))
5757

5858
def signtx(args):
5959
if args.fingerprint != "00000001":

test/functional/wallet_signer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,9 @@ def test_valid_signer(self):
130130
assert_equal(address_info['hdkeypath'], "m/86h/1h/0h/0/0")
131131

132132
self.log.info('Test walletdisplayaddress')
133-
result = hww.walletdisplayaddress(address1)
134-
assert_equal(result, {"address": address1})
133+
for address in [address1, address2, address3]:
134+
result = hww.walletdisplayaddress(address)
135+
assert_equal(result, {"address": address})
135136

136137
# Handle error thrown by script
137138
self.set_mock_result(self.nodes[1], "2")

0 commit comments

Comments
 (0)