Skip to content

Commit 34991a2

Browse files
committed
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 <[email protected]> Changelog-Fixed: `gossipd` will no longer miss some channel closes on restart.
1 parent e878b50 commit 34991a2

File tree

4 files changed

+46
-1
lines changed

4 files changed

+46
-1
lines changed

gossipd/gossmap_manage.c

+6
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,12 @@ void gossmap_manage_channel_spent(struct gossmap_manage *gm,
12421242
return;
12431243
}
12441244

1245+
/* Is it already dying? It's lightningd re-telling us */
1246+
for (size_t i = 0; i < tal_count(gm->dying_channels); i++) {
1247+
if (short_channel_id_eq(gm->dying_channels[i].scid, scid))
1248+
return;
1249+
}
1250+
12451251
/* BOLT #7:
12461252
* - once its funding output has been spent OR reorganized out:
12471253
* - SHOULD forget a channel after a 12-block delay.

lightningd/gossip_control.c

+17-1
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,25 @@ static void gossipd_init_done(struct subd *gossipd,
251251
const int *fds,
252252
void *unused)
253253
{
254+
struct lightningd *ld = gossipd->ld;
255+
u32 oldspends;
256+
254257
/* Any channels without channel_updates, we populate now: gossipd
255258
* might have lost its gossip_store. */
256-
channel_gossip_init_done(gossipd->ld);
259+
channel_gossip_init_done(ld);
260+
261+
/* Tell it about any closures it might have missed! */
262+
oldspends = wallet_utxoset_oldest_spentheight(tmpctx, ld->wallet);
263+
if (oldspends) {
264+
while (oldspends <= get_block_height(ld->topology)) {
265+
const struct short_channel_id *scids;
266+
267+
scids = wallet_utxoset_get_spent(tmpctx, ld->wallet,
268+
oldspends);
269+
gossipd_notify_spends(ld, oldspends, scids);
270+
oldspends++;
271+
}
272+
}
257273

258274
/* Break out of loop, so we can begin */
259275
log_debug(gossipd->ld->log, "io_break: %s", __func__);

wallet/wallet.c

+20
Original file line numberDiff line numberDiff line change
@@ -4462,6 +4462,26 @@ wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w,
44624462
return db_scids(ctx, stmt);
44634463
}
44644464

4465+
u32 wallet_utxoset_oldest_spentheight(const tal_t *ctx, struct wallet *w)
4466+
{
4467+
struct db_stmt *stmt;
4468+
u32 height;
4469+
stmt = db_prepare_v2(w->db, SQL("SELECT"
4470+
" spendheight "
4471+
"FROM utxoset "
4472+
"WHERE spendheight IS NOT NULL "
4473+
"ORDER BY spendheight ASC "
4474+
"LIMIT 1"));
4475+
db_query_prepared(stmt);
4476+
4477+
if (db_step(stmt))
4478+
height = db_col_int(stmt, "spendheight");
4479+
else
4480+
height = 0;
4481+
tal_free(stmt);
4482+
return height;
4483+
}
4484+
44654485
const struct short_channel_id *
44664486
wallet_utxoset_get_created(const tal_t *ctx, struct wallet *w,
44674487
u32 blockheight)

wallet/wallet.h

+3
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,9 @@ wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w, u32 blockheight);
11381138
/* Prune all UTXO entries spent (far) below this block height */
11391139
void wallet_utxoset_prune(struct wallet *w, u32 blockheight);
11401140

1141+
/* Get oldest spendheight (or 0 if none), to catch up */
1142+
u32 wallet_utxoset_oldest_spentheight(const tal_t *ctx, struct wallet *w);
1143+
11411144
/**
11421145
* Retrieve all UTXO entries that were created at a given blockheight.
11431146
*/

0 commit comments

Comments
 (0)