wallet: scaffold BIP86 addrtype
What changed, and why it matters
This commit is a small, preparatory code change that adds a new internal label for a future type of Bitcoin address (BIP86-style taproot). It does not implement the feature, change how money is handled, or fix any bug. There is no security issue visible in this patch.
No action needed; this is a benign feature-scaffolding commit. Continue normal review when the follow-up BIP86 implementation arrives.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch scaffolds UTXO_P2TR_BIP86 and ADDR_P2TR_MNEMONIC constants, adds a string conversion, updates a witness-weight switch, stubs out address generation for the new type, and adjusts test stubs. The actual BIP86 derivation and wallet functions are explicitly noted as ‘not yet implemented’. No cryptographic logic, parsing, validation, or spending paths are meaningfully altered.
Changed components
wallet address type definitionsbitcoin transaction input witness weight calculationwallet RPC address encodingwallet test stubsInspect captured patch +24 / −6
diff --git a/bitcoin/tx.c b/bitcoin/tx.c
index 4c1a63de..e03b98b3 100644
--- a/bitcoin/tx.c
+++ b/bitcoin/tx.c
@@ -940,6 +940,7 @@ size_t bitcoin_tx_input_witness_weight(enum utxotype utxotype)
/* In practice, these predate anchors, so: */
return 1 + 1 + bitcoin_tx_input_sig_weight();
case UTXO_P2TR:
+ case UTXO_P2TR_BIP86:
return 1 + 64;
}
abort();
diff --git a/bitcoin/tx.h b/bitcoin/tx.h
index 4b7134e0..4690b6fb 100644
--- a/bitcoin/tx.h
+++ b/bitcoin/tx.h
@@ -53,6 +53,8 @@ enum utxotype {
UTXO_P2WSH_FROM_CLOSE = 3,
/* "p2tr" addresses. */
UTXO_P2TR = 4,
+ /* "bip86" addresses (P2TR with BIP86 derivation). */
+ UTXO_P2TR_BIP86 = 5,
};
struct bitcoin_tx_output *new_tx_output(const tal_t *ctx,
diff --git a/common/utxo.c b/common/utxo.c
index ca978c50..f94c85ae 100644
--- a/common/utxo.c
+++ b/common/utxo.c
@@ -46,6 +46,8 @@ const char *utxotype_to_str(enum utxotype utxotype)
return "p2wsh_from_close";
case UTXO_P2TR:
return "p2tr";
+ case UTXO_P2TR_BIP86:
+ return "p2tr_bip86";
}
abort();
}
diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c
index c3d04111..d3087ccc 100644
--- a/wallet/test/run-wallet.c
+++ b/wallet/test/run-wallet.c
@@ -327,9 +327,6 @@ bool fromwire_hsmd_client_hsmfd_reply(const void *p UNNEEDED)
/* Generated stub for fromwire_hsmd_cupdate_sig_reply */
bool fromwire_hsmd_cupdate_sig_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **cu UNNEEDED)
{ fprintf(stderr, "fromwire_hsmd_cupdate_sig_reply called!\n"); abort(); }
-/* Generated stub for fromwire_hsmd_derive_bip86_key_reply */
-bool fromwire_hsmd_derive_bip86_key_reply(const void *p UNNEEDED, struct ext_key *bip86_base UNNEEDED)
-{ fprintf(stderr, "fromwire_hsmd_derive_bip86_key_reply called!\n"); abort(); }
/* Generated stub for fromwire_hsmd_derive_secret_reply */
bool fromwire_hsmd_derive_secret_reply(const void *p UNNEEDED, struct secret *secret UNNEEDED)
{ fprintf(stderr, "fromwire_hsmd_derive_secret_reply called!\n"); abort(); }
@@ -711,9 +708,6 @@ u8 *towire_hsmd_client_hsmfd(const tal_t *ctx UNNEEDED, const struct node_id *id
/* Generated stub for towire_hsmd_cupdate_sig_req */
u8 *towire_hsmd_cupdate_sig_req(const tal_t *ctx UNNEEDED, const u8 *cu UNNEEDED)
{ fprintf(stderr, "towire_hsmd_cupdate_sig_req called!\n"); abort(); }
-/* Generated stub for towire_hsmd_derive_bip86_key */
-u8 *towire_hsmd_derive_bip86_key(const tal_t *ctx UNNEEDED, u32 index UNNEEDED, bool is_change UNNEEDED)
-{ fprintf(stderr, "towire_hsmd_derive_bip86_key called!\n"); abort(); }
/* Generated stub for towire_hsmd_derive_secret */
u8 *towire_hsmd_derive_secret(const tal_t *ctx UNNEEDED, const u8 *info UNNEEDED)
{ fprintf(stderr, "towire_hsmd_derive_secret called!\n"); abort(); }
@@ -802,6 +796,14 @@ u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct n
{
return NULL;
}
+u8 *towire_hsmd_derive_bip86_key(const tal_t *ctx UNNEEDED, u32 index UNNEEDED, bool is_change UNNEEDED)
+{
+ return NULL;
+}
+bool fromwire_hsmd_derive_bip86_key_reply(const void *p UNNEEDED, struct ext_key *bip86_base UNNEEDED)
+{
+ return true;
+}
bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED)
{
return true;
diff --git a/wallet/wallet.c b/wallet/wallet.c
index 50d9ac7d..3a53ba70 100644
--- a/wallet/wallet.c
+++ b/wallet/wallet.c
@@ -169,6 +169,9 @@ static void our_addresses_add_for_index(struct wallet *w, u32 i)
tal_bytelen(scriptpubkey),
ADDR_P2TR);
return;
+ case ADDR_P2TR_MNEMONIC:
+ /* BIP86 addresses not yet implemented */
+ return;
}
abort();
}
@@ -3186,6 +3189,9 @@ static void got_utxo(struct wallet *w,
case ADDR_P2TR:
utxo->utxotype = UTXO_P2TR;
goto type_ok;
+ case ADDR_P2TR_MNEMONIC:
+ utxo->utxotype = UTXO_P2TR_BIP86;
+ goto type_ok;
case ADDR_ALL:
break;
}
diff --git a/wallet/wallet.h b/wallet/wallet.h
index 56f61b28..81bbe2c7 100644
--- a/wallet/wallet.h
+++ b/wallet/wallet.h
@@ -283,6 +283,7 @@ enum addrtype {
ADDR_P2SH_SEGWIT = 1,
ADDR_BECH32 = 2,
ADDR_P2TR = 4,
+ ADDR_P2TR_MNEMONIC = 8,
ADDR_ALL = (ADDR_BECH32 + ADDR_P2TR)
};
@@ -295,6 +296,9 @@ static inline enum addrtype wallet_addrtype_in_db(enum addrtype t)
case ADDR_P2TR:
BUILD_ASSERT(ADDR_P2TR == 4);
return t;
+ case ADDR_P2TR_MNEMONIC:
+ BUILD_ASSERT(ADDR_P2TR_MNEMONIC == 8);
+ return t;
case ADDR_ALL:
BUILD_ASSERT(ADDR_ALL == 6);
return t;
diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c
index a39f6851..e8fbdb1a 100644
--- a/wallet/walletrpc.c
+++ b/wallet/walletrpc.c
@@ -50,6 +50,7 @@ encode_pubkey_to_addr(const tal_t *ctx,
ok = segwit_addr_encode(out, hrp, 0, h160.u.u8, sizeof(h160));
goto done;
+ case ADDR_P2TR_MNEMONIC:
case ADDR_P2TR: {
u8 *p2tr_spk = scriptpubkey_p2tr(ctx, pubkey);
u8 *x_key = p2tr_spk + 2;
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.