wallet: handle null currency fields, skip & warn on mismatch.
What changed, and why it matters
This commit fixes a database migration crash in Core Lightning. When upgrading, the migration code could hit a NULL currency field and abort with a 'BROKEN' error. The patch lets the migration tolerate NULL currencies and also skips any records that use an unexpected foreign currency, logging a warning instead of crashing. It is a robustness fix for an unusual upgrade path, not a typical remote attack vector.
Treat as a routine bug-fix patch. Users on affected master builds should upgrade before migrating. No urgent security response is indicated, but verify that migration logs do not show unexpected skipped foreign-currency events.
Security signals we found
NULL pointer / null-column access prevented
Migration robustness improvement
Foreign-currency event skipped rather than processed
No explicit security framing by vendor
Evidence from the diff
The change modifies wallet/account_migration.c. It replaces db_col_strdup with db_col_strdup_optional for the currency column in both chain_event and channel_event parsing, preventing an abort on NULL currency values. It then adds checks during migration: if ev->currency is non-NULL and does not match chainparams->lightning_hrp, the event is skipped with a log_broken warning. This avoids migration failures for users who may have manually injected events with alternate currencies while running development (‘master’) builds.
Changed components
wallet/account_migration.cchain_event parsingchannel_event parsingmigrate_from_account_dbInspect captured patch +22 / −2
diff --git a/wallet/account_migration.c b/wallet/account_migration.c
index f22c6693..a4bf08d1 100644
--- a/wallet/account_migration.c
+++ b/wallet/account_migration.c
@@ -105,7 +105,7 @@ static struct chain_event *stmt2chain_event(const tal_t *ctx, struct db_stmt *st
e->debit = db_col_amount_msat(stmt, "e.debit");
e->output_value = db_col_amount_msat(stmt, "e.output_value");
- e->currency = db_col_strdup(e, stmt, "e.currency");
+ e->currency = db_col_strdup_optional(e, stmt, "e.currency");
e->timestamp = db_col_u64(stmt, "e.timestamp");
e->blockheight = db_col_int(stmt, "e.blockheight");
@@ -270,7 +270,7 @@ static struct channel_event *stmt2channel_event(const tal_t *ctx, struct db_stmt
e->debit = db_col_amount_msat(stmt, "e.debit");
e->fees = db_col_amount_msat(stmt, "e.fees");
- e->currency = db_col_strdup(e, stmt, "e.currency");
+ e->currency = db_col_strdup_optional(e, stmt, "e.currency");
if (!db_col_is_null(stmt, "e.payment_id")) {
e->payment_id = tal(e, struct sha256);
db_col_sha256(stmt, "e.payment_id", e->payment_id);
@@ -404,6 +404,16 @@ void migrate_from_account_db(struct lightningd *ld, struct db *db)
struct amount_sat output_sat;
u64 id;
+ /* We removed currency support, because the only way you could
+ * use it was to inject your own events, and nobody did that
+ * and it would be a nightmare to support */
+ if (ev->currency
+ && !streq(ev->currency, chainparams->lightning_hrp)) {
+ log_broken(ld->log, "IGNORING foreign currency chain event (%s, currency %s)",
+ ev->tag, ev->currency);
+ continue;
+ }
+
stmt = db_prepare_v2(db,
SQL("INSERT INTO chain_moves ("
" id,"
@@ -483,6 +493,16 @@ void migrate_from_account_db(struct lightningd *ld, struct db *db)
enum mvt_tag tag;
u64 id;
+ /* We removed currency support, because the only way you could
+ * use it was to inject your own events, and nobody did that
+ * and it would be a nightmare to support */
+ if (ev->currency
+ && !streq(ev->currency, chainparams->lightning_hrp)) {
+ log_broken(ld->log, "IGNORING foreign currency channel event (%s, currency %s)",
+ ev->tag, ev->currency);
+ continue;
+ }
+
stmt = db_prepare_v2(db,
SQL("INSERT INTO channel_moves ("
" id,"
Why this scored 22/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.