From bf3deb0135220813e9fa8ddc7a236d11bdaf51ed Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 18 Mar 2025 14:31:58 +1030 Subject: [PATCH 1/6] lightningd: rename `anchor_confirms` to `funding_confirms`. Calling the funding tx an anchor is pre-spec terminology, which is now confusing; let's rename the variable. Signed-off-by: Rusty Russell --- lightningd/dual_open_control.c | 2 +- lightningd/lightningd.h | 4 ++-- lightningd/opening_common.c | 2 +- lightningd/opening_control.c | 2 +- lightningd/options.c | 10 +++++----- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 49c3d844da4d..7c3de2ae8eed 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -4122,7 +4122,7 @@ bool peer_start_dualopend(struct peer *peer, * funding transaction. */ /* FIXME: We should override this to 0 in the openchannel2 hook of we want zeroconf*/ - channel->minimum_depth = peer->ld->config.anchor_confirms; + channel->minimum_depth = peer->ld->config.funding_confirms; msg = towire_dualopend_init(NULL, chainparams, peer->ld->our_features, diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 2f562f6c2f41..45732c006f8d 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -21,8 +21,8 @@ struct config { /* How long do we let them lock up our funds? (blocks: 2016 by spec) */ u32 max_htlc_cltv; - /* How many confirms until we consider an anchor "settled". */ - u32 anchor_confirms; + /* How many confirms until we consider a funding tx "settled". */ + u32 funding_confirms; /* Minimum CLTV to subtract from incoming HTLCs to outgoing */ u32 cltv_expiry_delta; diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index 7576d6149b97..79f7867c5733 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -62,7 +62,7 @@ new_uncommitted_channel(struct peer *peer) * funding transaction. */ /* We override this in openchannel hook if we want zeroconf */ - uc->minimum_depth = ld->config.anchor_confirms; + uc->minimum_depth = ld->config.funding_confirms; /* Use default 1% reserve if not otherwise specified. If this * is not-NULL it will be used by openingd as absolute value diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 333410d9055b..36008a8f2cfd 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1294,7 +1294,7 @@ static struct command_result *json_fundchannel_start(struct command *cmd, } if (!mindepth) - mindepth = tal_dup(cmd, u32, &cmd->ld->config.anchor_confirms); + mindepth = tal_dup(cmd, u32, &cmd->ld->config.funding_confirms); if (push_msat && amount_msat_greater_sat(*push_msat, *amount)) return command_fail(cmd, FUND_CANNOT_AFFORD, diff --git a/lightningd/options.c b/lightningd/options.c index 767d03a5d25b..781123dc6bd4 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -957,7 +957,7 @@ static const struct config testnet_config = { .max_htlc_cltv = 2016, /* We're fairly trusting, under normal circumstances. */ - .anchor_confirms = 1, + .funding_confirms = 1, /* Testnet blockspace is free. */ .max_concurrent_htlcs = 483, @@ -1025,7 +1025,7 @@ static const struct config mainnet_config = { .max_htlc_cltv = 2016, /* We're fairly trusting, under normal circumstances. */ - .anchor_confirms = 3, + .funding_confirms = 3, /* While up to 483 htlcs are possible we do 30 by default (as eclair does) to save blockspace */ .max_concurrent_htlcs = 30, @@ -1099,8 +1099,8 @@ static void check_config(struct lightningd *ld) if (ld->config.max_concurrent_htlcs < 1 || ld->config.max_concurrent_htlcs > 483) fatal("--max-concurrent-htlcs value must be between 1 and 483 it is: %u", ld->config.max_concurrent_htlcs); - if (ld->config.anchor_confirms == 0) - fatal("anchor-confirms must be greater than zero"); + if (ld->config.funding_confirms == 0) + fatal("funding-confirms must be greater than zero"); if (ld->always_use_proxy && !ld->proxyaddr) fatal("--always-use-proxy needs --proxy"); @@ -1497,7 +1497,7 @@ static void register_opts(struct lightningd *ld) opt_register_arg("--max-locktime-blocks", opt_set_max_htlc_cltv, NULL, ld, opt_hidden); clnopt_witharg("--funding-confirms", OPT_SHOWINT, opt_set_u32, opt_show_u32, - &ld->config.anchor_confirms, + &ld->config.funding_confirms, "Confirmations required for funding transaction"); clnopt_witharg("--require-confirmed-inputs", OPT_SHOWBOOL, opt_set_bool_arg, opt_show_bool, From cd03a7db559ace721701c516b8da05ead10da682 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 18 Mar 2025 14:32:58 +1030 Subject: [PATCH 2/6] lightningd: add another stae check function. In this case a "are we closed onchain". Signed-off-by: Rusty Russell --- lightningd/channel.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lightningd/channel.h b/lightningd/channel.h index 51b6353c3fa7..87706d0d19e6 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -601,6 +601,29 @@ static inline bool channel_state_failing_onchain(enum channel_state state) abort(); } +static inline bool channel_state_funding_spent_onchain(enum channel_state state) +{ + switch (state) { + case CHANNELD_AWAITING_LOCKIN: + case CHANNELD_NORMAL: + case CHANNELD_AWAITING_SPLICE: + case CLOSINGD_SIGEXCHANGE: + case CHANNELD_SHUTTING_DOWN: + case CLOSINGD_COMPLETE: + case DUALOPEND_OPEN_INIT: + case DUALOPEND_OPEN_COMMIT_READY: + case DUALOPEND_OPEN_COMMITTED: + case DUALOPEND_AWAITING_LOCKIN: + case AWAITING_UNILATERAL: + return false; + case CLOSED: + case FUNDING_SPEND_SEEN: + case ONCHAIN: + return true; + } + abort(); +} + static inline bool channel_state_pre_open(enum channel_state state) { switch (state) { From 6413f5bbaa676d604809a11e80a5054e1abee46a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 18 Mar 2025 14:33:58 +1030 Subject: [PATCH 3/6] lightningd: split channel update creation functions. We want a more fine-grained approach, so we now have: 1. update_channel_update() - returns true if it changed. 2. channel_should_enable() - should this channel be marked enabled. 3. arm_refresh_timer() - start a refresh timer for the channel_update. Signed-off-by: Rusty Russell --- lightningd/channel_gossip.c | 160 ++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 70 deletions(-) diff --git a/lightningd/channel_gossip.c b/lightningd/channel_gossip.c index 76a503c9875d..e429a3fce28b 100644 --- a/lightningd/channel_gossip.c +++ b/lightningd/channel_gossip.c @@ -199,50 +199,6 @@ static void broadcast_new_gossip(struct lightningd *ld, /* Recursion */ static void cupdate_timer_refresh(struct channel *channel); -static void set_public_cupdate(struct channel *channel, - const u8 *cupdate TAKES, - bool refresh_later) -{ - struct lightningd *ld = channel->peer->ld; - struct channel_gossip *cg = channel->channel_gossip; - u32 timestamp; - bool enabled; - struct timeabs now, due; - - if (!channel_update_details(cupdate, ×tamp, &enabled)) { - log_broken(channel->log, "Invalid channel_update %s: ignoring", - tal_hex(tmpctx, cupdate)); - if (taken(cupdate)) - tal_free(cupdate); - return; - } - - tal_free(cg->cupdate); - cg->cupdate = tal_dup_talarr(cg, u8, cupdate); - - cg->refresh_timer = tal_free(cg->refresh_timer); - - /* If enabled, we refresh, based on old timestamp */ - if (!enabled || !refresh_later) - return; - - due.ts.tv_sec = timestamp; - due.ts.tv_nsec = 0; - due = timeabs_add(due, - time_from_sec(GOSSIP_PRUNE_INTERVAL(ld->dev_fast_gossip_prune) - - GOSSIP_BEFORE_DEADLINE(ld->dev_fast_gossip_prune))); - - /* In case it's passed, timer should be zero */ - now = time_now(); - if (time_after(now, due)) - due = now; - - cg->refresh_timer = new_reltimer(ld->timers, cg, - time_between(due, now), - cupdate_timer_refresh, - channel); -} - static enum channel_gossip_state init_public_state(struct channel *channel, const struct remote_announce_sigs *remote_sigs) { @@ -328,53 +284,91 @@ static void send_private_cupdate(struct channel *channel, bool even_if_redundant msg_to_peer(channel->peer, cg->cupdate); } -/* Send gossipd a channel_update, if not redundant. */ -static void broadcast_public_cupdate(struct channel *channel, - bool ok_if_disconnected) +/* Sets channel->channel_gossip->cupdate. Returns true if it changed. */ +static bool update_channel_update(const struct channel *channel, + bool enable) { - struct lightningd *ld = channel->peer->ld; struct channel_gossip *cg = channel->channel_gossip; const u8 *cupdate; u32 old_timestamp; + bool have_old; + + /* If we have no previous channel_update, this fails */ + have_old = channel_update_details(cg->cupdate, &old_timestamp, NULL); + cupdate = unsigned_channel_update(tmpctx, channel, *channel->scid, + have_old ? &old_timestamp : NULL, + true, + enable); + + /* Suppress redundant ones */ + if (cg->cupdate && channel_update_same(cg->cupdate, cupdate)) + return false; + + tal_free(cg->cupdate); + cg->cupdate = sign_update(cg, channel->peer->ld, cupdate); + return true; +} + +/* Using default logic, should this channel be enabled? */ +static bool channel_should_enable(const struct channel *channel, + bool ok_if_disconnected) +{ bool enable, have_old; /* If we have no previous channel_update, this fails */ - have_old = channel_update_details(cg->cupdate, - &old_timestamp, &enable); + have_old = channel_update_details(channel->channel_gossip->cupdate, + NULL, &enable); if (!channel_state_can_add_htlc(channel->state)) { /* If it's (no longer) usable, it's a simply courtesy * to disable */ - enable = false; + return false; } else if (channel->owner) { /* If it's live, it's enabled */ - enable = true; + return true; } else if (starting_up) { /* If we are starting up, don't change it! */ if (!have_old) /* Assume the best if we don't have an updated */ enable = true; + return enable; } else { - enable = ok_if_disconnected; + return ok_if_disconnected; } +} - cupdate = unsigned_channel_update(tmpctx, channel, *channel->scid, - have_old ? &old_timestamp : NULL, - true, - enable); +/* Based on existing update, schedule next refresh */ +static void arm_refresh_timer(struct channel *channel) +{ + struct lightningd *ld = channel->peer->ld; + struct channel_gossip *cg = channel->channel_gossip; + struct timeabs now = time_now(), due; + u32 timestamp; - /* Suppress redundant ones */ - if (cg->cupdate && channel_update_same(cg->cupdate, cupdate)) + if (!channel_update_details(cg->cupdate, ×tamp, NULL)) { + log_broken(channel->log, "Missing channel_update for refresh?"); return; + } + due.ts.tv_sec = timestamp; + due.ts.tv_nsec = 0; - set_public_cupdate(channel, - take(sign_update(NULL, channel->peer->ld, cupdate)), - true); - broadcast_new_gossip(ld, cg->cupdate, NULL, "channel update"); + due = timeabs_add(due, + time_from_sec(GOSSIP_PRUNE_INTERVAL(ld->dev_fast_gossip_prune) + - GOSSIP_BEFORE_DEADLINE(ld->dev_fast_gossip_prune))); + + /* In case it's passed, timer should be zero */ + if (time_after(now, due)) + due = now; + + cg->refresh_timer = new_reltimer(ld->timers, cg, + time_between(due, now), + cupdate_timer_refresh, + channel); } static void cupdate_timer_refresh(struct channel *channel) { + struct lightningd *ld = channel->peer->ld; struct channel_gossip *cg = channel->channel_gossip; /* Don't try to free this again if set_public_cupdate called later */ @@ -385,7 +379,10 @@ static void cupdate_timer_refresh(struct channel *channel) /* Free old cupdate to force a new one to be generated */ cg->cupdate = tal_free(cg->cupdate); - broadcast_public_cupdate(channel, true); + update_channel_update(channel, channel_should_enable(channel, true)); + + broadcast_new_gossip(ld, cg->cupdate, NULL, "channel update"); + arm_refresh_timer(channel); } static void stash_remote_announce_sigs(struct channel *channel, @@ -523,8 +520,13 @@ static void send_channel_announcement(struct channel *channel) /* Send everyone our new channel announcement */ broadcast_new_gossip(ld, ca, &channel->funding_sats, "channel announcement"); - /* We can also send our first public channel_update now */ - broadcast_public_cupdate(channel, true); + + /* Any private cupdate will be different from this, so will force a refresh. */ + update_channel_update(channel, channel_should_enable(channel, true)); + + broadcast_new_gossip(ld, cg->cupdate, NULL, "channel update"); + arm_refresh_timer(channel); + /* And maybe our first node_announcement */ channel_gossip_node_announce(ld); } @@ -638,7 +640,8 @@ void channel_gossip_update(struct channel *channel) announced: /* We don't penalize disconnected clients normally: we only * do that if we actually try to send an htlc through */ - broadcast_public_cupdate(channel, true); + update_channel_update(channel, true); + broadcast_new_gossip(ld, cg->cupdate, NULL, "channel update"); check_channel_gossip(channel); return; } @@ -795,6 +798,8 @@ void channel_gossip_notify_new_block(struct lightningd *ld, void channel_gossip_update_from_gossipd(struct channel *channel, const u8 *channel_update TAKES) { + struct channel_gossip *cg = channel->channel_gossip; + if (!channel->channel_gossip) { log_broken(channel->log, "gossipd gave channel_update for unsaved channel? update=%s", @@ -828,10 +833,20 @@ void channel_gossip_update_from_gossipd(struct channel *channel, break; } + /* In case we generated one before gossipd told us? */ + if (cg->cupdate) { + tal_free(cg->cupdate); + cg->refresh_timer = tal_free(cg->refresh_timer); + } + /* We don't set refresh timer if we're not ANNOUNCED, we're just saving updates * for later! */ - set_public_cupdate(channel, channel_update, - channel->channel_gossip->state == CGOSSIP_ANNOUNCED); + cg->cupdate = tal_dup_talarr(cg, u8, channel_update); + if (cg->state == CGOSSIP_ANNOUNCED) { + broadcast_new_gossip(channel->peer->ld, + channel_update, NULL, "channel update"); + arm_refresh_timer(channel); + } check_channel_gossip(channel); } @@ -953,7 +968,12 @@ const u8 *channel_gossip_update_for_error(const tal_t *ctx, case CGOSSIP_NEED_PEER_SIGS: return NULL; case CGOSSIP_ANNOUNCED: - broadcast_public_cupdate(channel, false); + /* At this point we actually disable disconnected peers. */ + if (update_channel_update(channel, channel_should_enable(channel, false))) { + broadcast_new_gossip(channel->peer->ld, + cg->cupdate, NULL, + "channel update"); + } check_channel_gossip(channel); return cg->cupdate; } From 0719e0fa7f9980313ba671f4c860f3302b1ea222 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 18 Mar 2025 14:34:58 +1030 Subject: [PATCH 4/6] gossipd: don't spam the log on duplicate channel_update. This message was too verbose (even for trace!) Signed-off-by: Rusty Russell --- gossipd/gossmap_manage.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gossipd/gossmap_manage.c b/gossipd/gossmap_manage.c index a25c5dd88d75..7c3a40003a7d 100644 --- a/gossipd/gossmap_manage.c +++ b/gossipd/gossmap_manage.c @@ -824,9 +824,11 @@ static const char *process_channel_update(const tal_t *ctx, u32 prev_timestamp = gossip_store_get_timestamp(gm->gs, chan->cupdate_off[dir]); if (prev_timestamp >= timestamp) { - status_trace("Too-old update for %s", - fmt_short_channel_id(tmpctx, scid)); - /* Too old, ignore */ + /* Don't spam the logs for duplicates! */ + if (timestamp < prev_timestamp) + status_trace("Too-old update for %s", + fmt_short_channel_id(tmpctx, scid)); + /* Too old / redundant, ignore */ return NULL; } } else { From ff7ded7a5fb3c27e962114274185a3b34ad90c91 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 18 Mar 2025 14:35:13 +1030 Subject: [PATCH 5/6] lightningd: don't hand redundant block_height to block notifications. They can all call get_block_height(); the extra argument confused me and I thought they were called before the block height was actually updated. Signed-off-by: Rusty Russell --- lightningd/chaintopology.c | 4 ++-- lightningd/channel_control.c | 23 ++++++++++----------- lightningd/channel_control.h | 3 +-- lightningd/channel_gossip.c | 10 ++++----- lightningd/channel_gossip.h | 3 +-- lightningd/coin_mvts.c | 4 ++-- lightningd/coin_mvts.h | 2 +- lightningd/gossip_control.c | 6 ++++-- lightningd/gossip_control.h | 2 +- lightningd/lightningd.c | 12 +++++------ lightningd/lightningd.h | 2 +- lightningd/peer_control.c | 7 +++---- lightningd/peer_control.h | 3 +-- lightningd/peer_htlcs.c | 3 ++- lightningd/peer_htlcs.h | 2 +- lightningd/test/run-find_my_abspath.c | 13 +++++------- lightningd/test/run-invoice-select-inchan.c | 4 ---- wallet/test/run-wallet.c | 4 ---- 18 files changed, 46 insertions(+), 61 deletions(-) diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 41b9e0e68a8c..3630623d8fc3 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -824,7 +824,7 @@ static void updates_complete(struct chain_topology *topo) { if (!bitcoin_blkid_eq(&topo->tip->blkid, &topo->prev_tip)) { /* Tell lightningd about new block. */ - notify_new_block(topo->bitcoind->ld, topo->tip->height); + notify_new_block(topo->bitcoind->ld); /* Tell watch code to re-evaluate all txs. */ watch_topology_changed(topo); @@ -840,7 +840,7 @@ static void updates_complete(struct chain_topology *topo) /* Send out an account balance snapshot */ if (!first_update_complete) { - send_account_balance_snapshot(topo->ld, topo->tip->height); + send_account_balance_snapshot(topo->ld); first_update_complete = true; } } diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index d344c2f3585b..8e22b0702a41 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -114,9 +114,9 @@ static void try_update_feerates(struct lightningd *ld, struct channel *channel) } static void try_update_blockheight(struct lightningd *ld, - struct channel *channel, - u32 blockheight) + struct channel *channel) { + u32 blockheight = get_block_height(ld->topology); u8 *msg; /* We don't update the blockheight for non-leased chans */ @@ -1005,7 +1005,7 @@ void lockin_has_completed(struct channel *channel, bool record_push) * so update now. */ try_update_feerates(ld, channel); - try_update_blockheight(ld, channel, get_block_height(ld->topology)); + try_update_blockheight(ld, channel); /* Emit an event for the channel open (or channel proposal if blockheight * is zero) */ @@ -1878,8 +1878,7 @@ bool peer_start_channeld(struct channel *channel, * might not be what we expect: adjust now. */ if (channel->opener == LOCAL) { try_update_feerates(ld, channel); - try_update_blockheight(ld, channel, - get_block_height(ld->topology)); + try_update_blockheight(ld, channel); } /* "Reestablished" if we've just opened. */ @@ -1925,9 +1924,10 @@ void channeld_tell_depth(struct channel *channel, * If so, we should forget the channel. */ static bool is_fundee_should_forget(struct lightningd *ld, - struct channel *channel, - u32 block_height) + struct channel *channel) { + u32 block_height = get_block_height(ld->topology); + /* BOLT #2: * * A non-funding node (fundee): @@ -1967,9 +1967,9 @@ is_fundee_should_forget(struct lightningd *ld, } /* Notify all channels of new blocks. */ -void channel_notify_new_block(struct lightningd *ld, - u32 block_height) +void channel_notify_new_block(struct lightningd *ld) { + u32 block_height = get_block_height(ld->topology); struct peer *peer; struct channel *channel; struct channel **to_forget = tal_arr(NULL, struct channel *, 0); @@ -1983,13 +1983,12 @@ void channel_notify_new_block(struct lightningd *ld, list_for_each(&peer->channels, channel, list) { if (channel_state_uncommitted(channel->state)) continue; - if (is_fundee_should_forget(ld, channel, block_height)) { + if (is_fundee_should_forget(ld, channel)) { tal_arr_expand(&to_forget, channel); } else /* Let channels know about new blocks, * required for lease updates */ - try_update_blockheight(ld, channel, - block_height); + try_update_blockheight(ld, channel); } } diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index 199657abe1e0..9107fbd3aa8b 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -23,8 +23,7 @@ void channeld_tell_depth(struct channel *channel, u32 depth); /* Notify channels of new blocks. */ -void channel_notify_new_block(struct lightningd *ld, - u32 block_height); +void channel_notify_new_block(struct lightningd *ld); /* Cancel the channel after `fundchannel_complete` succeeds * but before funding broadcasts. */ diff --git a/lightningd/channel_gossip.c b/lightningd/channel_gossip.c index e429a3fce28b..e7cf9f0a67fe 100644 --- a/lightningd/channel_gossip.c +++ b/lightningd/channel_gossip.c @@ -752,8 +752,7 @@ void channel_gossip_scid_changed(struct channel *channel) /* Block height changed */ static void new_blockheight(struct lightningd *ld, - struct channel *channel, - u32 block_height) + struct channel *channel) { switch (channel->channel_gossip->state) { case CGOSSIP_PRIVATE: @@ -762,7 +761,7 @@ static void new_blockheight(struct lightningd *ld, case CGOSSIP_NOT_USABLE: return; case CGOSSIP_NOT_DEEP_ENOUGH: - if (!channel_announceable(channel, block_height)) { + if (!channel_announceable(channel, get_block_height(ld->topology))) { check_channel_gossip(channel); return; } @@ -773,8 +772,7 @@ static void new_blockheight(struct lightningd *ld, fatal("Bad channel_gossip_state %u", channel->channel_gossip->state); } -void channel_gossip_notify_new_block(struct lightningd *ld, - u32 block_height) +void channel_gossip_notify_new_block(struct lightningd *ld) { struct peer *peer; struct channel *channel; @@ -788,7 +786,7 @@ void channel_gossip_notify_new_block(struct lightningd *ld, if (!channel->channel_gossip) continue; - new_blockheight(ld, channel, block_height); + new_blockheight(ld, channel); check_channel_gossip(channel); } } diff --git a/lightningd/channel_gossip.h b/lightningd/channel_gossip.h index 0a81089dea14..6b8e4e203262 100644 --- a/lightningd/channel_gossip.h +++ b/lightningd/channel_gossip.h @@ -23,8 +23,7 @@ void channel_gossip_update(struct channel *channel); void channel_gossip_scid_changed(struct channel *channel); /* Block height changed */ -void channel_gossip_notify_new_block(struct lightningd *ld, - u32 block_height); +void channel_gossip_notify_new_block(struct lightningd *ld); /* Got announcement_signatures from peer */ void channel_gossip_got_announcement_sigs(struct channel *channel, diff --git a/lightningd/coin_mvts.c b/lightningd/coin_mvts.c index 74f940384fa5..df91cabb6a1b 100644 --- a/lightningd/coin_mvts.c +++ b/lightningd/coin_mvts.c @@ -103,7 +103,7 @@ static bool report_chan_balance(const struct channel *chan) abort(); } -void send_account_balance_snapshot(struct lightningd *ld, u32 blockheight) +void send_account_balance_snapshot(struct lightningd *ld) { struct balance_snapshot *snap = tal(NULL, struct balance_snapshot); struct account_balance *bal; @@ -112,7 +112,7 @@ void send_account_balance_snapshot(struct lightningd *ld, u32 blockheight) struct peer *p; struct peer_node_id_map_iter it; - snap->blockheight = blockheight; + snap->blockheight = get_block_height(ld->topology); snap->timestamp = time_now().ts.tv_sec; snap->node_id = &ld->our_nodeid; diff --git a/lightningd/coin_mvts.h b/lightningd/coin_mvts.h index 70ce9aa6c4d6..90db53178c74 100644 --- a/lightningd/coin_mvts.h +++ b/lightningd/coin_mvts.h @@ -36,5 +36,5 @@ struct channel_coin_mvt *new_channel_mvt_routed_hout(const tal_t *ctx, struct htlc_out *hout, struct channel *channel); -void send_account_balance_snapshot(struct lightningd *ld, u32 blockheight); +void send_account_balance_snapshot(struct lightningd *ld); #endif /* LIGHTNING_LIGHTNINGD_COIN_MVTS_H */ diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index e22bd1083f1e..a4e8477a98ca 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -255,8 +255,10 @@ static void gossipd_new_blockheight_reply(struct subd *gossipd, gossipd->ld->gossip_blockheight); } -void gossip_notify_new_block(struct lightningd *ld, u32 blockheight) +void gossip_notify_new_block(struct lightningd *ld) { + u32 blockheight = get_block_height(ld->topology); + /* Only notify gossipd once we're synced. */ if (!topology_synced(ld->topology)) return; @@ -269,7 +271,7 @@ void gossip_notify_new_block(struct lightningd *ld, u32 blockheight) static void gossip_topology_synced(struct chain_topology *topo, void *unused) { /* Now we start telling gossipd about blocks. */ - gossip_notify_new_block(topo->ld, get_block_height(topo)); + gossip_notify_new_block(topo->ld); } /* We make sure gossipd is started before plugins (which may want gossip_map) */ diff --git a/lightningd/gossip_control.h b/lightningd/gossip_control.h index cc9827b056a2..06a248799dfd 100644 --- a/lightningd/gossip_control.h +++ b/lightningd/gossip_control.h @@ -14,6 +14,6 @@ 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); +void gossip_notify_new_block(struct lightningd *ld); #endif /* LIGHTNING_LIGHTNINGD_GOSSIP_CONTROL_H */ diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index accd93ec6bdd..524de213cd05 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -768,14 +768,14 @@ static int io_poll_lightningd(struct pollfd *fds, nfds_t nfds, int timeout) * like this, and it's always better to have compile-time calls than runtime, * as it makes the code more explicit. But pasting in direct calls is also an * abstraction violation, so we use this middleman function. */ -void notify_new_block(struct lightningd *ld, u32 block_height) +void notify_new_block(struct lightningd *ld) { /* Inform our subcomponents individually. */ - htlcs_notify_new_block(ld, block_height); - channel_notify_new_block(ld, block_height); - channel_gossip_notify_new_block(ld, block_height); - gossip_notify_new_block(ld, block_height); - waitblockheight_notify_new_block(ld, block_height); + htlcs_notify_new_block(ld); + channel_notify_new_block(ld); + channel_gossip_notify_new_block(ld); + gossip_notify_new_block(ld); + waitblockheight_notify_new_block(ld); } static void on_sigint(int _ UNUSED) diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 45732c006f8d..7fd07a274d42 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -439,7 +439,7 @@ const char *subdaemon_path(const tal_t *ctx, const struct lightningd *ld, const void test_subdaemons(const struct lightningd *ld); /* Notify lightningd about new blocks. */ -void notify_new_block(struct lightningd *ld, u32 block_height); +void notify_new_block(struct lightningd *ld); /* Signal a clean exit from lightningd. * NOTE! This function **returns**. diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 75eac3fc7a7d..2190f0d71aa3 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -2912,9 +2912,9 @@ timeout_waitblockheight_waiter(struct waitblockheight_waiter *w) "Timed out.")); } /* Called by lightningd at each new block. */ -void waitblockheight_notify_new_block(struct lightningd *ld, - u32 block_height) +void waitblockheight_notify_new_block(struct lightningd *ld) { + u32 block_height = get_block_height(ld->topology); struct waitblockheight_waiter *w, *n; char *to_delete = tal(NULL, char); @@ -2929,8 +2929,7 @@ void waitblockheight_notify_new_block(struct lightningd *ld, list_del(&w->list); w->removed = true; tal_steal(to_delete, w); - was_pending(waitblockheight_complete(w->cmd, - block_height)); + was_pending(waitblockheight_complete(w->cmd, block_height)); } tal_free(to_delete); } diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 88a5f8866759..88d769e4bb77 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -154,8 +154,7 @@ struct leak_detect; void peer_dev_memleak(struct lightningd *ld, struct leak_detect *leaks); /* Triggered at each new block. */ -void waitblockheight_notify_new_block(struct lightningd *ld, - u32 block_height); +void waitblockheight_notify_new_block(struct lightningd *ld); /* JSON parameter by channel_id or scid (caller must check state!) */ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 8bfb9afa42f1..a91fce7fd9a1 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -2791,9 +2791,10 @@ static void consider_failing_incoming(struct lightningd *ld, local_fail_in_htlc(hout->in, take(towire_permanent_channel_failure(NULL))); } -void htlcs_notify_new_block(struct lightningd *ld, u32 height) +void htlcs_notify_new_block(struct lightningd *ld) { bool removed; + u32 height = get_block_height(ld->topology); /* BOLT #2: * diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 9b9e67255b74..edd9e3cffe30 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -46,7 +46,7 @@ void onchain_failed_our_htlc(const struct channel *channel, void onchain_fulfilled_htlc(struct channel *channel, const struct preimage *preimage); -void htlcs_notify_new_block(struct lightningd *ld, u32 height); +void htlcs_notify_new_block(struct lightningd *ld); /* Only defined if COMPAT_V061 */ void fixup_htlcs_out(struct lightningd *ld); diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 2e5c3332cd5a..b8eb2743281f 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -11,12 +11,10 @@ int unused_main(int argc, char *argv[]); void begin_topology(struct chain_topology *topo UNNEEDED) { fprintf(stderr, "begin_topology called!\n"); abort(); } /* Generated stub for channel_gossip_notify_new_block */ -void channel_gossip_notify_new_block(struct lightningd *ld UNNEEDED, - u32 block_height UNNEEDED) +void channel_gossip_notify_new_block(struct lightningd *ld UNNEEDED) { fprintf(stderr, "channel_gossip_notify_new_block called!\n"); abort(); } /* Generated stub for channel_notify_new_block */ -void channel_notify_new_block(struct lightningd *ld UNNEEDED, - u32 block_height UNNEEDED) +void channel_notify_new_block(struct lightningd *ld UNNEEDED) { fprintf(stderr, "channel_notify_new_block called!\n"); abort(); } /* Generated stub for connectd_activate */ void connectd_activate(struct lightningd *ld UNNEEDED) @@ -112,7 +110,7 @@ bool fromwire_status_version(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, void gossip_init(struct lightningd *ld UNNEEDED, int connectd_fd UNNEEDED) { fprintf(stderr, "gossip_init called!\n"); abort(); } /* Generated stub for gossip_notify_new_block */ -void gossip_notify_new_block(struct lightningd *ld UNNEEDED, u32 blockheight UNNEEDED) +void gossip_notify_new_block(struct lightningd *ld UNNEEDED) { fprintf(stderr, "gossip_notify_new_block called!\n"); abort(); } /* Generated stub for handle_early_opts */ void handle_early_opts(struct lightningd *ld UNNEEDED, int argc UNNEEDED, char *argv[]) @@ -127,7 +125,7 @@ size_t hash_htlc_key(const struct htlc_key *htlc_key UNNEEDED) struct ext_key *hsm_init(struct lightningd *ld UNNEEDED) { fprintf(stderr, "hsm_init called!\n"); abort(); } /* Generated stub for htlcs_notify_new_block */ -void htlcs_notify_new_block(struct lightningd *ld UNNEEDED, u32 height UNNEEDED) +void htlcs_notify_new_block(struct lightningd *ld UNNEEDED) { fprintf(stderr, "htlcs_notify_new_block called!\n"); abort(); } /* Generated stub for htlcs_resubmit */ void htlcs_resubmit(struct lightningd *ld UNNEEDED, @@ -283,8 +281,7 @@ struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED) const char *version(void) { fprintf(stderr, "version called!\n"); abort(); } /* Generated stub for waitblockheight_notify_new_block */ -void waitblockheight_notify_new_block(struct lightningd *ld UNNEEDED, - u32 block_height UNNEEDED) +void waitblockheight_notify_new_block(struct lightningd *ld UNNEEDED) { fprintf(stderr, "waitblockheight_notify_new_block called!\n"); abort(); } /* Generated stub for wallet_new */ struct wallet *wallet_new(struct lightningd *ld UNNEEDED, struct timers *timers UNNEEDED) diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 195db8a2cfc7..5c1300c67d6a 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -907,10 +907,6 @@ bool peer_start_channeld(struct channel *channel UNNEEDED, bool reconnected UNNEEDED, bool reestablish_only UNNEEDED) { fprintf(stderr, "peer_start_channeld called!\n"); abort(); } -/* Generated stub for peer_start_closingd */ -void peer_start_closingd(struct channel *channel UNNEEDED, - struct peer_fd *peer_fd UNNEEDED) -{ fprintf(stderr, "peer_start_closingd called!\n"); abort(); } /* Generated stub for peer_start_dualopend */ bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, struct channel *channel UNNEEDED) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 82be3f8babe2..6f0838beda72 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -929,10 +929,6 @@ bool peer_start_channeld(struct channel *channel UNNEEDED, bool reconnected UNNEEDED, bool reestablish_only UNNEEDED) { fprintf(stderr, "peer_start_channeld called!\n"); abort(); } -/* Generated stub for peer_start_closingd */ -void peer_start_closingd(struct channel *channel UNNEEDED, - struct peer_fd *peer_fd UNNEEDED) -{ fprintf(stderr, "peer_start_closingd called!\n"); abort(); } /* Generated stub for peer_start_dualopend */ bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, struct channel *channel UNNEEDED) From af559ce1fb2ea8116823ede1382b5a465ac4e6e2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 19 Mar 2025 12:29:10 +1030 Subject: [PATCH 6/6] lightningd: send announcement_signatures once channel is ready, don't wait until 6 deep. The spec used to say you had to wait for channel to be ready, *and* 6 depth before exchanging signatures. Now the 6 depth requirement is only on the actual announcing of the channel: you can send sigs any time. This means our state machine goes from: NOT_USABLE -> NOT_DEEP_ENOUGH -> NEED_PEER_SIGS -> ANNOUNCED to: NOT_USABLE -> NEED_PEER_SIGS -> NOT_DEEP_ENOUGH -> ANNOUNCED However, this revealed that our state machine is insufficient, so rework it to be more general and understandable. In particular, check for unexpected state transitions, and thus document them. Signed-off-by: Rusty Russell Changelog-Changed: Protocol: We now exchange `announcement_signatures` as soon as we're ready, rather than waiting for 6 blocks (as per recent BOLT update) --- lightningd/channel_gossip.c | 763 ++++++++++++++++++++++++------------ tests/test_gossip.py | 8 +- wallet/test/run-wallet.c | 9 +- 3 files changed, 521 insertions(+), 259 deletions(-) diff --git a/lightningd/channel_gossip.c b/lightningd/channel_gossip.c index e7cf9f0a67fe..5c56ae2e0885 100644 --- a/lightningd/channel_gossip.c +++ b/lightningd/channel_gossip.c @@ -1,4 +1,5 @@ #include "config.h" +#include #include #include #include @@ -16,14 +17,28 @@ #include enum channel_gossip_state { - /* Not a public channel */ + /* It's dead, so don't talk about it. */ + CGOSSIP_CHANNEL_DEAD, + /* It's dying, but we can still broadcast the "disabled" update. */ + CGOSSIP_CHANNEL_ANNOUNCED_DYING, + /* It's dead: send the "disabled" update only as error reply. */ + CGOSSIP_CHANNEL_ANNOUNCED_DEAD, + + /* Unannounced channels: without alias or scid */ + CGOSSIP_PRIVATE_WAITING_FOR_USABLE, + /* With alias/scid */ CGOSSIP_PRIVATE, - /* We can't yet send (non-forwardable) channel_update. */ - CGOSSIP_NOT_USABLE, - /* Not yet in at announcable depth. */ - CGOSSIP_NOT_DEEP_ENOUGH, - /* We want the peer's announcement_signatures. */ - CGOSSIP_NEED_PEER_SIGS, + + /* Public channels: */ + /* Not usable. */ + CGOSSIP_WAITING_FOR_USABLE, + /* No scid (zeroconf can be in CHANNELD_NORMAL without scid) */ + CGOSSIP_WAITING_FOR_SCID, + /* Sent ours, we want the peer's announcement_signatures (or + * we have it, but different scids) */ + CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, + /* Not yet in at announceable depth (6). */ + CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, /* We have received sigs, and announced. */ CGOSSIP_ANNOUNCED, }; @@ -31,20 +46,110 @@ enum channel_gossip_state { static const char *channel_gossip_state_str(enum channel_gossip_state s) { switch (s) { + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: + return "CGOSSIP_PRIVATE_WAITING_FOR_USABLE"; case CGOSSIP_PRIVATE: return "CGOSSIP_PRIVATE"; - case CGOSSIP_NOT_USABLE: - return "CGOSSIP_NOT_USABLE"; - case CGOSSIP_NOT_DEEP_ENOUGH: - return "CGOSSIP_NOT_DEEP_ENOUGH"; - case CGOSSIP_NEED_PEER_SIGS: - return "CGOSSIP_NEED_PEER_SIGS"; + case CGOSSIP_WAITING_FOR_USABLE: + return "CGOSSIP_WAITING_FOR_USABLE"; + case CGOSSIP_WAITING_FOR_SCID: + return "CGOSSIP_WAITING_FOR_SCID"; + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + return "CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS"; + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: + return "CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH"; case CGOSSIP_ANNOUNCED: return "CGOSSIP_ANNOUNCED"; + case CGOSSIP_CHANNEL_DEAD: + return "CGOSSIP_CHANNEL_DEAD"; + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + return "CGOSSIP_CHANNEL_ANNOUNCED_DYING"; + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + return "CGOSSIP_CHANNEL_ANNOUNCED_DEAD"; } return "***INVALID***"; } +struct state_transition { + enum channel_gossip_state from, to; + const char *description; +}; + +static struct state_transition allowed_transitions[] = { + /* Private channels */ + { CGOSSIP_PRIVATE_WAITING_FOR_USABLE, CGOSSIP_CHANNEL_DEAD, + "Unannounced channel closed before it had scid or alias" }, + { CGOSSIP_PRIVATE_WAITING_FOR_USABLE, CGOSSIP_PRIVATE, + "Unannounced channel live" }, + { CGOSSIP_PRIVATE, CGOSSIP_CHANNEL_DEAD, + "Unannounced channel closed" }, + + /* Public channels, startup */ + { CGOSSIP_WAITING_FOR_USABLE, CGOSSIP_CHANNEL_DEAD, + "Channel closed before it had scid or alias" }, + { CGOSSIP_WAITING_FOR_USABLE, CGOSSIP_WAITING_FOR_SCID, + "Channel usable (zeroconf) but no scid yet" }, + { CGOSSIP_WAITING_FOR_SCID, CGOSSIP_CHANNEL_DEAD, + "Zeroconf channel closed before funding tx mined" }, + { CGOSSIP_WAITING_FOR_USABLE, CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, + "Channel mined, but we haven't got matching announcment sigs from peer" }, + { CGOSSIP_WAITING_FOR_USABLE, CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, + "Channel mined, they had already sent announcement sigs when we noticed" }, + { CGOSSIP_WAITING_FOR_SCID, CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, + "Channel mined (zeroconf), but we haven't got matching announcment sigs from peer" }, + { CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, CGOSSIP_CHANNEL_DEAD, + "Channel closed while waiting for announcement sigs from peer" }, + { CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, + "Channel now waiting for 6 confirms to publish announcement" }, + { CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, CGOSSIP_CHANNEL_DEAD, + "Channel closed before 6 confirms" }, + { CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, CGOSSIP_ANNOUNCED, + "Channel fully announced" }, + { CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, CGOSSIP_ANNOUNCED, + "Got peer announcement signatures after already at 6 confirmations" }, + { CGOSSIP_WAITING_FOR_USABLE, CGOSSIP_ANNOUNCED, + "We got peer sigs first, then 6 confirms, then finally received CHANNEL_READY" }, + + /* Splice */ + { CGOSSIP_ANNOUNCED, CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, + "Splicing"}, + { CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, + "Splicing before 6 confirmations"}, + + /* Public channels, closing */ + { CGOSSIP_ANNOUNCED, CGOSSIP_CHANNEL_ANNOUNCED_DYING, + "Announced channel closing, but close tx not seen onchain yet." }, + { CGOSSIP_ANNOUNCED, CGOSSIP_CHANNEL_ANNOUNCED_DEAD, + "Announced channel closed by seeing onchain tx." }, + { CGOSSIP_CHANNEL_ANNOUNCED_DYING, CGOSSIP_CHANNEL_ANNOUNCED_DEAD, + "Announced channel closed onchain." }, + { CGOSSIP_CHANNEL_DEAD, CGOSSIP_CHANNEL_ANNOUNCED_DEAD, + "Channel closed before 6 confirms, but now has 6 confirms so could be announced." }, + { CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, CGOSSIP_CHANNEL_ANNOUNCED_DYING, + "Channel hit announced depth, but closed" }, +}; + +static void check_state_transition(const struct channel *channel, + enum channel_gossip_state oldstate, + enum channel_gossip_state newstate) +{ + /* Check transition */ + for (size_t i = 0; i < ARRAY_SIZE(allowed_transitions); i++) { + if (allowed_transitions[i].from == oldstate + && allowed_transitions[i].to == newstate) { + log_debug(channel->log, "gossip state: %s->%s (%s)", + channel_gossip_state_str(oldstate), + channel_gossip_state_str(newstate), + allowed_transitions[i].description); + return; + } + } + + log_broken(channel->log, "Illegal gossip state transition: %s->%s", + channel_gossip_state_str(oldstate), + channel_gossip_state_str(newstate)); +} + struct remote_announce_sigs { struct short_channel_id scid; secp256k1_ecdsa_signature node_sig; @@ -66,71 +171,162 @@ struct channel_gossip { /* Details of latest channel_update sent by peer */ const struct peer_update *peer_update; + + /* To avoid a storm, we only respond to announcement_signatures with + * our own signatures once */ + bool sent_sigs; }; static bool starting_up = true, gossipd_init_done = false; -/* We send non-forwardable channel updates if we can. */ -static bool can_send_channel_update(const struct channel *channel) +static bool is_private(const struct channel *channel) +{ + return !(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL); +} + +static bool is_usable(const struct channel *channel) { + if (channel_state_pre_open(channel->state)) + return false; /* Can't send if we can't talk about it. */ - if (!channel->scid && !channel->alias[REMOTE]) + return channel->scid != NULL || channel->alias[REMOTE] != NULL; +} + +static bool has_scid(const struct channel *channel) +{ + if (!is_usable(channel)) return false; - if (channel_state_pre_open(channel->state)) + return channel->scid != NULL; +} + +static bool has_matching_peer_sigs(const struct channel *channel) +{ + const struct channel_gossip *cg = channel->channel_gossip; + + if (!has_scid(channel)) return false; - return true; + + if (!cg->remote_sigs) + return false; + + return short_channel_id_eq(cg->remote_sigs->scid, *channel->scid); } -/* We send start the channel announcement signatures if we can. - * Caller must check it's not CGOSSIP_PRIVATE, but this is used - * to set up state so we cannot assert here! - */ -static bool channel_announceable(const struct channel *channel, - u32 block_height) +static bool has_announce_depth(const struct channel *channel) { - if (!channel->scid) + u32 block_height = get_block_height(channel->peer->ld->topology); + + if (!has_matching_peer_sigs(channel)) return false; + return is_scid_depth_announceable(*channel->scid, block_height); } -static void check_channel_gossip(const struct channel *channel) +/* Truly dead once we've seen spend onchain */ +static bool is_dead(const struct channel *channel) +{ + return channel_state_funding_spent_onchain(channel->state); +} + +static bool is_announced_dying(const struct channel *channel) +{ + return has_announce_depth(channel) + && channel_state_closing(channel->state) + && !channel_state_funding_spent_onchain(channel->state); +} + +static bool is_announced_dead(const struct channel *channel) +{ + return has_announce_depth(channel) + && channel_state_funding_spent_onchain(channel->state); +} + +#define check_channel_gossip(channel) check_channel_gossip_((channel), __LINE__) +static void check_channel_gossip_(const struct channel *channel, int line) { struct channel_gossip *cg = channel->channel_gossip; + bool enabled; + log_debug(channel->log, "checking channel gossip (%u)...", line); /* Note: we can't assert is_scid_depth_announceable, for two reasons: - * 1. on restart and rescan, block numbers can go backwards.' + * 1. on restar_t and rescan, block numbers can go backwards.' * 2. We don't get notified via channel_gossip_notify_new_block until * there are no new blocks to add, not on every block. */ switch (cg->state) { + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: + assert(is_private(channel)); + assert(!is_dead(channel)); + assert(!is_usable(channel)); + assert(!cg->remote_sigs); + assert(!cg->refresh_timer); + return; case CGOSSIP_PRIVATE: - assert(!(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)); + assert(is_private(channel)); + assert(!is_dead(channel)); + assert(is_usable(channel)); assert(!cg->remote_sigs); assert(!cg->refresh_timer); return; - - case CGOSSIP_NOT_USABLE: - assert(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL); - assert(!can_send_channel_update(channel)); + case CGOSSIP_WAITING_FOR_USABLE: + assert(!is_private(channel)); + assert(!is_dead(channel)); + assert(!is_usable(channel)); + assert(!cg->refresh_timer); + return; + case CGOSSIP_WAITING_FOR_SCID: + assert(!is_private(channel)); + assert(!is_dead(channel)); + assert(!has_scid(channel)); assert(!cg->refresh_timer); return; - case CGOSSIP_NOT_DEEP_ENOUGH: - assert(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL); - assert(can_send_channel_update(channel)); + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + assert(!is_private(channel)); + assert(!is_dead(channel)); + assert(!has_matching_peer_sigs(channel)); assert(!cg->refresh_timer); return; - case CGOSSIP_NEED_PEER_SIGS: - assert(can_send_channel_update(channel)); - assert(channel->scid); - /* If we have sigs, they don't match */ - if (cg->remote_sigs) - assert(!channel->scid || !short_channel_id_eq(cg->remote_sigs->scid, *channel->scid)); + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: + assert(!is_private(channel)); + assert(!is_dead(channel)); + /* We can't actually know !has_announce_depth: current + * block height may not have been updated to match! */ assert(!cg->refresh_timer); return; case CGOSSIP_ANNOUNCED: - assert(can_send_channel_update(channel)); - assert(channel->scid); - assert(cg->remote_sigs); + assert(!is_private(channel)); + assert(!is_dead(channel)); + /* We can't actually know !has_announce_depth: current + * block height may not have been updated to match! */ + /* refresh_timer is not always set at init */ + return; + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + assert(!is_dead(channel)); + assert(has_announce_depth(channel)); + /* We may not have a cupdate in some odd cases, e.g. reorg */ + if (cg->cupdate) { + assert(channel_update_details(cg->cupdate, NULL, + &enabled)); + assert(!enabled); + } + assert(!cg->refresh_timer); + return; + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + assert(is_dead(channel)); + assert(is_announced_dead(channel)); + /* We may not have a cupdate in some odd cases, e.g. reorg */ + if (cg->cupdate) { + assert(channel_update_details(cg->cupdate, NULL, + &enabled)); + assert(!enabled); + } + assert(!cg->refresh_timer); + return; + case CGOSSIP_CHANNEL_DEAD: + assert(is_dead(channel)); + assert(!is_announced_dying(channel)); + assert(!cg->cupdate); + assert(!cg->refresh_timer); return; } fatal("Bad channel_gossip_state %u", cg->state); @@ -179,6 +375,10 @@ static void broadcast_new_gossip(struct lightningd *ld, if (taken(msg)) tal_steal(tmpctx, msg); + /* Don't crash if shutting down */ + if (!ld->gossip) + return; + /* Tell gossipd about it */ subd_req(ld->gossip, ld->gossip, take(towire_gossipd_addgossip(NULL, msg, known_channel)), @@ -199,24 +399,35 @@ static void broadcast_new_gossip(struct lightningd *ld, /* Recursion */ static void cupdate_timer_refresh(struct channel *channel); -static enum channel_gossip_state init_public_state(struct channel *channel, - const struct remote_announce_sigs *remote_sigs) +static enum channel_gossip_state derive_channel_state(const struct channel *channel) { - struct lightningd *ld = channel->peer->ld; + if (is_announced_dying(channel)) + return CGOSSIP_CHANNEL_ANNOUNCED_DYING; - if (!can_send_channel_update(channel)) - return CGOSSIP_NOT_USABLE; + if (is_announced_dead(channel)) + return CGOSSIP_CHANNEL_ANNOUNCED_DEAD; - /* Note: depth when we startup is not actually reliable, since - * we step one block back. We'll fix this up when gossipd - * tells us it's announced, or, when we add the block. */ - if (!channel_announceable(channel, get_block_height(ld->topology))) - return CGOSSIP_NOT_DEEP_ENOUGH; + if (is_dead(channel)) + return CGOSSIP_CHANNEL_DEAD; - if (!remote_sigs) { - return CGOSSIP_NEED_PEER_SIGS; + if (is_private(channel)) { + if (!is_usable(channel)) + return CGOSSIP_PRIVATE_WAITING_FOR_USABLE; + return CGOSSIP_PRIVATE; } + if (!is_usable(channel)) + return CGOSSIP_WAITING_FOR_USABLE; + + if (!has_scid(channel)) + return CGOSSIP_WAITING_FOR_SCID; + + if (!has_matching_peer_sigs(channel)) + return CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS; + + if (!has_announce_depth(channel)) + return CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH; + return CGOSSIP_ANNOUNCED; } @@ -243,10 +454,6 @@ static void send_private_cupdate(struct channel *channel, bool even_if_redundant const u8 *cupdate; struct short_channel_id scid; - /* Only useful channels: not if closing */ - if (!channel_state_can_add_htlc(channel->state)) - return; - /* BOLT #7: * * - MAY create a `channel_update` to communicate the channel @@ -416,27 +623,34 @@ static void stash_remote_announce_sigs(struct channel *channel, "channel_gossip: received announcement sigs for %s (we have %s)", fmt_short_channel_id(tmpctx, scid), channel->scid ? fmt_short_channel_id(tmpctx, *channel->scid) : "none"); -} -static bool apply_remote_sigs(struct channel *channel) -{ - struct channel_gossip *cg = channel->channel_gossip; - - if (!cg->remote_sigs) - return false; + /* Save to db if we like these signatures */ + if (!channel->scid) + return; if (!short_channel_id_eq(cg->remote_sigs->scid, *channel->scid)) { log_debug(channel->log, "We have remote sigs, but wrong scid!"); - return false; + return; } wallet_announcement_save(channel->peer->ld->wallet, channel->dbid, &cg->remote_sigs->node_sig, &cg->remote_sigs->bitcoin_sig); - return true; } +/* BOLT #7: + * A node: + * - If the `open_channel` message has the `announce_channel` bit set AND a + * `shutdown` message has not been sent: + * - After `channel_ready` has been sent and received AND the funding + * transaction has enough confirmations to ensure that it won't be + * reorganized: + * - MUST send `announcement_signatures` for the funding transaction. + * - Otherwise: + * - MUST NOT send the `announcement_signatures` message. + */ + static void send_channel_announce_sigs(struct channel *channel) { /* First 2 + 256 byte are the signatures and msg type, skip them */ @@ -444,18 +658,18 @@ static void send_channel_announce_sigs(struct channel *channel) struct lightningd *ld = channel->peer->ld; struct sha256_double hash; secp256k1_ecdsa_signature local_node_sig, local_bitcoin_sig; + struct channel_gossip *cg = channel->channel_gossip; const u8 *ca, *msg; - /* If it's already closing, don't bother. */ - if (!channel_state_can_add_htlc(channel->state)) - return; - /* Wait until we've exchanged reestablish messages */ if (!channel->reestablished) { log_debug(channel->log, "channel_gossip: not sending channel_announcement_sigs until reestablished"); return; } + if (cg->sent_sigs) + return; + ca = create_channel_announcement(tmpctx, channel, *channel->scid, NULL, NULL, NULL, NULL); @@ -485,8 +699,10 @@ static void send_channel_announce_sigs(struct channel *channel) &channel->cid, *channel->scid, &local_node_sig, &local_bitcoin_sig); msg_to_peer(channel->peer, take(msg)); + cg->sent_sigs = true; } +/* Sends channel_announcement */ static void send_channel_announcement(struct channel *channel) { secp256k1_ecdsa_signature local_node_sig, local_bitcoin_sig; @@ -508,10 +724,6 @@ static void send_channel_announcement(struct channel *channel) &local_bitcoin_sig)) fatal("Reading hsmd_sign_any_cannouncement_reply: %s", tal_hex(tmpctx, msg)); - /* Don't crash if shutting down */ - if (!ld->gossip) - return; - ca = create_channel_announcement(tmpctx, channel, *channel->scid, &local_node_sig, &local_bitcoin_sig, @@ -520,46 +732,145 @@ static void send_channel_announcement(struct channel *channel) /* Send everyone our new channel announcement */ broadcast_new_gossip(ld, ca, &channel->funding_sats, "channel announcement"); - - /* Any private cupdate will be different from this, so will force a refresh. */ - update_channel_update(channel, channel_should_enable(channel, true)); - - broadcast_new_gossip(ld, cg->cupdate, NULL, "channel update"); - arm_refresh_timer(channel); - - /* And maybe our first node_announcement */ - channel_gossip_node_announce(ld); } -static void set_gossip_state(struct channel *channel, - enum channel_gossip_state state) +#define set_gossip_state(channel, state) \ + set_gossip_state_((channel), (state), __LINE__) +static void set_gossip_state_(struct channel *channel, + enum channel_gossip_state state, int line) { struct channel_gossip *cg = channel->channel_gossip; - cg->state = state; + check_state_transition(channel, cg->state, state); + /* Steps as we leave old state */ switch (cg->state) { + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: + case CGOSSIP_WAITING_FOR_USABLE: case CGOSSIP_PRIVATE: + case CGOSSIP_WAITING_FOR_SCID: + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + break; + case CGOSSIP_ANNOUNCED: + /* Stop refreshing (if we were) */ + cg->refresh_timer = tal_free(cg->refresh_timer); + break; + + /* We should never leave these */ + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + case CGOSSIP_CHANNEL_DEAD: + break; + } + + cg->state = state; + + /* Now the state we're entering */ + switch (cg->state) { + /* These are initial states, never set */ + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: + case CGOSSIP_WAITING_FOR_USABLE: abort(); - case CGOSSIP_NOT_USABLE: + + /* We don't do anything when we first enter these states */ + case CGOSSIP_PRIVATE: + case CGOSSIP_WAITING_FOR_SCID: return; - case CGOSSIP_NOT_DEEP_ENOUGH: - /* But it exists, so try sending private channel_update */ - send_private_cupdate(channel, false); + + /* Always ready to send sigs (once) if we're waiting + * for theirs: particularly for splicing. */ + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + cg->sent_sigs = false; return; - case CGOSSIP_NEED_PEER_SIGS: + + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: + wallet_announcement_save(channel->peer->ld->wallet, + channel->dbid, + &cg->remote_sigs->node_sig, + &cg->remote_sigs->bitcoin_sig); + return; + + case CGOSSIP_ANNOUNCED: + /* BOLT #7: + * A recipient node: + *... + * - If it has sent AND received a valid `announcement_signatures` + * message: + * - If the funding transaction has at least 6 confirmations: + * - SHOULD queue the `channel_announcement` message for + * its peers. + */ + send_channel_announcement(channel); + + /* Any private cupdate will be different from this, so will force a refresh. */ + update_channel_update(channel, channel_should_enable(channel, true)); + broadcast_new_gossip(channel->peer->ld, cg->cupdate, NULL, "channel update"); + + /* We need to refresh channel update every 13 days */ + arm_refresh_timer(channel); + + /* And maybe our first node_announcement */ + channel_gossip_node_announce(channel->peer->ld); + return; + + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + /* Make sure update tells them it's disabled */ + if (update_channel_update(channel, false)) { + /* We might have skipped over CGOSSIP_ANNOUNCED, so tell + * gossipd about us now, so it doesn't complain. */ + send_channel_announcement(channel); + /* And tell the world */ + broadcast_new_gossip(channel->peer->ld, cg->cupdate, NULL, + "channel update"); + } + return; + + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + /* It's disabled, but gossipd has forgotten it, so no + * broadcast */ + update_channel_update(channel, false); + return; + + case CGOSSIP_CHANNEL_DEAD: + return; + } + fatal("Bad channel_gossip_state %u", cg->state); +} + +static void update_gossip_state(struct channel *channel) +{ + enum channel_gossip_state newstate; + struct channel_gossip *cg = channel->channel_gossip; + + newstate = derive_channel_state(channel); + if (newstate != cg->state) + set_gossip_state(channel, newstate); + + switch (cg->state) { + case CGOSSIP_CHANNEL_DEAD: + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + case CGOSSIP_WAITING_FOR_USABLE: + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: + return; + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: send_channel_announce_sigs(channel); - /* We may already have remote signatures */ - if (!apply_remote_sigs(channel)) - return; - cg->state = CGOSSIP_ANNOUNCED; /* fall thru */ + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: + case CGOSSIP_WAITING_FOR_SCID: + case CGOSSIP_PRIVATE: + /* Always try to send private cupdate: ignored if redundant */ + send_private_cupdate(channel, false); + return; case CGOSSIP_ANNOUNCED: - /* Any previous update was private, so clear. */ - cg->cupdate = tal_free(cg->cupdate); - send_channel_announcement(channel); + /* If a channel parameter has changed, send new update */ + if (update_channel_update(channel, channel_should_enable(channel, true))) + broadcast_new_gossip(channel->peer->ld, cg->cupdate, NULL, + "channel update"); return; } + fatal("Bad channel_gossip_state %u", cg->state); } @@ -576,6 +887,7 @@ void channel_gossip_init(struct channel *channel, cg->refresh_timer = NULL; cg->peer_update = tal_dup_or_null(channel, struct peer_update, remote_update); cg->remote_sigs = NULL; + cg->sent_sigs = false; /* If we have an scid, we might have announcement signatures * saved in the db already. */ @@ -590,10 +902,9 @@ void channel_gossip_init(struct channel *channel, } } - if (public) - cg->state = init_public_state(channel, cg->remote_sigs); - else - cg->state = CGOSSIP_PRIVATE; + cg->state = derive_channel_state(channel); + log_debug(channel->log, "Initial channel state %s", + channel_gossip_state_str(cg->state)); check_channel_gossip(channel); } @@ -601,51 +912,13 @@ void channel_gossip_init(struct channel *channel, /* Something about channel changed: update if required */ void channel_gossip_update(struct channel *channel) { - struct lightningd *ld = channel->peer->ld; struct channel_gossip *cg = channel->channel_gossip; /* Ignore unsaved channels */ if (!cg) return; - switch (cg->state) { - case CGOSSIP_NOT_USABLE: - /* Change might make it usable */ - if (!can_send_channel_update(channel)) { - check_channel_gossip(channel); - return; - } - set_gossip_state(channel, CGOSSIP_NOT_DEEP_ENOUGH); - /* fall thru */ - case CGOSSIP_NOT_DEEP_ENOUGH: - /* Now we can send at non-forwardable update */ - send_private_cupdate(channel, false); - /* Might have gotten straight from not-usable to announceable - * if we have a flurry of blocks, or minconf >= 6. */ - if (!channel_announceable(channel, get_block_height(ld->topology))) { - check_channel_gossip(channel); - return; - } - set_gossip_state(channel, CGOSSIP_NEED_PEER_SIGS); - /* Could have actually already had sigs! */ - if (cg->state == CGOSSIP_ANNOUNCED) - goto announced; - /* fall thru */ - case CGOSSIP_PRIVATE: - case CGOSSIP_NEED_PEER_SIGS: - send_private_cupdate(channel, false); - check_channel_gossip(channel); - return; - case CGOSSIP_ANNOUNCED: - announced: - /* We don't penalize disconnected clients normally: we only - * do that if we actually try to send an htlc through */ - update_channel_update(channel, true); - broadcast_new_gossip(ld, cg->cupdate, NULL, "channel update"); - check_channel_gossip(channel); - return; - } - fatal("Bad channel_gossip_state %u", channel->channel_gossip->state); + update_gossip_state(channel); } void channel_gossip_got_announcement_sigs(struct channel *channel, @@ -659,7 +932,13 @@ void channel_gossip_got_announcement_sigs(struct channel *channel, return; } + /* Ignore the weird cases */ switch (channel->channel_gossip->state) { + case CGOSSIP_CHANNEL_DEAD: + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + return; + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: case CGOSSIP_PRIVATE: log_unusual(channel->log, "They sent an announcement_signatures message for a private channel? Ignoring."); u8 *warning = towire_warningfmt(NULL, @@ -667,35 +946,24 @@ void channel_gossip_got_announcement_sigs(struct channel *channel, "You sent announcement_signatures for private channel"); msg_to_peer(channel->peer, take(warning)); return; - case CGOSSIP_NOT_USABLE: - case CGOSSIP_NOT_DEEP_ENOUGH: - /* They're early? */ - stash_remote_announce_sigs(channel, - scid, node_sig, bitcoin_sig); - check_channel_gossip(channel); - return; - case CGOSSIP_NEED_PEER_SIGS: - stash_remote_announce_sigs(channel, - scid, node_sig, bitcoin_sig); - if (apply_remote_sigs(channel)) - set_gossip_state(channel, CGOSSIP_ANNOUNCED); - check_channel_gossip(channel); + case CGOSSIP_WAITING_FOR_SCID: + stash_remote_announce_sigs(channel, scid, node_sig, bitcoin_sig); return; case CGOSSIP_ANNOUNCED: - /* BOLT #7: - * - Upon reconnection (once the above timing requirements - * have been met): - *... - * - If it receives `announcement_signatures` for the - * funding transaction: - * - MUST respond with its own `announcement_signatures` - * message. - */ - send_channel_announce_sigs(channel); - check_channel_gossip(channel); - return; + /* We don't care what they said, but it does prompt our response */ + goto send_our_sigs; + case CGOSSIP_WAITING_FOR_USABLE: + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: + stash_remote_announce_sigs(channel, scid, node_sig, bitcoin_sig); + update_gossip_state(channel); + goto send_our_sigs; } fatal("Bad channel_gossip_state %u", channel->channel_gossip->state); + +send_our_sigs: + /* This only works once, so we won't spam them. */ + send_channel_announce_sigs(channel); } /* Short channel id changed (splice, or reorg). */ @@ -712,64 +980,38 @@ void channel_gossip_scid_changed(struct channel *channel) cg->cupdate = tal_free(cg->cupdate); /* Any announcement signatures we received for old scid are no longer - * valid. */ + * valid. We keep cg->remote_sigs though: it's common that they + * have already sent them for the new scid. */ wallet_remote_ann_sigs_clear(ld->wallet, channel); + /* Sanity check */ switch (cg->state) { - case CGOSSIP_PRIVATE: - /* Still private, just send new channel_update */ - send_private_cupdate(channel, false); - check_channel_gossip(channel); - return; - case CGOSSIP_NOT_USABLE: + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: + case CGOSSIP_WAITING_FOR_USABLE: + case CGOSSIP_WAITING_FOR_SCID: + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + case CGOSSIP_CHANNEL_DEAD: /* Shouldn't happen. */ + log_broken(channel->log, "Got scid change in state %s!", + channel_gossip_state_str(cg->state)); return; - case CGOSSIP_NOT_DEEP_ENOUGH: - case CGOSSIP_NEED_PEER_SIGS: + case CGOSSIP_PRIVATE: + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: case CGOSSIP_ANNOUNCED: - log_debug(channel->log, "channel_gossip: scid now %s", - fmt_short_channel_id(tmpctx, *channel->scid)); - /* Start again. */ - /* Maybe remote announcement signatures now apply? If not, - * free them */ - if (cg->remote_sigs - && !short_channel_id_eq(cg->remote_sigs->scid, - *channel->scid)) { - cg->remote_sigs = tal_free(cg->remote_sigs); - } - - /* Stop refresh timer, we're not announcing the old one. */ - cg->refresh_timer = tal_free(cg->refresh_timer); - - set_gossip_state(channel, - init_public_state(channel, cg->remote_sigs)); - send_channel_announce_sigs(channel); - check_channel_gossip(channel); - return; + break; } - fatal("Bad channel_gossip_state %u", cg->state); + + update_gossip_state(channel); } /* Block height changed */ static void new_blockheight(struct lightningd *ld, struct channel *channel) { - switch (channel->channel_gossip->state) { - case CGOSSIP_PRIVATE: - case CGOSSIP_NEED_PEER_SIGS: - case CGOSSIP_ANNOUNCED: - case CGOSSIP_NOT_USABLE: - return; - case CGOSSIP_NOT_DEEP_ENOUGH: - if (!channel_announceable(channel, get_block_height(ld->topology))) { - check_channel_gossip(channel); - return; - } - set_gossip_state(channel, CGOSSIP_NEED_PEER_SIGS); - check_channel_gossip(channel); - return; - } - fatal("Bad channel_gossip_state %u", channel->channel_gossip->state); + /* This can change state if we're CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH */ + update_gossip_state(channel); } void channel_gossip_notify_new_block(struct lightningd *ld) @@ -787,7 +1029,6 @@ void channel_gossip_notify_new_block(struct lightningd *ld) continue; new_blockheight(ld, channel); - check_channel_gossip(channel); } } } @@ -808,25 +1049,24 @@ void channel_gossip_update_from_gossipd(struct channel *channel, /* We might still want signatures from peer (we lost state?) */ switch (channel->channel_gossip->state) { case CGOSSIP_PRIVATE: - log_broken(channel->log, - "gossipd gave channel_update for private channel? update=%s", - tal_hex(tmpctx, channel_update)); - return; - /* This happens: we step back a block when restarting. We can - * fast-forward in this case. */ - case CGOSSIP_NOT_DEEP_ENOUGH: - set_gossip_state(channel, CGOSSIP_NEED_PEER_SIGS); - check_channel_gossip(channel); - break; - - case CGOSSIP_NOT_USABLE: - case CGOSSIP_NEED_PEER_SIGS: + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: + case CGOSSIP_WAITING_FOR_USABLE: + case CGOSSIP_CHANNEL_DEAD: + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + /* Shouldn't happen. */ if (taken(channel_update)) tal_free(channel_update); log_broken(channel->log, - "gossipd gave us channel_update for channel in gossip_state %s", - channel_gossip_state_str(channel->channel_gossip->state)); + "gossipd gave channel_update in %s? update=%s", + channel_gossip_state_str(channel->channel_gossip->state), + tal_hex(tmpctx, channel_update)); return; + + /* This happens: we step back a block when restarting. */ + case CGOSSIP_WAITING_FOR_SCID: + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: case CGOSSIP_ANNOUNCED: break; } @@ -891,8 +1131,16 @@ void channel_gossip_init_done(struct lightningd *ld) "gossipd lost track of announced channel: re-announcing!"); check_channel_gossip(channel); send_channel_announcement(channel); + update_channel_update(channel, channel_should_enable(channel, true)); + broadcast_new_gossip(ld, channel->channel_gossip->cupdate, NULL, "channel update"); + + /* We need to refresh channel update every 13 days */ + arm_refresh_timer(channel); } } + + /* And maybe our first node_announcement */ + channel_gossip_node_announce(ld); } static void channel_reestablished_stable(struct channel *channel) @@ -918,27 +1166,34 @@ void channel_gossip_channel_reestablished(struct channel *channel) if (!channel->channel_gossip) return; + /* We can re-xmit sigs once per reconnect */ + channel->channel_gossip->sent_sigs = false; + + /* BOLT #7: + * - Upon reconnection (once the above timing requirements have + * been met): + * - If it has NOT previously received + * `announcement_signatures` for the funding transaction: + * - MUST send its own `announcement_signatures` message. + */ + /* We also always send a private channel_update, even if redundant + * (they might have lost it) */ switch (channel->channel_gossip->state) { - case CGOSSIP_NOT_USABLE: - return; - case CGOSSIP_PRIVATE: - case CGOSSIP_NOT_DEEP_ENOUGH: - send_private_cupdate(channel, true); + case CGOSSIP_CHANNEL_DEAD: + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + case CGOSSIP_ANNOUNCED: + case CGOSSIP_WAITING_FOR_USABLE: + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: check_channel_gossip(channel); return; - case CGOSSIP_NEED_PEER_SIGS: - /* BOLT #7: - * - Upon reconnection (once the above timing requirements have - * been met): - * - If it has NOT previously received - * `announcement_signatures` for the funding transaction: - * - MUST send its own `announcement_signatures` message. - */ - send_private_cupdate(channel, true); + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: send_channel_announce_sigs(channel); - check_channel_gossip(channel); - return; - case CGOSSIP_ANNOUNCED: + /* fall thru */ + case CGOSSIP_PRIVATE: + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: + case CGOSSIP_WAITING_FOR_SCID: + send_private_cupdate(channel, true); check_channel_gossip(channel); return; } @@ -960,11 +1215,17 @@ const u8 *channel_gossip_update_for_error(const tal_t *ctx, struct channel_gossip *cg = channel->channel_gossip; switch (cg->state) { + case CGOSSIP_CHANNEL_DEAD: + case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: case CGOSSIP_PRIVATE: - case CGOSSIP_NOT_USABLE: - case CGOSSIP_NOT_DEEP_ENOUGH: - case CGOSSIP_NEED_PEER_SIGS: + case CGOSSIP_WAITING_FOR_USABLE: + case CGOSSIP_WAITING_FOR_SCID: + case CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS: + case CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH: return NULL; + case CGOSSIP_CHANNEL_ANNOUNCED_DYING: + case CGOSSIP_CHANNEL_ANNOUNCED_DEAD: + return cg->cupdate; case CGOSSIP_ANNOUNCED: /* At this point we actually disable disconnected peers. */ if (update_channel_update(channel, channel_should_enable(channel, false))) { @@ -1042,7 +1303,7 @@ void channel_gossip_set_remote_update(struct lightningd *ld, /* For public channels, it could come from anywhere. Private * channels must come from gossipd itself (the old store * migration!) or the correct peer. */ - if (cg->state == CGOSSIP_PRIVATE + if (is_private(channel) && source && !node_id_eq(source, &channel->peer->id)) { log_unusual(ld->log, "Bad gossip order: %s sent us a channel update for a " diff --git a/tests/test_gossip.py b/tests/test_gossip.py index cda6c4e98aae..43ef9f79362c 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -393,8 +393,9 @@ def test_connect_by_gossip(node_factory, bitcoind): def test_gossip_jsonrpc(node_factory): l1, l2 = node_factory.line_graph(2, fundchannel=True, wait_for_announce=False) - # Shouldn't send announce signatures until 6 deep. - assert not l1.daemon.is_in_log('peer_out WIRE_ANNOUNCEMENT_SIGNATURES') + # We will exchange announcement signatures immediately. + l1.daemon.wait_for_logs(['peer_out WIRE_ANNOUNCEMENT_SIGNATURES', + 'peer_in WIRE_ANNOUNCEMENT_SIGNATURES']) # Make sure we can route through the channel, will raise on failure l1.rpc.getroute(l2.info['id'], 100, 1) @@ -412,9 +413,6 @@ def test_gossip_jsonrpc(node_factory): # Now proceed to funding-depth and do a full gossip round l1.bitcoin.generate_block(5) - # Could happen in either order. - l1.daemon.wait_for_logs(['peer_out WIRE_ANNOUNCEMENT_SIGNATURES', - 'peer_in WIRE_ANNOUNCEMENT_SIGNATURES']) # Just wait for the update to kick off and then check the effect needle = "Received node_announcement for node" diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 6f0838beda72..22844c62b947 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -363,9 +363,6 @@ bool fromwire_tlv(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *record UNNEEDED, struct tlv_field **fields UNNEEDED, const u64 *extra_types UNNEEDED, size_t *err_off UNNEEDED, u64 *err_type UNNEEDED) { fprintf(stderr, "fromwire_tlv called!\n"); abort(); } -/* Generated stub for get_block_height */ -u32 get_block_height(const struct chain_topology *topo UNNEEDED) -{ fprintf(stderr, "get_block_height called!\n"); abort(); } /* Generated stub for get_network_blockheight */ u32 get_network_blockheight(const struct chain_topology *topo UNNEEDED) { fprintf(stderr, "get_network_blockheight called!\n"); abort(); } @@ -1300,6 +1297,12 @@ void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *scrip tal_free(script); } +/* Can actually be called by new_channel */ +u32 get_block_height(const struct chain_topology *topo UNNEEDED) +{ + return 0; +} + /** * mempat -- Set the memory to a pattern *