Skip to content

Commit

Permalink
wallet: fix up PSBTs as a migration.
Browse files Browse the repository at this point in the history
In the now-misnamed "last_tx" field.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Mar 30, 2023
1 parent f1fa75f commit 5bb0270
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 20 deletions.
8 changes: 0 additions & 8 deletions gossipd/test/run-check_channel_announcement.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,6 @@ const u8 *gossip_store_get_private_update(const tal_t *ctx UNNEEDED,
void gossip_store_mark_channel_deleted(struct gossip_store *gs UNNEEDED,
const struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "gossip_store_mark_channel_deleted called!\n"); abort(); }
/* Generated stub for gossip_store_mark_channel_zombie */
void gossip_store_mark_channel_zombie(struct gossip_store *gs UNNEEDED,
struct broadcastable *bcast UNNEEDED)
{ fprintf(stderr, "gossip_store_mark_channel_zombie called!\n"); abort(); }
/* Generated stub for gossip_store_mark_cupdate_zombie */
void gossip_store_mark_cupdate_zombie(struct gossip_store *gs UNNEEDED,
struct broadcastable *bcast UNNEEDED)
{ fprintf(stderr, "gossip_store_mark_cupdate_zombie called!\n"); abort(); }
/* Generated stub for gossip_store_new */
struct gossip_store *gossip_store_new(struct routing_state *rstate UNNEEDED,
struct list_head *peers UNNEEDED)
Expand Down
8 changes: 0 additions & 8 deletions gossipd/test/run-txout_failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,6 @@ const u8 *gossip_store_get_private_update(const tal_t *ctx UNNEEDED,
void gossip_store_mark_channel_deleted(struct gossip_store *gs UNNEEDED,
const struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "gossip_store_mark_channel_deleted called!\n"); abort(); }
/* Generated stub for gossip_store_mark_channel_zombie */
void gossip_store_mark_channel_zombie(struct gossip_store *gs UNNEEDED,
struct broadcastable *bcast UNNEEDED)
{ fprintf(stderr, "gossip_store_mark_channel_zombie called!\n"); abort(); }
/* Generated stub for gossip_store_mark_cupdate_zombie */
void gossip_store_mark_cupdate_zombie(struct gossip_store *gs UNNEEDED,
struct broadcastable *bcast UNNEEDED)
{ fprintf(stderr, "gossip_store_mark_cupdate_zombie called!\n"); abort(); }
/* Generated stub for memleak_add_helper_ */
void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED,
const tal_t *)){ }
Expand Down
3 changes: 1 addition & 2 deletions lightningd/test/run-invoice-select-inchan.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ struct channel *any_channel_by_scid(struct lightningd *ld UNNEEDED,
bool privacy_leak_ok UNNEEDED)
{ fprintf(stderr, "any_channel_by_scid called!\n"); abort(); }
/* Generated stub for bip32_pubkey */
void bip32_pubkey(struct lightningd *ld UNNEEDED,
struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED)
void bip32_pubkey(struct lightningd *ld UNNEEDED, struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED)
{ fprintf(stderr, "bip32_pubkey called!\n"); abort(); }
/* Generated stub for bitcoind_getutxout_ */
void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED,
Expand Down
6 changes: 6 additions & 0 deletions tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ def test_backfill_scriptpubkeys(node_factory, bitcoind):

# Test the first time, all entries are with option_static_remotekey
l1 = node_factory.get_node(node_id=3, dbfile='pubkey_regen.sqlite.xz',
# Our db had the old non-DER sig in psbt!
allow_broken_log=True,
options={'database-upgrade': True})
results = l1.db_query('SELECT hex(prev_out_tx) AS txid, hex(scriptpubkey) AS script FROM outputs')
scripts = [{'txid': x['txid'], 'scriptpubkey': x['script']} for x in results]
Expand Down Expand Up @@ -284,6 +286,8 @@ def test_backfill_scriptpubkeys(node_factory, bitcoind):
l1.stop()

l2 = node_factory.get_node(node_id=3, dbfile='pubkey_regen_commitment_point.sqlite3.xz',
# Our db had the old non-DER sig in psbt!
allow_broken_log=True,
options={'database-upgrade': True})
results = l2.db_query('SELECT hex(prev_out_tx) AS txid, hex(scriptpubkey) AS script FROM outputs')
scripts = [{'txid': x['txid'], 'scriptpubkey': x['script']} for x in results]
Expand Down Expand Up @@ -363,6 +367,8 @@ def test_local_basepoints_cache(bitcoind, node_factory):
l1 = node_factory.get_node(
dbfile='no-local-basepoints.sqlite3.xz',
start=False,
# Our db had the old non-DER sig in psbt!
allow_broken_log=True,
options={'database-upgrade': True}
)

Expand Down
78 changes: 78 additions & 0 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <lightningd/hsm_control.h>
#include <lightningd/plugin_hook.h>
#include <wallet/db.h>
#include <wallet/psbt_fixup.h>
#include <wire/wire_sync.h>

struct migration {
Expand Down Expand Up @@ -54,6 +55,9 @@ static void fillin_missing_lease_satoshi(struct lightningd *ld,
static void fillin_missing_lease_satoshi(struct lightningd *ld,
struct db *db);

static void migrate_invalid_last_tx_psbts(struct lightningd *ld,
struct db *db);

/* Do not reorder or remove elements from this array, it is used to
* migrate existing databases from a previous state, based on the
* string indices */
Expand Down Expand Up @@ -938,6 +942,7 @@ static struct migration dbmigrations[] = {
{SQL("ALTER TABLE channels ADD require_confirm_inputs_remote INTEGER DEFAULT 0;"), NULL},
{SQL("ALTER TABLE channels ADD require_confirm_inputs_local INTEGER DEFAULT 0;"), NULL},
{NULL, fillin_missing_lease_satoshi},
{NULL, migrate_invalid_last_tx_psbts},
};

/**
Expand Down Expand Up @@ -1561,3 +1566,76 @@ static void fillin_missing_lease_satoshi(struct lightningd *ld,
db_exec_prepared_v2(stmt);
tal_free(stmt);
}

static void complain_unfixed(struct lightningd *ld,
enum channel_state state,
u64 id,
const u8 *bytes,
const char *why)
{
/* This is OK on closed channels */
if (state != CLOSED) {
log_broken(ld->log,
"%s channel id %"PRIu64" PSBT hex '%s'",
why, id, tal_hex(tmpctx, bytes));
} else {
log_debug(ld->log,
"%s on closed channel id %"PRIu64" PSBT hex '%s'",
why, id, tal_hex(tmpctx, bytes));
}
}

static void migrate_invalid_last_tx_psbts(struct lightningd *ld,
struct db *db)
{
struct db_stmt *stmt;

/* We try all of them, but note that last_tx used to be a tx,
* and migrate_last_tx_to_psbt didn't convert channels which had
* already been closed, so we expect some failures. */
stmt = db_prepare_v2(db, SQL("SELECT "
" id"
", state"
", last_tx"
" FROM channels"));

db_query_prepared(stmt);
while (db_step(stmt)) {
struct db_stmt *update_stmt;
const u8 *bytes, *fixed;
enum channel_state state;
u64 id;
struct wally_psbt *psbt;

state = db_col_int(stmt, "state");
id = db_col_u64(stmt, "id");

/* Parses fine? */
if (db_col_psbt(tmpctx, stmt, "last_tx"))
continue;

/* Can we fix it? */
bytes = db_col_arr(tmpctx, stmt, "last_tx", u8);
fixed = psbt_fixup(tmpctx, bytes);
if (!fixed) {
complain_unfixed(ld, state, id, bytes, "Could not fix");
continue;
}
psbt = psbt_from_bytes(tmpctx, fixed, tal_bytelen(fixed));
if (!psbt) {
complain_unfixed(ld, state, id, fixed, "Fix made invalid psbt");
continue;
}

log_broken(ld->log, "Forced database repair of psbt %s -> %s",
tal_hex(tmpctx, bytes), tal_hex(tmpctx, fixed));
update_stmt = db_prepare_v2(db, SQL("UPDATE channels"
" SET last_tx = ?"
" WHERE id = ?;"));
db_bind_psbt(update_stmt, 0, psbt);
db_bind_u64(update_stmt, 1, id);
db_exec_prepared_v2(update_stmt);
tal_free(update_stmt);
}
tal_free(stmt);
}
6 changes: 4 additions & 2 deletions wallet/test/run-db.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ static void db_log_(struct log *log UNUSED, enum log_level level UNUSED, const s

/* AUTOGENERATED MOCKS START */
/* Generated stub for bip32_pubkey */
void bip32_pubkey(struct lightningd *ld UNNEEDED,
struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED)
void bip32_pubkey(struct lightningd *ld UNNEEDED, struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED)
{ fprintf(stderr, "bip32_pubkey called!\n"); abort(); }
/* Generated stub for derive_channel_id */
void derive_channel_id(struct channel_id *channel_id UNNEEDED,
Expand All @@ -44,6 +43,9 @@ void get_channel_basepoints(struct lightningd *ld UNNEEDED,
struct basepoints *local_basepoints UNNEEDED,
struct pubkey *local_funding_pubkey UNNEEDED)
{ fprintf(stderr, "get_channel_basepoints called!\n"); abort(); }
/* Generated stub for psbt_fixup */
const u8 *psbt_fixup(const tal_t *ctx UNNEEDED, const u8 *psbtblob UNNEEDED)
{ fprintf(stderr, "psbt_fixup called!\n"); abort(); }
/* Generated stub for towire_hsmd_get_channel_basepoints */
u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct node_id *peerid UNNEEDED, u64 dbid UNNEEDED)
{ fprintf(stderr, "towire_hsmd_get_channel_basepoints called!\n"); abort(); }
Expand Down
3 changes: 3 additions & 0 deletions wallet/test/run-wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,9 @@ struct route_step *process_onionpacket(
bool has_realm
)
{ fprintf(stderr, "process_onionpacket called!\n"); abort(); }
/* Generated stub for psbt_fixup */
const u8 *psbt_fixup(const tal_t *ctx UNNEEDED, const u8 *psbtblob UNNEEDED)
{ fprintf(stderr, "psbt_fixup called!\n"); abort(); }
/* Generated stub for report_subd_memleak */
void report_subd_memleak(struct leak_detect *leak_detect UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "report_subd_memleak called!\n"); abort(); }
Expand Down

0 comments on commit 5bb0270

Please sign in to comment.