From bb589e0eafc363494c317a2e0ec5168a948c86f5 Mon Sep 17 00:00:00 2001 From: niftynei Date: Thu, 21 May 2020 22:45:14 -0500 Subject: [PATCH] psbt: database migration for converting last_tx to a psbt We update the `last_tx` in `channels` to be psbt format, instead of a linearized transaction. We need the amount of the input populated, which we have since this is the 'funding' amount. Ideally we'd also populate the funding scriptPubkey, but to do that we'd need to access the HSM module to fetch our local funding pubkey, which isn't initialized at the time that the database migrations are run. Since the only field the HSM uses currently when signing these is the amount field, it's ok to just leave it out. needs a test! --- wallet/db.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ wallet/db.h | 1 + wallet/test/run-db.c | 7 ++++ 3 files changed, 84 insertions(+) diff --git a/wallet/db.c b/wallet/db.c index 3e407150fb35..b5eb29c5e80b 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 3252d681b1aa..f8b6c112e999 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 5a75a5793fbb..aeeed1ea2ee3 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,