diff --git a/lightningd/channel.c b/lightningd/channel.c index b971ebe8e..90fede3cd 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -88,13 +88,17 @@ static void destroy_channel(struct channel *channel) list_del_from(&channel->peer->channels, &channel->list); } -void delete_channel(struct channel *channel STEALS) +void delete_channel(struct channel *channel STEALS, bool completely_eliminate) { const u8 *msg; struct peer *peer = channel->peer; - if (channel->dbid != 0) + if (channel->dbid != 0) { wallet_channel_close(channel->peer->ld->wallet, channel); + /* Never open at all, not ours. */ + if (completely_eliminate) + wallet_channel_delete(channel->peer->ld->wallet, channel); + } /* Tell the hsm to forget the channel, needs to be after it's * been forgotten here */ @@ -1035,7 +1039,7 @@ static void channel_fail_perm(struct channel *channel, drop_to_chain(ld, channel, false, spent_by); if (channel_state_open_uncommitted(channel->state)) - delete_channel(channel); + delete_channel(channel, false); } void channel_fail_permanent(struct channel *channel, @@ -1093,7 +1097,7 @@ void channel_fail_forget(struct channel *channel, const char *fmt, ...) channel->error = towire_errorfmt(channel, &channel->cid, "%s", why); - delete_channel(channel); + delete_channel(channel, false); tal_free(why); } @@ -1162,7 +1166,7 @@ void channel_internal_error(struct channel *channel, const char *fmt, ...) /* Nothing ventured, nothing lost! */ if (channel_state_uncommitted(channel->state)) { channel_set_owner(channel, NULL); - delete_channel(channel); + delete_channel(channel, false); return; } diff --git a/lightningd/channel.h b/lightningd/channel.h index 51b6353c3..5a802ce6b 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -479,7 +479,8 @@ channel_current_inflight(const struct channel *channel); /* What's the last feerate used for a funding tx on this channel? */ u32 channel_last_funding_feerate(const struct channel *channel); -void delete_channel(struct channel *channel STEALS); +/* Only set completely_eliminate for never-existed channels */ +void delete_channel(struct channel *channel STEALS, bool completely_eliminate); const char *channel_state_name(const struct channel *channel); const char *channel_state_str(enum channel_state state); diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 64d52cc16..f1d3d6477 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -1321,7 +1321,7 @@ static void forget(struct channel *channel) channel->forgets = tal_arr(channel, struct command *, 0); /* Forget the channel. */ - delete_channel(channel); + delete_channel(channel, false); for (size_t i = 0; i < tal_count(forgets); i++) { assert(!forgets[i]->json_stream); @@ -2017,8 +2017,8 @@ void channel_notify_new_block(struct lightningd *ld, block_height - channel->first_blocknum, fmt_bitcoin_txid(tmpctx, &channel->funding.txid)); /* FIXME: Send an error packet for this case! */ - /* And forget it. */ - delete_channel(channel); + /* And forget it. COMPLETELY. */ + delete_channel(channel, true); } tal_free(to_forget); diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index c1863d2ee..925ab1fe1 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -67,7 +67,7 @@ void channel_unsaved_close_conn(struct channel *channel, const char *why) assert(channel->owner); channel_set_owner(channel, NULL); - delete_channel(channel); + delete_channel(channel, false); } static void channel_saved_err_broken_reconn(struct channel *channel, @@ -3959,13 +3959,13 @@ static void dualopen_errmsg(struct channel *channel, if (channel_state_uncommitted(channel->state)) { log_info(channel->log, "%s", "Unsaved peer failed." " Deleting channel."); - delete_channel(channel); + delete_channel(channel, false); return; } if ((warning || disconnect) && channel_state_open_uncommitted(channel->state)) { log_info(channel->log, "%s", "Commit ready peer failed." " Deleting channel."); - delete_channel(channel); + delete_channel(channel, false); return; } @@ -4009,7 +4009,7 @@ static void dualopen_errmsg(struct channel *channel, if (channel_state_open_uncommitted(channel->state)) { log_info(channel->log, "%s", "Commit ready peer can't reconnect." " Deleting channel."); - delete_channel(channel); + delete_channel(channel, false); return; } char *err = restart_dualopend(tmpctx, diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index cb09b1ee4..3ea834ee0 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -528,7 +528,7 @@ static void handle_irrevocably_resolved(struct channel *channel, const u8 *msg U log_info(channel->log, "onchaind complete, forgetting peer"); /* This will also free onchaind. */ - delete_channel(channel); + delete_channel(channel, false); } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 38fec6961..e9092d74a 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -519,7 +519,7 @@ void channel_errmsg(struct channel *channel, if (channel_state_uncommitted(channel->state)) { log_info(channel->log, "%s", "Unsaved peer failed." " Deleting channel."); - delete_channel(channel); + delete_channel(channel, false); return; } @@ -3432,7 +3432,7 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED, forget->channel->error = towire_errorfmt(forget->channel, &forget->channel->cid, "dev_forget_channel"); - delete_channel(forget->channel); + delete_channel(forget->channel, false); was_pending(command_success(forget->cmd, response)); } diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index ca8d78e48..188b6a5c4 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -243,7 +243,7 @@ struct anchor_details *create_anchor_details(const tal_t *ctx UNNEEDED, const struct bitcoin_tx *tx UNNEEDED) { fprintf(stderr, "create_anchor_details called!\n"); abort(); } /* Generated stub for delete_channel */ -void delete_channel(struct channel *channel STEALS UNNEEDED) +void delete_channel(struct channel *channel STEALS UNNEEDED, bool completely_eliminate UNNEEDED) { fprintf(stderr, "delete_channel called!\n"); abort(); } /* Generated stub for depthcb_update_scid */ bool depthcb_update_scid(struct channel *channel UNNEEDED, diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index c68a5f314..492527cdf 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -285,7 +285,8 @@ struct peer *new_peer(struct lightningd *ld UNNEEDED, u64 dbid UNNEEDED, bool connected_incoming UNNEEDED) { fprintf(stderr, "new_peer called!\n"); abort(); } /* Generated stub for notify_chain_mvt */ -void notify_chain_mvt(struct lightningd *ld UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED) +void notify_chain_mvt(struct lightningd *ld UNNEEDED, + const struct chain_coin_mvt *chain_mvt UNNEEDED) { fprintf(stderr, "notify_chain_mvt called!\n"); abort(); } /* Generated stub for notify_forward_event */ void notify_forward_event(struct lightningd *ld UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index de5787ed3..590cb1956 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -701,10 +701,12 @@ struct uncommitted_channel *new_uncommitted_channel(struct peer *peer UNNEEDED) bool node_announcement_same(const u8 *nann1 UNNEEDED, const u8 *nann2 UNNEEDED) { fprintf(stderr, "node_announcement_same called!\n"); abort(); } /* Generated stub for notify_chain_mvt */ -void notify_chain_mvt(struct lightningd *ld UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED) +void notify_chain_mvt(struct lightningd *ld UNNEEDED, + const struct chain_coin_mvt *chain_mvt UNNEEDED) { fprintf(stderr, "notify_chain_mvt called!\n"); abort(); } /* Generated stub for notify_channel_mvt */ -void notify_channel_mvt(struct lightningd *ld UNNEEDED, const struct channel_coin_mvt *mvt UNNEEDED) +void notify_channel_mvt(struct lightningd *ld UNNEEDED, + const struct channel_coin_mvt *chan_mvt UNNEEDED) { fprintf(stderr, "notify_channel_mvt called!\n"); abort(); } /* Generated stub for notify_channel_open_failed */ void notify_channel_open_failed(struct lightningd *ld UNNEEDED, @@ -2116,7 +2118,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) /* do inflights get cleared when the channel is closed?*/ dbid = chan->dbid; - delete_channel(chan); /* Also clears up peer! */ + delete_channel(chan, false); /* Also clears up peer! */ CHECK_MSG(count_inflights(w, dbid) == 0, "inflights cleaned up"); db_commit_transaction(w->db); CHECK_MSG(!wallet_err, wallet_err); diff --git a/wallet/wallet.c b/wallet/wallet.c index 9b83dbdb5..b8b2f5d64 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2814,12 +2814,8 @@ void wallet_channel_insert(struct wallet *w, struct channel *chan) void wallet_channel_close(struct wallet *w, const struct channel *chan) { - /* We keep a couple of dependent tables around as well, such as the - * channel_configs table, since that might help us debug some issues, - * and it is rather limited in size. Tables that can grow quite - * considerably and that are of limited use after channel closure will - * be pruned as well. */ - + /* We keep the entry in the channel_configs table, since that might + * help us debug some issues, and it is rather limited in size. */ struct db_stmt *stmt; /* Delete entries from `channel_htlcs` */ @@ -2861,6 +2857,24 @@ void wallet_channel_close(struct wallet *w, db_bind_u64(stmt, chan->dbid); db_exec_prepared_v2(take(stmt)); + /* Delete transaction annotations */ + stmt = db_prepare_v2(w->db, SQL("DELETE FROM transaction_annotations " + "WHERE channel=?")); + db_bind_u64(stmt, chan->dbid); + db_exec_prepared_v2(take(stmt)); + + /* Delete feerates */ + stmt = db_prepare_v2(w->db, SQL("DELETE FROM channel_feerates " + "WHERE channel_id=?")); + db_bind_u64(stmt, chan->dbid); + db_exec_prepared_v2(take(stmt)); + + /* Delete anchor information */ + stmt = db_prepare_v2(w->db, SQL("DELETE FROM local_anchors " + "WHERE channel_id=?")); + db_bind_u64(stmt, chan->dbid); + db_exec_prepared_v2(take(stmt)); + /* Set the channel to closed */ stmt = db_prepare_v2(w->db, SQL("UPDATE channels " "SET state=? " @@ -2870,6 +2884,32 @@ void wallet_channel_close(struct wallet *w, db_exec_prepared_v2(take(stmt)); } +/* Completely unused channels get wiped entirely (we've already closed it above) */ +void wallet_channel_delete(struct wallet *w, const struct channel *channel) +{ + struct db_stmt *stmt; + + /* Delete channel configuration for both sides */ + stmt = db_prepare_v2(w->db, SQL("DELETE FROM channel_configs" + " WHERE id=? OR id=?")); + db_bind_u64(stmt, channel->channel_info.their_config.id); + db_bind_u64(stmt, channel->our_config.id); + db_exec_prepared_v2(stmt); + + assert(db_count_changes(stmt) == 2); + tal_free(stmt); + + stmt = db_prepare_v2(w->db, SQL("DELETE FROM channels" + " WHERE state = ?" + " AND id=?")); + db_bind_u64(stmt, channel_state_in_db(CLOSED)); + db_bind_u64(stmt, channel->dbid); + db_exec_prepared_v2(stmt); + + assert(db_count_changes(stmt) == 1); + tal_free(stmt); +} + void wallet_channel_inflight_cleanup_incomplete(struct wallet *w, u64 wallet_id) { struct db_stmt *stmt; diff --git a/wallet/wallet.h b/wallet/wallet.h index ea0853528..b2e9430e0 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -699,6 +699,11 @@ void wallet_channel_clear_inflights(struct wallet *w, void wallet_channel_close(struct wallet *w, const struct channel *chan); +/** + * If it was never used, we can forget it entirely after wallet_channel_close. + */ +void wallet_channel_delete(struct wallet *w, const struct channel *channel); + /** * Adds a channel state change history entry into the database */