wallet/hsmd: fix signmessagewithkey for BIP86 wallets

The signmessagewithkey RPC was failing for BIP86 (mnemonic-based)
wallets because:

1. The wallet RPC was iterating through BIP32-derived addresses only,
   so it couldn't find BIP86-derived addresses.

2. The HSM's handle_bip137_sign_message always used bitcoin_key()
   (BIP32 derivation) regardless of wallet type.
This commit is contained in:
Sangbida Chaudhuri
2026-01-14 08:24:20 +10:30
committed by Rusty Russell
parent c17590379e
commit 5fdc56c544
3 changed files with 18 additions and 27 deletions

View File

@@ -767,8 +767,12 @@ static u8 *handle_bip137_sign_message(struct hsmd_client *c, const u8 *msg_in)
sha256_update(&sctx, msg, msg_len);
sha256_double_done(&sctx, &shad);
/* get the private key BIP32 */
bitcoin_key(&privkey, &pubkey, keyidx);
/* Get the private key using appropriate derivation method */
if (use_bip86_derivation(tal_bytelen(secretstuff.bip32_seed))) {
bip86_key(&privkey, &pubkey, keyidx);
} else {
bitcoin_key(&privkey, &pubkey, keyidx);
}
if (!secp256k1_ecdsa_sign_recoverable(
secp256k1_ctx, &rsig, shad.sha.u.u8, privkey.secret.data, NULL,

View File

@@ -911,6 +911,7 @@ static struct wallet *create_test_wallet(struct lightningd *ld, const tal_t *ctx
w->ld = ld;
ld->wallet = w;
ld->bip86_base = NULL;
ld->bip32_base = tal(ld, struct ext_key);
CHECK(bip32_key_from_seed(badseed, sizeof(badseed),
BIP32_VER_TEST_PRIVATE, 0,

View File

@@ -1282,38 +1282,24 @@ json_signmessagewithkey(struct command *cmd, const char *buffer,
"HSM does not support signing BIP137 signing.");
}
const u32 bip32_max_index =
db_get_intvar(cmd->ld->wallet->db, "bip32_max_index", 0);
bool match_found = false;
u32 keyidx;
enum addrtype addrtype;
enum addrtype addrtype;
/* loop over all generated keys, find a matching key */
for (keyidx = 1; keyidx <= bip32_max_index; keyidx++) {
bip32_pubkey(cmd->ld, &pubkey, keyidx);
u8 *redeemscript_p2wpkh;
char *out_p2wpkh = encode_pubkey_to_addr(
cmd, &pubkey, ADDR_BECH32, &redeemscript_p2wpkh);
if (!out_p2wpkh) {
abort();
}
/* wallet_get_addrtype fails for entries prior to v24.11, all
* address types are assumed in that case. */
if (!wallet_get_addrtype(cmd->ld->wallet, keyidx, &addrtype))
addrtype = ADDR_ALL;
if (streq(addr, out_p2wpkh) &&
(addrtype == ADDR_BECH32 || addrtype == ADDR_ALL)) {
match_found = true;
break;
}
}
if (!match_found) {
/* Use wallet_can_spend which handles both BIP32 and BIP86 addresses */
if (!wallet_can_spend(cmd->ld->wallet, scriptpubkey, script_len,
&keyidx, &addrtype)) {
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
"Address is not found in the wallet's database");
}
/* Derive the pubkey for the found key index */
if (cmd->ld->bip86_base) {
bip86_pubkey(cmd->ld, &pubkey, keyidx);
} else {
bip32_pubkey(cmd->ld, &pubkey, keyidx);
}
/* wire to hsmd a sign request */
u8 *msg = towire_hsmd_bip137_sign_message(
cmd, tal_dup_arr(tmpctx, u8, (u8 *)message, strlen(message), 0),