diff --git a/wallet/db.c b/wallet/db.c index 3e407150f..b5eb29c5e 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -1,12 +1,15 @@ #include "db.h" #include +#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -613,6 +616,7 @@ static struct migration dbmigrations[] = { {SQL("ALTER TABLE channel_htlcs ADD we_filled INTEGER;"), NULL}, /* We track the counter for coin_moves, as a convenience for notification consumers */ {SQL("INSERT INTO vars (name, intval) VALUES ('coin_moves_count', 0);"), NULL}, + {NULL, migrate_last_tx_to_psbt}, }; /* Leak tracking. */ @@ -1111,6 +1115,78 @@ static void migrate_our_funding(struct lightningd *ld, struct db *db) tal_free(stmt); } +/* We're moving everything over to PSBTs from tx's, particularly our last_tx's + * which are commitment transactions for channels. + * This migration loads all of the last_tx's and 're-formats' them into psbts, + * adds the required input witness utxo information, and then saves it back to disk + * */ +void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db) +{ + struct db_stmt *stmt, *update_stmt; + + stmt = db_prepare_v2(db, SQL("SELECT " + " c.id" + ", p.node_id" + ", c.last_tx" + ", c.funding_satoshi" + ", c.fundingkey_remote" + ", c.last_sig" + " FROM channels c" + " LEFT OUTER JOIN peers p" + " ON p.id = c.peer_id;")); + + db_query_prepared(stmt); + while (db_step(stmt)) { + struct bitcoin_tx *last_tx; + struct amount_sat funding_sat; + struct node_id peer_id; + struct pubkey local_funding_pubkey, remote_funding_pubkey; + struct basepoints local_basepoints UNUSED; + struct bitcoin_signature last_sig; + u64 cdb_id; + u8 *funding_wscript; + + cdb_id = db_column_u64(stmt, 0); + last_tx = db_column_tx(stmt, stmt, 2); + assert(last_tx != NULL); + + db_column_node_id(stmt, 1, &peer_id); + db_column_amount_sat(stmt, 3, &funding_sat); + db_column_pubkey(stmt, 4, &remote_funding_pubkey); + + get_channel_basepoints(ld, &peer_id, cdb_id, + &local_basepoints, &local_funding_pubkey); + + funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey, + &remote_funding_pubkey); + + psbt_input_set_prev_utxo_wscript(last_tx->psbt, + 0, funding_wscript, + funding_sat); + + if (!db_column_signature(stmt, 5, &last_sig.s)) + abort(); + + last_sig.sighash_type = SIGHASH_ALL; + psbt_input_set_partial_sig(last_tx->psbt, 0, + &remote_funding_pubkey, &last_sig); + psbt_input_add_pubkey(last_tx->psbt, 0, + &local_funding_pubkey); + psbt_input_add_pubkey(last_tx->psbt, 0, + &remote_funding_pubkey); + + update_stmt = db_prepare_v2(db, SQL("UPDATE channels" + " SET last_tx = ?" + " WHERE id = ?;")); + db_bind_psbt(update_stmt, 0, last_tx->psbt); + db_bind_int(update_stmt, 1, cdb_id); + db_exec_prepared_v2(update_stmt); + tal_free(update_stmt); + } + + tal_free(stmt); +} + void db_bind_null(struct db_stmt *stmt, int pos) { assert(pos < tal_count(stmt->bindings)); diff --git a/wallet/db.h b/wallet/db.h index 3252d681b..f8b6c112e 100644 --- a/wallet/db.h +++ b/wallet/db.h @@ -23,6 +23,7 @@ struct db_stmt; struct db; struct wally_psbt; +void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db); /** * Macro to annotate a named SQL query. * diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index 5a75a5793..aeeed1ea2 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -21,6 +21,13 @@ static void db_log_(struct log *log UNUSED, enum log_level level UNUSED, const s /* Generated stub for fatal */ void fatal(const char *fmt UNNEEDED, ...) { fprintf(stderr, "fatal called!\n"); abort(); } +/* Generated stub for get_channel_basepoints */ +void get_channel_basepoints(struct lightningd *ld UNNEEDED, + const struct node_id *peer_id UNNEEDED, + const u64 dbid UNNEEDED, + struct basepoints *local_basepoints UNNEEDED, + struct pubkey *local_funding_pubkey UNNEEDED) +{ fprintf(stderr, "get_channel_basepoints called!\n"); abort(); } /* Generated stub for new_log */ struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, const struct node_id *default_node_id UNNEEDED,