wallet: Cache the max_index for bip32 and bip86 address indices
What changed, and why it matters
This commit is a straightforward performance optimization. It caches two address-index values in memory instead of reading them from the database twice for every transaction output in every scanned block. The change fixes a slowdown during blockchain scans and does not alter security behavior.
No security action required. Treat as a normal performance fix.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch adds bip32_max_index and bip86_max_index fields to the struct wallet and initializes them once from database intvars in wallet_new(). wallet_can_spend() now reads these cached values instead of calling db_get_intvar() twice per invocation, and updates both the in-memory cache and the persisted intvar when a larger address index is discovered. The logic and security checks remain identical; only redundant database lookups are removed.
Changed components
wallet/wallet.cwallet/wallet.hInspect captured patch +15 / −5
diff --git a/wallet/wallet.c b/wallet/wallet.c
index 91eb507..7c54ad1 100644
--- a/wallet/wallet.c
+++ b/wallet/wallet.c
@@ -231,6 +231,9 @@ struct wallet *wallet_new(struct lightningd *ld, struct timers *timers)
our_addresses_init(wallet);
trace_span_end(wallet);
+ wallet->bip32_max_index = db_get_intvar(wallet->db, "bip32_max_index", 0);
+ wallet->bip86_max_index = db_get_intvar(wallet->db, "bip86_max_index", 0);
+
db_commit_transaction(wallet->db);
return wallet;
}
@@ -1030,9 +1033,8 @@ bool wallet_can_spend(struct wallet *w, const u8 *script, size_t script_len,
const struct wallet_address *waddr;
struct script_with_len scriptwl = {script, script_len};
- /* Update hash table if we need to */
- bip32_max_index = db_get_intvar(w->db, "bip32_max_index", 0);
- bip86_max_index = db_get_intvar(w->db, "bip86_max_index", 0);
+ bip32_max_index = w->bip32_max_index;
+ bip86_max_index = w->bip86_max_index;
/* Scan both BIP32 and BIP86 addresses */
u64 max_index = (bip32_max_index > bip86_max_index) ? bip32_max_index : bip86_max_index;
@@ -1047,12 +1049,16 @@ bool wallet_can_spend(struct wallet *w, const u8 *script, size_t script_len,
* remember that. */
if (w->ld->bip86_base) {
/* BIP86-based wallet: all addresses use BIP86 derivation */
- if (waddr->index > bip86_max_index)
+ if (waddr->index > bip86_max_index) {
+ w->bip86_max_index = waddr->index;
db_set_intvar(w->db, "bip86_max_index", waddr->index);
+ }
} else {
/* Legacy wallet: all addresses use BIP32 derivation */
- if (waddr->index > bip32_max_index)
+ if (waddr->index > bip32_max_index) {
db_set_intvar(w->db, "bip32_max_index", waddr->index);
+ w->bip32_max_index = waddr->index;
+ }
}
*index = waddr->index;
diff --git a/wallet/wallet.h b/wallet/wallet.h
index 504e49a..c110b8b 100644
--- a/wallet/wallet.h
+++ b/wallet/wallet.h
@@ -56,6 +56,10 @@ struct wallet {
/* How many keys should we look ahead at most? */
u64 keyscan_gap;
+
+ /* Address lookahead max index. */
+ u64 bip32_max_index;
+ u64 bip86_max_index;
};
static inline enum output_status output_status_in_db(enum output_status s)
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.