gossipd: replay old spent UTXOs when restarting.

This may help the cases we see where gossipd doesn't realize channels
are closed (because of shutdown before it processed the closing).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `gossipd` will no longer miss some channel closes on restart.
This commit is contained in:
Rusty Russell 2024-11-13 13:24:28 +10:30
parent a4847b5af4
commit 658cc9db5f
4 changed files with 46 additions and 1 deletions

View File

@ -1242,6 +1242,12 @@ void gossmap_manage_channel_spent(struct gossmap_manage *gm,
return;
}
/* Is it already dying? It's lightningd re-telling us */
for (size_t i = 0; i < tal_count(gm->dying_channels); i++) {
if (short_channel_id_eq(gm->dying_channels[i].scid, scid))
return;
}
/* BOLT #7:
* - once its funding output has been spent OR reorganized out:
* - SHOULD forget a channel after a 12-block delay.

View File

@ -251,9 +251,25 @@ static void gossipd_init_done(struct subd *gossipd,
const int *fds,
void *unused)
{
struct lightningd *ld = gossipd->ld;
u32 oldspends;
/* Any channels without channel_updates, we populate now: gossipd
* might have lost its gossip_store. */
channel_gossip_init_done(gossipd->ld);
channel_gossip_init_done(ld);
/* Tell it about any closures it might have missed! */
oldspends = wallet_utxoset_oldest_spentheight(tmpctx, ld->wallet);
if (oldspends) {
while (oldspends <= get_block_height(ld->topology)) {
const struct short_channel_id *scids;
scids = wallet_utxoset_get_spent(tmpctx, ld->wallet,
oldspends);
gossipd_notify_spends(ld, oldspends, scids);
oldspends++;
}
}
/* Break out of loop, so we can begin */
log_debug(gossipd->ld->log, "io_break: %s", __func__);

View File

@ -4462,6 +4462,26 @@ wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w,
return db_scids(ctx, stmt);
}
u32 wallet_utxoset_oldest_spentheight(const tal_t *ctx, struct wallet *w)
{
struct db_stmt *stmt;
u32 height;
stmt = db_prepare_v2(w->db, SQL("SELECT"
" spendheight "
"FROM utxoset "
"WHERE spendheight IS NOT NULL "
"ORDER BY spendheight ASC "
"LIMIT 1"));
db_query_prepared(stmt);
if (db_step(stmt))
height = db_col_int(stmt, "spendheight");
else
height = 0;
tal_free(stmt);
return height;
}
const struct short_channel_id *
wallet_utxoset_get_created(const tal_t *ctx, struct wallet *w,
u32 blockheight)

View File

@ -1138,6 +1138,9 @@ wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w, u32 blockheight);
/* Prune all UTXO entries spent (far) below this block height */
void wallet_utxoset_prune(struct wallet *w, u32 blockheight);
/* Get oldest spendheight (or 0 if none), to catch up */
u32 wallet_utxoset_oldest_spentheight(const tal_t *ctx, struct wallet *w);
/**
* Retrieve all UTXO entries that were created at a given blockheight.
*/