From 0d94d2d269c760721a49d2e0c8951371e9a435c2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 14 Sep 2022 13:20:32 +0930 Subject: [PATCH] gossipd: batch outpoints spent, add block height. It's a bit more optimal, and tells gossipd exactly what height the spend occurred at (with multiple blocks, it's not always the current height!). It will need that next patch. Signed-off-by: Rusty Russell --- gossipd/gossipd.c | 27 ++++++++++++++++----------- gossipd/gossipd_wire.csv | 8 +++++--- lightningd/chaintopology.c | 11 +++-------- lightningd/gossip_control.c | 14 +++++++++----- lightningd/gossip_control.h | 5 +++-- 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 26be95bd6..395f303b4 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -927,22 +927,27 @@ static void handle_new_lease_rates(struct daemon *daemon, const u8 *msg) /*~ This is where lightningd tells us that a channel's funding transaction has * been spent. */ -static void handle_outpoint_spent(struct daemon *daemon, const u8 *msg) +static void handle_outpoints_spent(struct daemon *daemon, const u8 *msg) { - struct short_channel_id scid; - struct chan *chan; + struct short_channel_id *scids; + u32 blockheight; struct routing_state *rstate = daemon->rstate; - if (!fromwire_gossipd_outpoint_spent(msg, &scid)) - master_badmsg(WIRE_GOSSIPD_OUTPOINT_SPENT, msg); - chan = get_channel(rstate, &scid); - if (chan) { + if (!fromwire_gossipd_outpoints_spent(msg, msg, &blockheight, &scids)) + master_badmsg(WIRE_GOSSIPD_OUTPOINTS_SPENT, msg); + + for (size_t i = 0; i < tal_count(scids); i++) { + struct chan *chan = get_channel(rstate, &scids[i]); + + if (!chan) + continue; + status_debug( "Deleting channel %s due to the funding outpoint being " "spent", - type_to_string(msg, struct short_channel_id, &scid)); + type_to_string(msg, struct short_channel_id, &scids[i])); /* Suppress any now-obsolete updates/announcements */ - add_to_txout_failures(rstate, &scid); + add_to_txout_failures(rstate, &scids[i]); remove_channel_from_store(rstate, chan); /* Freeing is sufficient since everything else is allocated off * of the channel and this takes care of unregistering @@ -999,8 +1004,8 @@ static struct io_plan *recv_req(struct io_conn *conn, handle_txout_reply(daemon, msg); goto done; - case WIRE_GOSSIPD_OUTPOINT_SPENT: - handle_outpoint_spent(daemon, msg); + case WIRE_GOSSIPD_OUTPOINTS_SPENT: + handle_outpoints_spent(daemon, msg); goto done; case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE: diff --git a/gossipd/gossipd_wire.csv b/gossipd/gossipd_wire.csv index 35594b633..2c266584e 100644 --- a/gossipd/gossipd_wire.csv +++ b/gossipd/gossipd_wire.csv @@ -42,9 +42,11 @@ msgdata,gossipd_get_txout_reply,satoshis,amount_sat, msgdata,gossipd_get_txout_reply,len,u16, msgdata,gossipd_get_txout_reply,outscript,u8,len -# master -> gossipd: a potential funding outpoint was spent, please forget the eventual channel -msgtype,gossipd_outpoint_spent,3024 -msgdata,gossipd_outpoint_spent,short_channel_id,short_channel_id, +# master -> gossipd: these potential funding outpoints were spent, please forget any channels +msgtype,gossipd_outpoints_spent,3024 +msgdata,gossipd_outpoints_spent,blockheight,u32, +msgdata,gossipd_outpoints_spent,len,u32, +msgdata,gossipd_outpoints_spent,short_channel_id,short_channel_id,len # master -> gossipd: do you have a memleak? msgtype,gossipd_dev_memleak,3033 diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index d521eae4c..103752c46 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -682,11 +682,7 @@ static void topo_update_spends(struct chain_topology *topo, struct block *b) * tell gossipd about them. */ spent_scids = wallet_utxoset_get_spent(tmpctx, topo->ld->wallet, b->height); - - for (size_t i=0; ibitcoind->ld, &spent_scids[i]); - } - tal_free(spent_scids); + gossipd_notify_spends(topo->bitcoind->ld, b->height, spent_scids); } static void topo_add_utxos(struct chain_topology *topo, struct block *b) @@ -792,12 +788,11 @@ static void remove_tip(struct chain_topology *topo) /* This may have unconfirmed txs: reconfirm as we add blocks. */ watch_for_utxo_reconfirmation(topo, topo->ld->wallet); block_map_del(&topo->block_map, b); - tal_free(b); /* These no longer exist, so gossipd drops any reference to them just * as if they were spent. */ - for (size_t i = 0; i < tal_count(removed_scids); i++) - gossipd_notify_spend(topo->bitcoind->ld, &removed_scids[i]); + gossipd_notify_spends(topo->bitcoind->ld, b->height, removed_scids); + tal_free(b); } static void get_new_block(struct bitcoind *bitcoind, diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 23b5eb8ee..b4665cddb 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -153,7 +153,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) /* These are messages we send, not them. */ case WIRE_GOSSIPD_INIT: case WIRE_GOSSIPD_GET_TXOUT_REPLY: - case WIRE_GOSSIPD_OUTPOINT_SPENT: + case WIRE_GOSSIPD_OUTPOINTS_SPENT: case WIRE_GOSSIPD_NEW_LEASE_RATES: case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE: @@ -273,11 +273,15 @@ void gossip_init(struct lightningd *ld, int connectd_fd) assert(ret == ld->gossip); } -void gossipd_notify_spend(struct lightningd *ld, - const struct short_channel_id *scid) +/* We save these so we always tell gossipd about new blockheight first. */ +void gossipd_notify_spends(struct lightningd *ld, + u32 blockheight, + const struct short_channel_id *scids) { - u8 *msg = towire_gossipd_outpoint_spent(tmpctx, scid); - subd_send_msg(ld->gossip, msg); + subd_send_msg(ld->gossip, + take(towire_gossipd_outpoints_spent(NULL, + blockheight, + scids))); } /* We unwrap, add the peer id, and send to gossipd. */ diff --git a/lightningd/gossip_control.h b/lightningd/gossip_control.h index c1d587902..82f264386 100644 --- a/lightningd/gossip_control.h +++ b/lightningd/gossip_control.h @@ -10,8 +10,9 @@ struct lightningd; void gossip_init(struct lightningd *ld, int connectd_fd); -void gossipd_notify_spend(struct lightningd *ld, - const struct short_channel_id *scid); +void gossipd_notify_spends(struct lightningd *ld, + u32 blockheight, + const struct short_channel_id *scids); void gossip_notify_new_block(struct lightningd *ld, u32 blockheight);