From 249fa03674078b106f6a2f8919656f6b6639e0aa Mon Sep 17 00:00:00 2001 From: Sangbida Chaudhuri <101164840+sangbida@users.noreply.github.com> Date: Fri, 24 Oct 2025 13:57:47 +1030 Subject: [PATCH] lightningd: scan outputs for BIP86 addresses This commit fixes an issue where BIP86 addresses were not being discovered during wallet recovery/rescan operations. The root cause was that init_txfilter() only populated the transaction filter with BIP32-derived keys, preventing lightningd from recognizing BIP86 UTXOs during blockchain scans. Now both BIP32 and BIP86 derived scripts are included in the filter when BIP86 derivation is enabled. This ensures that wallets restored from BIP39 mnemonics can properly discover and display previously funded BIP86 addresses without requiring manual address generation first. [ We also move the slightly-lost comment about libbacktrace so it is where we actually include --RR ] --- common/daemon.c | 3 +++ lightningd/lightningd.c | 20 +++++++++++++++----- lightningd/test/run-find_my_abspath.c | 6 ++++++ wallet/wallet.c | 18 +++++++++++++++++- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/common/daemon.c b/common/daemon.c index c3adac2a0..651582838 100644 --- a/common/daemon.c +++ b/common/daemon.c @@ -1,5 +1,8 @@ #include "config.h" #include +/*~ This is Ian Lance Taylor's libbacktrace. It turns out that it's + * horrifically difficult to obtain a decent backtrace in C; the standard + * backtrace function is useless in most programs. */ #include #include #include diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index f5128229c..fda955dfa 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -21,9 +21,8 @@ * before anything else. */ #include "config.h" -/*~ This is Ian Lance Taylor's libbacktrace. It turns out that it's - * horrifically difficult to obtain a decent backtrace in C; the standard - * backtrace function is useless in most programs. */ +/*~ Various bitcoin-related helpers live in the bitcoin/ directory */ +#include /*~ These headers are from CCAN: http://ccodearchive.net. * @@ -56,8 +55,8 @@ #include #include #include -#include +#include #include #include #include @@ -676,7 +675,7 @@ static void init_txfilter(struct wallet *w, struct ext_key ext; /*~ Note the use of ccan/short_types u64 rather than uint64_t. * Thank me later. */ - u64 bip32_max_index; + u64 bip32_max_index, bip86_max_index; bip32_max_index = db_get_intvar(w->db, "bip32_max_index", 0); /*~ One of the C99 things I unequivocally approve: for-loop scope. */ @@ -686,6 +685,17 @@ static void init_txfilter(struct wallet *w, } txfilter_add_derkey(filter, ext.pub_key); } + + /* If BIP86 is enabled, also add BIP86-derived keys to the filter */ + if (w->ld->bip86_base) { + bip86_max_index = db_get_intvar(w->db, "bip86_max_index", 0); + for (u64 i = 0; i <= bip86_max_index + w->keyscan_gap; i++) { + struct pubkey pubkey; + bip86_pubkey(w->ld, &pubkey, i); + u8 *script = scriptpubkey_p2tr(tmpctx, &pubkey); + txfilter_add_scriptpubkey(filter, take(script)); + } + } } /*~ The normal advice for daemons is to move into the root directory, so you diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 7f15dc1b8..995322590 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -227,6 +227,12 @@ struct wallet *wallet_new(struct lightningd *ld UNNEEDED, struct timers *timers /* Generated stub for wallet_sanity_check */ bool wallet_sanity_check(struct wallet *w UNNEEDED) { fprintf(stderr, "wallet_sanity_check called!\n"); abort(); } +/* Generated stub for bip86_pubkey */ +void bip86_pubkey(struct lightningd *ld UNNEEDED, struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED) +{ fprintf(stderr, "bip86_pubkey called!\n"); abort(); } +/* Generated stub for txfilter_add_scriptpubkey */ +void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES UNNEEDED) +{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ struct logger *crashlog; diff --git a/wallet/wallet.c b/wallet/wallet.c index e76192983..0e0d5a032 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -148,6 +148,12 @@ static void our_addresses_add_for_index(struct wallet *w, u32 i) /* FIXME: We could deprecate P2SH once we don't see * any, since we stopped publishing them in 24.02 */ if (!wallet_get_addrtype(w, i, &addrtype)) { + if (w->ld->bip86_base) { + /* Derive and add BIP86 script for this index */ + our_addresses_add_bip86_for_index(w, i); + return; + } + const u8 *addr; scriptpubkey = scriptpubkey_p2wpkh_derkey(NULL, ext.pub_key); addr = scriptpubkey_p2sh(NULL, scriptpubkey); @@ -205,7 +211,17 @@ static void our_addresses_init(struct wallet *w) w->our_addresses_maxindex = 0; w->our_addresses = new_htable(w, wallet_address_htable); - our_addresses_add_for_index(w, w->our_addresses_maxindex); + /* If BIP86 is enabled, prefill the address table up to keyscan_gap so + * rescans immediately include BIP86 scripts without needing prior + * address allocations. */ + if (w->ld->bip86_base) { + for (u32 i = 0; i <= w->keyscan_gap; i++) { + our_addresses_add_for_index(w, i); + } + w->our_addresses_maxindex = w->keyscan_gap; + } else { + our_addresses_add_for_index(w, w->our_addresses_maxindex); + } } static void outpointfilters_init(struct wallet *w)