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 <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-09-14 13:20:32 +09:30
parent bfc21cbb55
commit 0d94d2d269
5 changed files with 36 additions and 29 deletions

View File

@@ -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 /*~ This is where lightningd tells us that a channel's funding transaction has
* been spent. */ * 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 short_channel_id *scids;
struct chan *chan; u32 blockheight;
struct routing_state *rstate = daemon->rstate; 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 (!fromwire_gossipd_outpoints_spent(msg, msg, &blockheight, &scids))
if (chan) { 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( status_debug(
"Deleting channel %s due to the funding outpoint being " "Deleting channel %s due to the funding outpoint being "
"spent", "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 */ /* 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); remove_channel_from_store(rstate, chan);
/* Freeing is sufficient since everything else is allocated off /* Freeing is sufficient since everything else is allocated off
* of the channel and this takes care of unregistering * 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); handle_txout_reply(daemon, msg);
goto done; goto done;
case WIRE_GOSSIPD_OUTPOINT_SPENT: case WIRE_GOSSIPD_OUTPOINTS_SPENT:
handle_outpoint_spent(daemon, msg); handle_outpoints_spent(daemon, msg);
goto done; goto done;
case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE: case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE:

View File

@@ -42,9 +42,11 @@ msgdata,gossipd_get_txout_reply,satoshis,amount_sat,
msgdata,gossipd_get_txout_reply,len,u16, msgdata,gossipd_get_txout_reply,len,u16,
msgdata,gossipd_get_txout_reply,outscript,u8,len msgdata,gossipd_get_txout_reply,outscript,u8,len
# master -> gossipd: a potential funding outpoint was spent, please forget the eventual channel # master -> gossipd: these potential funding outpoints were spent, please forget any channels
msgtype,gossipd_outpoint_spent,3024 msgtype,gossipd_outpoints_spent,3024
msgdata,gossipd_outpoint_spent,short_channel_id,short_channel_id, 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? # master -> gossipd: do you have a memleak?
msgtype,gossipd_dev_memleak,3033 msgtype,gossipd_dev_memleak,3033
1 #include <common/cryptomsg.h>
42 msgtype,gossipd_dev_memleak_reply,3133 # master -> gossipd: do you have a memleak?
43 msgdata,gossipd_dev_memleak_reply,leak,bool, msgtype,gossipd_dev_memleak,3033
44 # master -> gossipd: please rewrite the gossip_store msgtype,gossipd_dev_memleak_reply,3133
45 msgtype,gossipd_dev_compact_store,3034 msgdata,gossipd_dev_memleak_reply,leak,bool,
46 # gossipd -> master: ok # master -> gossipd: please rewrite the gossip_store
47 msgtype,gossipd_dev_compact_store_reply,3134 msgtype,gossipd_dev_compact_store,3034
48 # gossipd -> master: ok
49 msgtype,gossipd_dev_compact_store_reply,3134
50 msgdata,gossipd_dev_compact_store_reply,success,bool,
51 # master -> gossipd: blockheight increased.
52 msgtype,gossipd_new_blockheight,3026

View File

@@ -682,11 +682,7 @@ static void topo_update_spends(struct chain_topology *topo, struct block *b)
* tell gossipd about them. */ * tell gossipd about them. */
spent_scids = spent_scids =
wallet_utxoset_get_spent(tmpctx, topo->ld->wallet, b->height); wallet_utxoset_get_spent(tmpctx, topo->ld->wallet, b->height);
gossipd_notify_spends(topo->bitcoind->ld, b->height, spent_scids);
for (size_t i=0; i<tal_count(spent_scids); i++) {
gossipd_notify_spend(topo->bitcoind->ld, &spent_scids[i]);
}
tal_free(spent_scids);
} }
static void topo_add_utxos(struct chain_topology *topo, struct block *b) 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. */ /* This may have unconfirmed txs: reconfirm as we add blocks. */
watch_for_utxo_reconfirmation(topo, topo->ld->wallet); watch_for_utxo_reconfirmation(topo, topo->ld->wallet);
block_map_del(&topo->block_map, b); block_map_del(&topo->block_map, b);
tal_free(b);
/* These no longer exist, so gossipd drops any reference to them just /* These no longer exist, so gossipd drops any reference to them just
* as if they were spent. */ * as if they were spent. */
for (size_t i = 0; i < tal_count(removed_scids); i++) gossipd_notify_spends(topo->bitcoind->ld, b->height, removed_scids);
gossipd_notify_spend(topo->bitcoind->ld, &removed_scids[i]); tal_free(b);
} }
static void get_new_block(struct bitcoind *bitcoind, static void get_new_block(struct bitcoind *bitcoind,

View File

@@ -153,7 +153,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
/* These are messages we send, not them. */ /* These are messages we send, not them. */
case WIRE_GOSSIPD_INIT: case WIRE_GOSSIPD_INIT:
case WIRE_GOSSIPD_GET_TXOUT_REPLY: 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_NEW_LEASE_RATES:
case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE:
case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE: case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE:
@@ -273,11 +273,15 @@ void gossip_init(struct lightningd *ld, int connectd_fd)
assert(ret == ld->gossip); assert(ret == ld->gossip);
} }
void gossipd_notify_spend(struct lightningd *ld, /* We save these so we always tell gossipd about new blockheight first. */
const struct short_channel_id *scid) 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,
subd_send_msg(ld->gossip, msg); take(towire_gossipd_outpoints_spent(NULL,
blockheight,
scids)));
} }
/* We unwrap, add the peer id, and send to gossipd. */ /* We unwrap, add the peer id, and send to gossipd. */

View File

@@ -10,8 +10,9 @@ struct lightningd;
void gossip_init(struct lightningd *ld, int connectd_fd); void gossip_init(struct lightningd *ld, int connectd_fd);
void gossipd_notify_spend(struct lightningd *ld, void gossipd_notify_spends(struct lightningd *ld,
const struct short_channel_id *scid); u32 blockheight,
const struct short_channel_id *scids);
void gossip_notify_new_block(struct lightningd *ld, u32 blockheight); void gossip_notify_new_block(struct lightningd *ld, u32 blockheight);