diff --git a/lightningd/Makefile b/lightningd/Makefile index b320fef01..b40a7244f 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -6,6 +6,7 @@ LIGHTNINGD_SRC := \ lightningd/chaintopology.c \ lightningd/channel.c \ lightningd/channel_control.c \ + lightningd/channel_gossip.c \ lightningd/closing_control.c \ lightningd/coin_mvts.c \ lightningd/dual_open_control.c \ diff --git a/lightningd/channel.h b/lightningd/channel.h index c2893fc09..578a4f762 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -141,6 +141,9 @@ struct channel { /* Is there a single subdaemon responsible for us? */ struct subd *owner; + /* Telling the world (or just our peer) about us */ + struct channel_gossip *channel_gossip; + /* History */ struct logger *log; struct billboard billboard; diff --git a/lightningd/channel_gossip.c b/lightningd/channel_gossip.c new file mode 100644 index 000000000..6ba99ecd3 --- /dev/null +++ b/lightningd/channel_gossip.c @@ -0,0 +1,970 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum channel_gossip_state { + /* Not a public channel */ + 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, + /* We have received sigs, and announced. */ + CGOSSIP_ANNOUNCED, +}; + +struct remote_announce_sigs { + struct short_channel_id scid; + secp256k1_ecdsa_signature node_sig; + secp256k1_ecdsa_signature bitcoin_sig; +}; + +struct channel_gossip { + enum channel_gossip_state state; + + /* Cached update info */ + const u8 *cupdate; + + /* Remote channel_announcement sigs we've received (but not + * necessarily committed!) */ + struct remote_announce_sigs *remote_sigs; + + /* Timer to refresh public channels every 13 days */ + struct oneshot *refresh_timer; + + /* Details of latest channel_update sent by peer */ + const struct peer_update *peer_update; +}; + +/* FIXME: this is a hack! We should wait 1 minute after connectd has + * tried to connect to all peers. */ +static bool starting_up = true; + +/* We send non-forwardable channel updates if we can. */ +static bool can_send_channel_update(const struct channel *channel) +{ + /* Can't send if we can't talk about it. */ + if (!channel->scid && !channel->alias[REMOTE]) + return false; + if (channel_state_pre_open(channel->state)) + return false; + return true; +} + +/* 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) +{ + if (!channel->scid) + return false; + return is_scid_depth_announceable(channel->scid, block_height); +} + +static void check_channel_gossip(const struct channel *channel) +{ + struct channel_gossip *cg = channel->channel_gossip; + + /* Note: we can't assert is_scid_depth_announceable, for two reasons: + * 1. on restart 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: + assert(!(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_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)); + assert(!cg->refresh_timer); + return; + case CGOSSIP_NOT_DEEP_ENOUGH: + assert(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL); + assert(can_send_channel_update(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)); + assert(!cg->refresh_timer); + return; + case CGOSSIP_ANNOUNCED: + assert(can_send_channel_update(channel)); + assert(channel->scid); + assert(cg->remote_sigs); + return; + } + fatal("Bad channel_gossip_state %u", cg->state); +} + +/* Recursion */ +static void cupdate_timer_refresh(struct channel *channel); + +static void set_public_cupdate(struct channel *channel, + const u8 *cupdate TAKES) +{ + 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) + 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 void msg_to_peer(const struct channel *channel, const u8 *msg TAKES) +{ + struct peer *peer = channel->peer; + struct lightningd *ld = peer->ld; + + /* Shutting down, or peer not connected? */ + if (ld->connectd && peer->connected == PEER_CONNECTED) { + subd_send_msg(ld->connectd, + take(towire_connectd_peer_send_msg(NULL, + &peer->id, + peer->connectd_counter, + msg))); + } + + if (taken(msg)) + tal_free(msg); +} + +static enum channel_gossip_state init_public_state(struct channel *channel, + const struct remote_announce_sigs *remote_sigs) +{ + struct lightningd *ld = channel->peer->ld; + + if (!can_send_channel_update(channel)) + return CGOSSIP_NOT_USABLE; + + /* 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 (!remote_sigs) { + return CGOSSIP_NEED_PEER_SIGS; + } + + return CGOSSIP_ANNOUNCED; +} + +static u8 *sign_update(const tal_t *ctx, + struct lightningd *ld, + const u8 *unsigned_cupdate) +{ + const u8 *msg; + u8 *signed_update; + + /* Sign it please! */ + msg = hsm_sync_req(tmpctx, ld, + take(towire_hsmd_cupdate_sig_req(NULL, unsigned_cupdate))); + + if (!fromwire_hsmd_cupdate_sig_reply(ctx, msg, &signed_update)) + fatal("Reading cupdate_sig_reply: %s", tal_hex(tmpctx, msg)); + return signed_update; +} + +/* Try to send a channel_update direct to peer, unless redundant */ +static void send_private_cupdate(struct channel *channel, bool even_if_redundant) +{ + struct channel_gossip *cg = channel->channel_gossip; + const u8 *cupdate; + const struct short_channel_id *scid; + + /* BOLT #7: + * + * - MAY create a `channel_update` to communicate the channel + * parameters to the channel peer, even though the channel has not + * yet been announced (i.e. the `announce_channel` bit was not set). + * - MUST set the `short_channel_id` to either an `alias` it has + * received from the peer, or the real channel `short_channel_id`. + * - MUST set `dont_forward` to 1 in `message_flags` + */ + /* We prefer their alias, if possible: they might not have seen the block which + * mined the funding tx yet, so the scid would be meaningless to them. */ + if (channel->alias[REMOTE]) + scid = channel->alias[REMOTE]; + else + scid = channel->scid; + + /* Only useful channels: not if closing */ + if (!channel_state_can_add_htlc(channel->state)) + return; + + /* We always set "enabled" on unannounced channels, since if peer + * receives it, that's what it means */ + cupdate = unsigned_channel_update(tmpctx, channel, scid, + NULL, false, true); + + /* Suppress redundant ones (except on reconnect, in case it's + * lost) */ + if (cg->cupdate) { + if (!even_if_redundant + && channel_update_same(cg->cupdate, cupdate)) { + return; + } + tal_free(cg->cupdate); + } + + cg->cupdate = sign_update(cg, channel->peer->ld, cupdate); + msg_to_peer(channel, cg->cupdate); +} + +static void broadcast_public_cupdate_addgossip_reply(struct subd *gossip UNUSED, + const u8 *reply, + const int *fds UNUSED, + struct channel *channel) +{ + char *err; + + if (!fromwire_gossipd_addgossip_reply(reply, reply, &err)) + fatal("Reading broadcast_public_cupdate_addgossip_reply: %s", + tal_hex(tmpctx, reply)); + + if (strlen(err)) + log_broken(channel->log, "gossipd rejected our channel update: %s", err); +} + +/* Send gossipd a channel_update, if not redundant. */ +static void broadcast_public_cupdate(struct channel *channel, + bool ok_if_disconnected) +{ + struct lightningd *ld = channel->peer->ld; + struct channel_gossip *cg = channel->channel_gossip; + const u8 *cupdate; + u32 old_timestamp; + bool enable, have_old; + + /* If we have no previous channel_update, this fails */ + have_old = channel_update_details(cg->cupdate, + &old_timestamp, &enable); + + if (!channel_state_can_add_htlc(channel->state)) { + /* If it's (no longer) usable, it's a simply courtesy + * to disable */ + enable = false; + } else if (channel->owner) { + /* If it's live, it's enabled */ + enable = 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; + } else { + enable = ok_if_disconnected; + } + + 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; + + set_public_cupdate(channel, + take(sign_update(NULL, channel->peer->ld, cupdate))); + + subd_req(ld->gossip, ld->gossip, + take(towire_gossipd_addgossip(NULL, cg->cupdate)), + -1, 0, broadcast_public_cupdate_addgossip_reply, channel); +} + +static void cupdate_timer_refresh(struct channel *channel) +{ + struct channel_gossip *cg = channel->channel_gossip; + + /* Don't try to free this again if set_public_cupdate called later */ + cg->refresh_timer = NULL; + + log_debug(channel->log, "Sending keepalive channel_update for %s", + short_channel_id_to_str(tmpctx, channel->scid)); + + /* Free old cupdate to force a new one to be generated */ + cg->cupdate = tal_free(cg->cupdate); + broadcast_public_cupdate(channel, true); +} + +static void stash_remote_announce_sigs(struct channel *channel, + struct short_channel_id scid, + const secp256k1_ecdsa_signature *node_sig, + const secp256k1_ecdsa_signature *bitcoin_sig) +{ + struct channel_gossip *cg = channel->channel_gossip; + + tal_free(cg->remote_sigs); + cg->remote_sigs = tal(cg, struct remote_announce_sigs); + cg->remote_sigs->scid = scid; + cg->remote_sigs->node_sig = *node_sig; + cg->remote_sigs->bitcoin_sig = *bitcoin_sig; + log_debug(channel->log, + "channel_gossip: received announcement sigs for %s (we have %s)", + short_channel_id_to_str(tmpctx, &scid), + channel->scid ? short_channel_id_to_str(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; + + if (!short_channel_id_eq(&cg->remote_sigs->scid, channel->scid)) { + log_debug(channel->log, "We have remote sigs, but wrong scid!"); + return false; + } + + /* FIXME: check sigs are valid! */ + wallet_announcement_save(channel->peer->ld->wallet, + channel->dbid, + &cg->remote_sigs->node_sig, + &cg->remote_sigs->bitcoin_sig); + return true; +} + +static void send_channel_announce_sigs(struct channel *channel) +{ + /* First 2 + 256 byte are the signatures and msg type, skip them */ + const size_t offset = 258; + struct lightningd *ld = channel->peer->ld; + struct sha256_double hash; + secp256k1_ecdsa_signature local_node_sig, local_bitcoin_sig; + struct pubkey mykey; + const u8 *ca, *msg; + + /* If it's already closing, don't bother. */ + if (!channel_state_can_add_htlc(channel->state)) + return; + + ca = create_channel_announcement(tmpctx, channel, + NULL, NULL, NULL, NULL); + + msg = hsm_sync_req(tmpctx, ld, + take(towire_hsmd_sign_any_cannouncement_req(NULL, + ca, + &channel->peer->id, + channel->dbid))); + if (!fromwire_hsmd_sign_any_cannouncement_reply(msg, &local_node_sig, &local_bitcoin_sig)) + fatal("Reading hsmd_sign_any_cannouncement_reply: %s", tal_hex(tmpctx, msg)); + + /* Double-check that HSM gave valid signatures. */ + sha256_double(&hash, ca + offset, tal_count(ca) - offset); + if (!pubkey_from_node_id(&mykey, &ld->id)) + fatal("Could not convert own public key"); + + if (!check_signed_hash(&hash, &local_node_sig, &mykey)) { + channel_internal_error(channel, + "HSM returned an invalid node signature"); + return; + } + + if (!check_signed_hash(&hash, &local_bitcoin_sig, &channel->local_funding_pubkey)) { + channel_internal_error(channel, + "HSM returned an invalid bitcoin signature"); + return; + } + + msg = towire_announcement_signatures(NULL, + &channel->cid, channel->scid, + &local_node_sig, &local_bitcoin_sig); + msg_to_peer(channel, take(msg)); +} + +static void send_channel_announce_addgossip_reply(struct subd *gossip UNUSED, + const u8 *reply, + const int *fds UNUSED, + struct channel *channel) +{ + char *err; + + if (!fromwire_gossipd_addgossip_reply(reply, reply, &err)) + fatal("Reading send_channel_announce_addgossip_reply: %s", + tal_hex(tmpctx, reply)); + + if (strlen(err)) + log_broken(channel->log, "gossipd rejected our channel announcement: %s", err); +} + +static void send_channel_announcement(struct channel *channel) +{ + secp256k1_ecdsa_signature local_node_sig, local_bitcoin_sig; + struct lightningd *ld = channel->peer->ld; + const u8 *ca, *msg; + struct channel_gossip *cg = channel->channel_gossip; + + ca = create_channel_announcement(tmpctx, channel, + NULL, NULL, + &cg->remote_sigs->node_sig, + &cg->remote_sigs->bitcoin_sig); + + msg = hsm_sync_req(tmpctx, ld, + take(towire_hsmd_sign_any_cannouncement_req(NULL, ca, + &channel->peer->id, + channel->dbid))); + if (!fromwire_hsmd_sign_any_cannouncement_reply(msg, + &local_node_sig, + &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, + &local_node_sig, + &local_bitcoin_sig, + &cg->remote_sigs->node_sig, + &cg->remote_sigs->bitcoin_sig); + + subd_req(ld->gossip, ld->gossip, + take(towire_gossipd_addgossip(NULL, ca)), + -1, 0, send_channel_announce_addgossip_reply, channel); + /* We can also send our first public channel_update now */ + broadcast_public_cupdate(channel, true); +} + +static void set_gossip_state(struct channel *channel, + enum channel_gossip_state state) +{ + struct channel_gossip *cg = channel->channel_gossip; + + cg->state = state; + + switch (cg->state) { + case CGOSSIP_PRIVATE: + abort(); + case CGOSSIP_NOT_USABLE: + return; + case CGOSSIP_NOT_DEEP_ENOUGH: + /* But it exists, so try sending private channel_update */ + send_private_cupdate(channel, false); + return; + case CGOSSIP_NEED_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_ANNOUNCED: + /* Any previous update was private, so clear. */ + cg->cupdate = tal_free(cg->cupdate); + send_channel_announcement(channel); + return; + } + fatal("Bad channel_gossip_state %u", cg->state); +} + +/* Initialize channel->channel_gossip state */ +void channel_gossip_init(struct channel *channel, + const struct peer_update *remote_update) +{ + struct lightningd *ld = channel->peer->ld; + struct channel_gossip *cg; + bool public = (channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL); + + cg = channel->channel_gossip = tal(channel, struct channel_gossip); + cg->cupdate = NULL; + cg->refresh_timer = NULL; + cg->peer_update = tal_dup_or_null(channel, struct peer_update, remote_update); + cg->remote_sigs = NULL; + + /* If we have an scid, we might have announcement signatures + * saved in the db already. */ + if (channel->scid && public) { + cg->remote_sigs = tal(cg, struct remote_announce_sigs); + cg->remote_sigs->scid = *channel->scid; + if (!wallet_remote_ann_sigs_load(ld->wallet, + channel, + &cg->remote_sigs->node_sig, + &cg->remote_sigs->bitcoin_sig)) { + cg->remote_sigs = tal_free(cg->remote_sigs); + } + } + + if (public) + cg->state = init_public_state(channel, cg->remote_sigs); + else + cg->state = CGOSSIP_PRIVATE; + + check_channel_gossip(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 */ + broadcast_public_cupdate(channel, true); + check_channel_gossip(channel); + return; + } + fatal("Bad channel_gossip_state %u", channel->channel_gossip->state); +} + +void channel_gossip_got_announcement_sigs(struct channel *channel, + struct short_channel_id scid, + const secp256k1_ecdsa_signature *node_sig, + const secp256k1_ecdsa_signature *bitcoin_sig) +{ + /* Ignore unsaved channels */ + if (!channel->channel_gossip) { + log_broken(channel->log, "They sent an announcement_signatures message for a unsaved channel? Ignoring."); + return; + } + + switch (channel->channel_gossip->state) { + case CGOSSIP_PRIVATE: + log_unusual(channel->log, "They sent an announcement_signatures message for a private channel? Ignoring."); + u8 *warning = towire_warningfmt(NULL, + &channel->cid, + "You sent announcement_signatures for private channel"); + msg_to_peer(channel, 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); + return; + case CGOSSIP_ANNOUNCED: + /* BOLT #7: + * - upon reconnection (once the above timing requirements + * have been met): + * - MUST respond to the first `announcement_signatures` + * message with its own `announcement_signatures` message. + */ + send_channel_announce_sigs(channel); + check_channel_gossip(channel); + return; + } + fatal("Bad channel_gossip_state %u", channel->channel_gossip->state); +} + +/* Short channel id changed (splice, or reorg). */ +void channel_gossip_scid_changed(struct channel *channel) +{ + struct lightningd *ld = channel->peer->ld; + struct channel_gossip *cg = channel->channel_gossip; + + /* Ignore unsaved channels */ + if (!cg) + return; + + /* Clear any cached update, we'll need a new one! */ + cg->cupdate = tal_free(cg->cupdate); + + /* Any announcement signatures we received for old scid are no longer + * valid. */ + wallet_remote_ann_sigs_clear(ld->wallet, channel); + + 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: + /* Shouldn't happen. */ + return; + case CGOSSIP_NOT_DEEP_ENOUGH: + case CGOSSIP_NEED_PEER_SIGS: + case CGOSSIP_ANNOUNCED: + log_debug(channel->log, "channel_gossip: scid now %s", + short_channel_id_to_str(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; + } + fatal("Bad channel_gossip_state %u", cg->state); +} + +/* Block height changed */ +static void new_blockheight(struct lightningd *ld, + struct channel *channel, + u32 block_height) +{ + 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, block_height)) { + 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); +} + +void channel_gossip_notify_new_block(struct lightningd *ld, + u32 block_height) +{ + struct peer *peer; + struct channel *channel; + struct peer_node_id_map_iter it; + + for (peer = peer_node_id_map_first(ld->peers, &it); + peer; + peer = peer_node_id_map_next(ld->peers, &it)) { + list_for_each(&peer->channels, channel, list) { + /* Ignore unsaved channels */ + if (!channel->channel_gossip) + continue; + + new_blockheight(ld, channel, block_height); + check_channel_gossip(channel); + } + } +} + +/* Gossipd told us about a channel update on one of our channels (on loading) */ +void channel_gossip_update_from_gossipd(struct channel *channel, + const u8 *channel_update TAKES) +{ + if (!channel->channel_gossip) { + log_broken(channel->log, + "gossipd gave channel_update for unsaved channel? update=%s", + tal_hex(tmpctx, channel_update)); + return; + } + + /* If we didn't think it was announced already, it is now! */ + 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; + case CGOSSIP_NOT_USABLE: + case CGOSSIP_NOT_DEEP_ENOUGH: + case CGOSSIP_NEED_PEER_SIGS: + set_gossip_state(channel, CGOSSIP_ANNOUNCED); + break; + case CGOSSIP_ANNOUNCED: + break; + } + + set_public_cupdate(channel, channel_update); + check_channel_gossip(channel); +} + +static void set_not_starting_up(struct lightningd *ld) +{ + starting_up = false; + log_debug(ld->log, "channel_gossip: no longer in startup mode"); +} + +/* Gossipd init is done: if you expected a channel_update, be + * disappointed. */ +void channel_gossip_init_done(struct lightningd *ld) +{ + struct peer *peer; + struct channel *channel; + struct peer_node_id_map_iter it; + + for (peer = peer_node_id_map_first(ld->peers, &it); + peer; + peer = peer_node_id_map_next(ld->peers, &it)) { + list_for_each(&peer->channels, channel, list) { + /* Ignore unsaved channels */ + if (!channel->channel_gossip) + continue; + + check_channel_gossip(channel); + if (channel->channel_gossip->cupdate) + continue; + if (channel->channel_gossip->state != CGOSSIP_ANNOUNCED) + continue; + /* gossipd lost announcement: re-create */ + log_unusual(channel->log, + "gossipd lost track of announced channel: re-announcing!"); + check_channel_gossip(channel); + send_channel_announcement(channel); + } + } + + notleak(new_reltimer(ld->timers, ld, + time_from_sec(60), + set_not_starting_up, ld)); +} + +/* Peer has connected. */ +/* FIXME: We really want "peer has reestablished */ +void channel_gossip_peer_connected(struct peer *peer) +{ + struct channel *channel; + + list_for_each(&peer->channels, channel, list) { + /* Ignore unsaved channels */ + if (!channel->channel_gossip) + continue; + + switch (channel->channel_gossip->state) { + case CGOSSIP_NOT_USABLE: + continue; + case CGOSSIP_PRIVATE: + case CGOSSIP_NOT_DEEP_ENOUGH: + send_private_cupdate(channel, true); + check_channel_gossip(channel); + continue; + case CGOSSIP_NEED_PEER_SIGS: + /* BOLT #7: + * - upon reconnection (once the above timing + * requirements have been met): + * ... + * - if it has NOT received an + * `announcement_signatures` message: + * - SHOULD retransmit the + * `announcement_signatures` message. + */ + send_private_cupdate(channel, true); + send_channel_announce_sigs(channel); + check_channel_gossip(channel); + continue; + case CGOSSIP_ANNOUNCED: + check_channel_gossip(channel); + continue; + } + fatal("Bad channel_gossip_state %u", channel->channel_gossip->state); + } +} + +/* We *could* send channel_updates for private channels, or + * unannounced. We do not */ +const u8 *channel_gossip_update_for_error(const tal_t *ctx, + struct channel *channel) +{ + /* We cannot ask this about unsaved channels. */ + struct channel_gossip *cg = channel->channel_gossip; + + switch (cg->state) { + case CGOSSIP_PRIVATE: + case CGOSSIP_NOT_USABLE: + case CGOSSIP_NOT_DEEP_ENOUGH: + case CGOSSIP_NEED_PEER_SIGS: + return NULL; + case CGOSSIP_ANNOUNCED: + broadcast_public_cupdate(channel, false); + check_channel_gossip(channel); + return cg->cupdate; + } + fatal("Bad channel_gossip_state %u", cg->state); +} + +/* BOLT #7: + * - MUST set the `short_channel_id` to either an `alias` it has + * received from the peer, or the real channel `short_channel_id`. + */ +/* But we used to get this wrong! Sot this is the only place where we + * look up by *remote* id. It's not unique, but it is unique for a + * specific peer. */ +static struct channel *lookup_by_peer_remote_alias(struct lightningd *ld, + const struct node_id *source, + struct short_channel_id scid) +{ + const struct peer *p; + struct channel *chan; + + if (!source) + return NULL; + + p = peer_by_id(ld, source); + if (!p) + return NULL; + + list_for_each(&p->channels, chan, list) { + if (chan->alias[REMOTE] + && short_channel_id_eq(&scid, chan->alias[REMOTE])) { + return chan; + } + } + return NULL; +} + +/* A peer sent gossipd an update_channel message for one of our channels. + * Gossipd checked the signature. + */ +void channel_gossip_set_remote_update(struct lightningd *ld, + const struct peer_update *update TAKES, + const struct node_id *source) +{ + struct channel *channel; + struct channel_gossip *cg; + + channel = any_channel_by_scid(ld, &update->scid, true); + if (!channel) { + channel = lookup_by_peer_remote_alias(ld, source, update->scid); + if (channel) + log_debug(channel->log, + "Bad gossip order: peer sent update using their own alias!"); + } + if (!channel) { + log_unusual(ld->log, "Bad gossip order: could not find channel %s for peer's " + "channel update", + short_channel_id_to_str(tmpctx, &update->scid)); + return; + } + + cg = channel->channel_gossip; + + if (!cg) { + log_broken(ld->log, "Peer sent update_channel for unsaved channel"); + return; + } + + /* 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 + && source + && !node_id_eq(source, &channel->peer->id)) { + log_unusual(ld->log, "Bad gossip order: %s sent us a channel update for a " + "channel owned by %s (%s)", + type_to_string(tmpctx, struct node_id, source), + type_to_string(tmpctx, struct node_id, + &channel->peer->id), + type_to_string(tmpctx, struct short_channel_id, &update->scid)); + return; + } + + log_debug(ld->log, "updating channel %s with inbound settings", + type_to_string(tmpctx, struct short_channel_id, &update->scid)); + tal_free(cg->peer_update); + cg->peer_update = tal_dup(cg, struct peer_update, update); + wallet_channel_save(ld->wallet, channel); +} + +const struct peer_update *channel_gossip_get_remote_update(const struct channel *channel) +{ + struct channel_gossip *cg = channel->channel_gossip; + + if (!cg) + return NULL; + return cg->peer_update; +} diff --git a/lightningd/channel_gossip.h b/lightningd/channel_gossip.h new file mode 100644 index 000000000..9d49df911 --- /dev/null +++ b/lightningd/channel_gossip.h @@ -0,0 +1,55 @@ +#ifndef LIGHTNING_LIGHTNINGD_CHANNEL_GOSSIP_H +#define LIGHTNING_LIGHTNINGD_CHANNEL_GOSSIP_H +#include "config.h" +#include +#include + +struct channel; +struct lightningd; +struct peer; +struct peer_update; + +/* Initialize channel->channel_gossip state */ +void channel_gossip_init(struct channel *channel, + const struct peer_update *remote_update TAKES); + +/* Something about channel/blockchain changed: update if required */ +void channel_gossip_update(struct channel *channel); + +/* Short channel id changed (splice, or reorg). */ +void channel_gossip_scid_changed(struct channel *channel); + +/* Block height changed */ +void channel_gossip_notify_new_block(struct lightningd *ld, + u32 block_height); + +/* Got announcement_signatures from peer */ +void channel_gossip_got_announcement_sigs(struct channel *channel, + struct short_channel_id scid, + const secp256k1_ecdsa_signature *node_sig, + const secp256k1_ecdsa_signature *bitcoin_sig); + +/* Gossipd told us about a channel update on one of our channels (on loading) */ +void channel_gossip_update_from_gossipd(struct channel *channel, + const u8 *channel_update TAKES); + +/* Gossipd init is done: if you expected a channel_update, be + * disappointed. */ +void channel_gossip_init_done(struct lightningd *ld); + +/* Peer has connected. */ +void channel_gossip_peer_connected(struct peer *peer); + +/* Gossipd sent us this channel_update about the peer's side of the channle */ +void channel_gossip_set_remote_update(struct lightningd *ld, + const struct peer_update *update TAKES, + const struct node_id *source); + +/* Get channel_update to send in an error onion reply (can give NULL!) */ +const u8 *channel_gossip_update_for_error(const tal_t *ctx, + struct channel *channel); + +/* Get the peer's last-sent channel_update info, if any. */ +const struct peer_update *channel_gossip_get_remote_update(const struct channel *channel); + +#endif /* LIGHTNING_LIGHTNINGD_CHANNEL_GOSSIP_H */