Skip to content

Commit 8f9cdeb

Browse files
committed
wallet: add optional sql and functions to downgrade db.
This will allow a downgrade tool to attempt to downgrade a node to the previous version. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 55d622b commit 8f9cdeb

File tree

1 file changed

+63
-5
lines changed

1 file changed

+63
-5
lines changed

wallet/db.c

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
struct migration {
2121
const char *sql;
2222
void (*func)(struct lightningd *ld, struct db *db);
23+
const char *revertsql;
24+
/* If non-NULL, returns string explaining why downgrade is impossible */
25+
const char *(*revertfn)(const tal_t *ctx, struct db *db);
2326
};
2427

2528
static void migrate_pr2342_feerate_per_channel(struct lightningd *ld, struct db *db);
@@ -87,6 +90,9 @@ static void migrate_initialize_channel_htlcs_wait_indexes_and_fixup_forwards(str
8790
static void migrate_fail_pending_payments_without_htlcs(struct lightningd *ld,
8891
struct db *db);
8992

93+
static const char *revert_too_early(const tal_t *ctx, struct db *db);
94+
static const char *revert_withheld_column(const tal_t *ctx, struct db *db);
95+
9096
/* Do not reorder or remove elements from this array, it is used to
9197
* migrate existing databases from a previous state, based on the
9298
* string indices */
@@ -1087,9 +1093,13 @@ static struct migration dbmigrations[] = {
10871093
")"), NULL},
10881094
/* We do a lookup before each append, to avoid duplicates */
10891095
{SQL("CREATE INDEX chain_moves_utxo_idx ON chain_moves (utxo)"), NULL},
1090-
{NULL, migrate_from_account_db},
1096+
{NULL, migrate_from_account_db, NULL, revert_too_early},
1097+
/* ^v25.09 */
1098+
10911099
/* We accidentally allowed duplicate entries */
1092-
{NULL, migrate_remove_chain_moves_duplicates},
1100+
{NULL, migrate_remove_chain_moves_duplicates,
1101+
/* Removing duplicates is idempotent, so no revert needed */
1102+
NULL, NULL},
10931103
{SQL("CREATE TABLE network_events ("
10941104
" id BIGSERIAL,"
10951105
" peer_id BLOB NOT NULL,"
@@ -1099,9 +1109,16 @@ static struct migration dbmigrations[] = {
10991109
" duration_nsec BIGINT,"
11001110
" connect_attempted INTEGER NOT NULL,"
11011111
" PRIMARY KEY (id)"
1102-
")"), NULL},
1103-
{NULL, migrate_fail_pending_payments_without_htlcs},
1104-
{SQL("ALTER TABLE channels ADD withheld INTEGER DEFAULT 0;"), NULL},
1112+
")"), NULL,
1113+
/* Simply drop table. */
1114+
"DROP TABLE network_events"},
1115+
{NULL, migrate_fail_pending_payments_without_htlcs,
1116+
/* Failing pending payments is idempotent, so no revert needed */
1117+
NULL, NULL},
1118+
{SQL("ALTER TABLE channels ADD withheld INTEGER DEFAULT 0;"), NULL,
1119+
/* Need to make sure that withheld isn't used. */
1120+
NULL, revert_withheld_column},
1121+
/* ^v25.12 */
11051122
};
11061123

11071124
/**
@@ -2153,3 +2170,44 @@ static void migrate_fail_pending_payments_without_htlcs(struct lightningd *ld,
21532170
db_bind_int(stmt, payment_status_in_db(PAYMENT_PENDING));
21542171
db_exec_prepared_v2(take(stmt));
21552172
}
2173+
2174+
static const char *revert_too_early(const tal_t *ctx, struct db *db)
2175+
{
2176+
return tal_strdup(ctx, "Downgrade to before v25.09 not supported");
2177+
}
2178+
2179+
/* Don't allow downgrade if they've *used* the withheld column. */
2180+
static const char *revert_withheld_column(const tal_t *ctx, struct db *db)
2181+
{
2182+
struct db_stmt *stmt;
2183+
struct channel_id *cid;
2184+
struct short_channel_id *scid;
2185+
2186+
stmt = db_prepare_v2(db, SQL("SELECT full_channel_id, scid FROM channels WHERE withheld != 0"));
2187+
db_query_prepared(stmt);
2188+
if (db_step(stmt)) {
2189+
cid = tal(tmpctx, struct channel_id);
2190+
db_col_channel_id(stmt, "full_channel_id", cid);
2191+
if (db_col_is_null(stmt, "scid"))
2192+
scid = NULL;
2193+
else {
2194+
scid = tal(tmpctx, struct short_channel_id);
2195+
*scid = db_col_short_channel_id(stmt, "scid");
2196+
}
2197+
} else {
2198+
cid = NULL;
2199+
scid = NULL;
2200+
}
2201+
tal_free(stmt);
2202+
2203+
if (cid) {
2204+
return tal_fmt(tmpctx, "Channel %s (%s) used v25.12's withheld flag",
2205+
fmt_channel_id(tmpctx, cid),
2206+
scid ? fmt_short_channel_id(tmpctx, *scid) : "no short channel id");
2207+
}
2208+
2209+
/* For sqlite3 needs "2021-03-12 (3.35.0)" or above */
2210+
stmt = db_prepare_v2(db, SQL("ALTER TABLE channels DROP COLUMN withheld"));
2211+
db_exec_prepared_v2(take(stmt));
2212+
return NULL;
2213+
}

0 commit comments

Comments
 (0)