From 6b81243f96d7b7c559ddf59a16dc3fe91e22461d Mon Sep 17 00:00:00 2001 From: Dustin Dettmer Date: Thu, 13 Apr 2023 18:06:38 -0400 Subject: [PATCH] splicing: add DB details for splice HTLCs Changelog-None --- wallet/db.c | 3 ++ wallet/wallet.c | 73 ++++++++++++++++++++++++++++++++++++++++++++----- wallet/wallet.h | 17 +++++++++++- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/wallet/db.c b/wallet/db.c index b97053732..961495890 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -970,6 +970,9 @@ static struct migration dbmigrations[] = { {SQL("CREATE INDEX invoice_update_idx ON invoices (updated_index)"), NULL}, {NULL, migrate_datastore_commando_runes}, {NULL, migrate_invoice_created_index_var}, + /* Splicing requires us to store HTLC sigs for inflight splices and allows us to discard old sigs after splice confirmation. */ + {SQL("ALTER TABLE htlc_sigs ADD inflight_tx_id BLOB"), NULL}, + {SQL("ALTER TABLE htlc_sigs ADD inflight_tx_outnum INTEGER"), NULL}, }; /** diff --git a/wallet/wallet.c b/wallet/wallet.c index e28f59cf8..beb5e980a 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -982,7 +982,8 @@ wallet_htlc_sigs_load(const tal_t *ctx, struct wallet *w, u64 channelid, struct bitcoin_signature *htlc_sigs = tal_arr(ctx, struct bitcoin_signature, 0); stmt = db_prepare_v2( - w->db, SQL("SELECT signature FROM htlc_sigs WHERE channelid = ?")); + w->db, SQL("SELECT signature FROM htlc_sigs WHERE channelid = ?" + " AND inflight_tx_id is NULL")); db_bind_u64(stmt, channelid); db_query_prepared(stmt); @@ -1160,7 +1161,10 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight) db_bind_amount_sat(stmt, &inflight->funding->our_funds); db_bind_psbt(stmt, inflight->funding_psbt); db_bind_int(stmt, inflight->remote_tx_sigs ? 1 : 0); - db_bind_psbt(stmt, inflight->last_tx->psbt); + if (inflight->last_tx) + db_bind_psbt(stmt, inflight->last_tx->psbt); + else + db_bind_null(stmt); db_bind_signature(stmt, &inflight->last_sig.s); if (inflight->lease_expiry != 0) { @@ -1192,18 +1196,24 @@ void wallet_inflight_save(struct wallet *w, struct db_stmt *stmt; /* The *only* thing you can update on an * inflight is the funding PSBT (to add sigs) - * ((and maybe later the last_tx/last_sig if this is for - * a splice */ + * and the last_tx/last_sig if this is for a splice */ stmt = db_prepare_v2(w->db, SQL("UPDATE channel_funding_inflights SET" " funding_psbt=?" // 0 ", funding_tx_remote_sigs_received=?" // 1 + ", last_tx=?" // 2 + ", last_sig=?" // 3 " WHERE" - " channel_id=?" // 2 - " AND funding_tx_id=?" // 3 - " AND funding_tx_outnum=?")); // 4 + " channel_id=?" // 4 + " AND funding_tx_id=?" // 5 + " AND funding_tx_outnum=?")); // 6 db_bind_psbt(stmt, inflight->funding_psbt); db_bind_int(stmt, inflight->remote_tx_sigs); + if (inflight->last_tx) + db_bind_psbt(stmt, inflight->last_tx->psbt); + else + db_bind_null(stmt); + db_bind_signature(stmt, &inflight->last_sig.s); db_bind_u64(stmt, inflight->channel->dbid); db_bind_txid(stmt, &inflight->funding->outpoint.txid); db_bind_int(stmt, inflight->funding->outpoint.n); @@ -2052,6 +2062,35 @@ void wallet_announcement_save(struct wallet *w, u64 id, db_exec_prepared_v2(take(stmt)); } + +void wallet_htlcsigs_confirm_inflight(struct wallet *w, struct channel *chan, + struct bitcoin_outpoint confirmed_outpoint) +{ + struct db_stmt *stmt; + + /* A NULL inflight_tx_id means these htlc_sigs apply to the currently + * active channel */ + stmt = db_prepare_v2(w->db, SQL("DELETE FROM htlc_sigs" + " WHERE channelid=?" + " AND (inflight_tx_id is NULL" + " OR (" + " inflight_tx_id!=?" + " AND " + " inflight_tx_outnum!=?" + ")" + ")")); + db_bind_u64(stmt, 0, chan->dbid); + db_bind_txid(stmt, 1, &confirmed_outpoint.txid); + db_bind_int(stmt, 2, confirmed_outpoint.n); + db_exec_prepared_v2(take(stmt)); + + stmt = db_prepare_v2(w->db, SQL("UPDATE htlc_sigs" + " SET inflight_tx_id=NULL" + " WHERE channelid=?")); + db_bind_u64(stmt, 0, chan->dbid); + db_exec_prepared_v2(take(stmt)); +} + void wallet_channel_save(struct wallet *w, struct channel *chan) { struct db_stmt *stmt; @@ -3799,6 +3838,26 @@ void wallet_htlc_sigs_save(struct wallet *w, u64 channel_id, } } +void wallet_htlc_sigs_add(struct wallet *w, u64 channel_id, + struct bitcoin_outpoint inflight_outpoint, + const struct bitcoin_signature *htlc_sigs) +{ + struct db_stmt *stmt; + + /* Now insert the new ones */ + for (size_t i=0; idb, + SQL("INSERT INTO htlc_sigs (channelid," + " inflight_tx_id, inflight_tx_outnum," + " signature) VALUES (?, ?, ?)")); + db_bind_u64(stmt, 0, channel_id); + db_bind_txid(stmt, 1, &inflight_outpoint.txid); + db_bind_int(stmt, 2, inflight_outpoint.n); + db_bind_signature(stmt, 3, &htlc_sigs[i].s); + db_exec_prepared_v2(take(stmt)); + } +} + bool wallet_sanity_check(struct wallet *w) { struct bitcoin_blkid chainhash; diff --git a/wallet/wallet.h b/wallet/wallet.h index 6aa90a761..2cf03f582 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -607,6 +607,9 @@ bool wallet_shachain_add_hash(struct wallet *wallet, */ u64 wallet_get_channel_dbid(struct wallet *wallet); +void wallet_htlcsigs_confirm_inflight(struct wallet *w, struct channel *chan, + struct bitcoin_outpoint confirmed_outpoint); + /** * wallet_channel_save -- Upsert the channel into the database * @@ -635,6 +638,9 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight); void wallet_inflight_save(struct wallet *w, struct channel_inflight *inflight); +void wallet_promote_splice_candidate(struct wallet *w, + struct channel *chan); + /** * Remove all the inflights from a channel. Also cleans up * the channel's inflight list @@ -1005,11 +1011,20 @@ wallet_payments_by_invoice_request(const tal_t *ctx, const struct sha256 *local_invreq_id); /** - * wallet_htlc_sigs_save - Store the latest HTLC sigs for the channel + * wallet_htlc_sigs_save - Delete all HTLC sigs (including inflights) for the + * channel and store `htlc_sigs` as the new values. */ void wallet_htlc_sigs_save(struct wallet *w, u64 channel_id, const struct bitcoin_signature *htlc_sigs); +/** + * wallet_htlc_sigs_add - Appends `htlc_sigs` for the given inflight splice. + * `inflight_id` is the funding txid for the given splice. + */ +void wallet_htlc_sigs_add(struct wallet *w, u64 channel_id, + struct bitcoin_outpoint inflight_outpoint, + const struct bitcoin_signature *htlc_sigs); + /** * wallet_sanity_check - Check that the wallet is setup for this node_id and chain *