hsmd: find correct P2TR key for utxo
In the case where we receive a taproot utxo we want to be able to tell if it was derived using a BIP32 seed or a BIP86 seed. Considering we will only be supporting BI86 type wallet addresses for mnemonics we can check if the out secret is 64 bytes long and if it is we can use our BIP86 for the withdrawal.
This commit is contained in:
committed by
Rusty Russell
parent
618d4f3377
commit
1b3e881d5a
@@ -557,3 +557,14 @@ size_t hsm_secret_size(const struct hsm_secret *hsm)
|
||||
return tal_bytelen(hsm->secret_data);
|
||||
return sizeof(hsm->secret);
|
||||
}
|
||||
|
||||
bool is_mnemonic_secret(size_t secret_len)
|
||||
{
|
||||
return secret_len == HSM_SECRET_MNEMONIC_SIZE;
|
||||
}
|
||||
|
||||
bool use_bip86_derivation(size_t secret_len)
|
||||
{
|
||||
/* BIP86 was introduced alongside mnemonic support, so they're available together */
|
||||
return is_mnemonic_secret(secret_len);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,19 @@ const u8 *hsm_secret_bytes(const struct hsm_secret *hsm);
|
||||
*/
|
||||
size_t hsm_secret_size(const struct hsm_secret *hsm);
|
||||
|
||||
/**
|
||||
* Check if this HSM secret is mnemonic-based (64-byte seed).
|
||||
* Returns true for mnemonic-derived secrets, false for legacy 32-byte secrets.
|
||||
*/
|
||||
bool is_mnemonic_secret(size_t secret_len);
|
||||
|
||||
/**
|
||||
* Check if we should use BIP86 derivation for this HSM secret.
|
||||
* BIP86 was introduced alongside mnemonic support, so they're available together.
|
||||
* Returns true if mnemonic-based secret is available, false otherwise.
|
||||
*/
|
||||
bool use_bip86_derivation(size_t secret_len);
|
||||
|
||||
/**
|
||||
* Checks whether the hsm_secret data requires a passphrase to decrypt.
|
||||
* Handles legacy, encrypted, and mnemonic-based formats.
|
||||
|
||||
@@ -696,7 +696,7 @@ static struct io_plan *handle_derive_bip86_key(struct io_conn *conn,
|
||||
return bad_req(conn, c, msg_in);
|
||||
|
||||
/* Check if we have a mnemonic-based HSM secret */
|
||||
if (hsm_secret_size(&hsm_secret) != 64) {
|
||||
if (!use_bip86_derivation(hsm_secret_size(&hsm_secret))) {
|
||||
return bad_req_fmt(conn, c, msg_in,
|
||||
"BIP86 derivation requires mnemonic-based HSM secret");
|
||||
}
|
||||
@@ -724,7 +724,7 @@ static struct io_plan *handle_check_bip86_pubkey(struct io_conn *conn,
|
||||
return bad_req(conn, c, msg_in);
|
||||
|
||||
/* Check if we have a mnemonic-based HSM secret */
|
||||
if (hsm_secret_size(&hsm_secret) != 64) {
|
||||
if (!use_bip86_derivation(hsm_secret_size(&hsm_secret))) {
|
||||
return bad_req_fmt(conn, c, msg_in,
|
||||
"BIP86 derivation requires mnemonic-based HSM secret");
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
#include <bitcoin/script.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/bolt12_id.h>
|
||||
#include <common/bolt12_merkle.h>
|
||||
#include <common/hash_u5.h>
|
||||
#include <common/hsm_secret.h>
|
||||
#include <common/key_derive.h>
|
||||
#include <common/lease_rates.h>
|
||||
#include <common/memleak.h>
|
||||
@@ -542,8 +544,32 @@ static void hsm_key_for_utxo(struct privkey *privkey, struct pubkey *pubkey,
|
||||
hsmd_status_debug("Derived public key %s from unilateral close",
|
||||
fmt_pubkey(tmpctx, pubkey));
|
||||
} else {
|
||||
/* Simple case: just get derive via HD-derivation */
|
||||
bitcoin_key(privkey, pubkey, utxo->keyindex);
|
||||
/* Check if this is a BIP86 UTXO by examining the scriptPubkey */
|
||||
const size_t script_len = tal_bytelen(utxo->scriptPubkey);
|
||||
bool is_bip86 = false;
|
||||
|
||||
/* For P2TR scripts, we need to determine if it's BIP86 or regular P2TR
|
||||
* But BIP86 derivation requires mnemonic-based secrets */
|
||||
if (is_p2tr(utxo->scriptPubkey, script_len, NULL) &&
|
||||
use_bip86_derivation(secretstuff.bip32_seed_len)) {
|
||||
/* Try BIP86 derivation first and see if it matches */
|
||||
struct pubkey test_pubkey;
|
||||
bip86_key(NULL, &test_pubkey, utxo->keyindex);
|
||||
|
||||
/* Create P2TR scriptpubkey from BIP86 key and compare */
|
||||
const u8 *bip86_script = scriptpubkey_p2tr(tmpctx, &test_pubkey);
|
||||
if (memeq(utxo->scriptPubkey, script_len, bip86_script, tal_bytelen(bip86_script))) {
|
||||
is_bip86 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_bip86) {
|
||||
/* Use BIP86 derivation */
|
||||
bip86_key(privkey, pubkey, utxo->keyindex);
|
||||
} else {
|
||||
/* Simple case: just get derive via HD-derivation */
|
||||
bitcoin_key(privkey, pubkey, utxo->keyindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user