diff --git a/channeld/channeld.c b/channeld/channeld.c index a8d0aaaa0..0c2727915 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -191,6 +191,9 @@ struct peer { /* We allow a 'tx-sigs' message between reconnect + funding_locked */ bool tx_sigs_allowed; + + /* Most recent channel_update message. */ + u8 *channel_update; }; static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer); @@ -414,28 +417,6 @@ static void send_channel_update(struct peer *peer, int disable_flag) wire_sync_write(peer->pps->gossip_fd, take(msg)); } -/* Get the latest channel update for this channel from gossipd */ -static const u8 *get_local_channel_update(const tal_t *ctx, struct peer *peer) -{ - const u8 *msg; - - msg = towire_gossipd_get_update(NULL, &peer->short_channel_ids[LOCAL]); - wire_sync_write(peer->pps->gossip_fd, take(msg)); - - /* Wait for reply to come back; handle other gossipd msgs meanwhile */ - while ((msg = wire_sync_read(tmpctx, peer->pps->gossip_fd)) != NULL) { - u8 *update; - if (fromwire_gossipd_get_update_reply(ctx, msg, &update)) - return update; - - handle_gossip_msg(peer->pps, take(msg)); - } - - /* Gossipd hangs up on us to kill us when a new - * connection comes in. */ - peer_failed_connection_lost(); -} - /** * Add a channel locally and send a channel update to the peer * @@ -3312,6 +3293,15 @@ static void handle_funding_depth(struct peer *peer, const u8 *msg) billboard_update(peer); } +static const u8 *get_cupdate(const struct peer *peer) +{ + /* Technically we only need to tell it the first time (unless it's + * changed). But it's not that common. */ + wire_sync_write(MASTER_FD, + take(towire_channeld_used_channel_update(NULL))); + return peer->channel_update; +} + static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) { u8 *msg; @@ -3373,7 +3363,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) peer->htlc_id++; return; case CHANNEL_ERR_INVALID_EXPIRY: - failwiremsg = towire_incorrect_cltv_expiry(inmsg, cltv_expiry, get_local_channel_update(tmpctx, peer)); + failwiremsg = towire_incorrect_cltv_expiry(inmsg, cltv_expiry, get_cupdate(peer)); failstr = tal_fmt(inmsg, "Invalid cltv_expiry %u", cltv_expiry); goto failed; case CHANNEL_ERR_DUPLICATE: @@ -3387,18 +3377,18 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) goto failed; /* FIXME: Fuzz the boundaries a bit to avoid probing? */ case CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED: - failwiremsg = towire_temporary_channel_failure(inmsg, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); failstr = tal_fmt(inmsg, "Capacity exceeded - HTLC fee: %s", fmt_amount_sat(inmsg, htlc_fee)); goto failed; case CHANNEL_ERR_HTLC_BELOW_MINIMUM: - failwiremsg = towire_amount_below_minimum(inmsg, amount, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_amount_below_minimum(inmsg, amount, get_cupdate(peer)); failstr = tal_fmt(inmsg, "HTLC too small (%s minimum)", type_to_string(tmpctx, struct amount_msat, &peer->channel->config[REMOTE].htlc_minimum)); goto failed; case CHANNEL_ERR_TOO_MANY_HTLCS: - failwiremsg = towire_temporary_channel_failure(inmsg, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); failstr = "Too many HTLCs"; goto failed; case CHANNEL_ERR_DUST_FAILURE: @@ -3408,7 +3398,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) * - SHOULD NOT send this HTLC * - SHOULD fail this HTLC if it's forwarded */ - failwiremsg = towire_temporary_channel_failure(inmsg, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); failstr = "HTLC too dusty, allowed dust limit reached"; goto failed; } @@ -3591,6 +3581,14 @@ static void handle_shutdown_cmd(struct peer *peer, const u8 *inmsg) start_commit_timer(peer); } +/* Lightningd tells us when channel_update has changed. */ +static void handle_channel_update(struct peer *peer, const u8 *msg) +{ + peer->channel_update = tal_free(peer->channel_update); + if (!fromwire_channeld_channel_update(peer, msg, &peer->channel_update)) + master_badmsg(WIRE_CHANNELD_CHANNEL_UPDATE, msg); +} + static void handle_send_error(struct peer *peer, const u8 *msg) { char *reason; @@ -3757,6 +3755,9 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_PING: handle_send_ping(peer, msg); return; + case WIRE_CHANNELD_CHANNEL_UPDATE: + handle_channel_update(peer, msg); + return; #if DEVELOPER case WIRE_CHANNELD_DEV_REENABLE_COMMIT: handle_dev_reenable_commit(peer); @@ -3793,6 +3794,7 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_DEV_QUIESCE_REPLY: case WIRE_CHANNELD_UPGRADED: case WIRE_CHANNELD_PING_REPLY: + case WIRE_CHANNELD_USED_CHANNEL_UPDATE: break; } @@ -3898,7 +3900,8 @@ static void init_channel(struct peer *peer) &dev_fail_process_onionpacket, &dev_disable_commit, &pbases, - &reestablish_only)) { + &reestablish_only, + &peer->channel_update)) { master_badmsg(WIRE_CHANNELD_INIT, msg); } diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index f095b3cb5..00d9784b7 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -77,6 +77,8 @@ msgdata,channeld_init,num_penalty_bases,u32, msgdata,channeld_init,pbases,penalty_base,num_penalty_bases msgdata,channeld_init,reestablish_only_len,u16, msgdata,channeld_init,reestablish_only,u8,reestablish_only_len +msgdata,channeld_init,channel_update_len,u16, +msgdata,channeld_init,channel_update,u8,channel_update_len # master->channeld funding hit new depth(funding locked if >= lock depth) msgtype,channeld_funding_depth,1002 @@ -224,6 +226,14 @@ msgdata,channeld_send_error,reason,wirestring, # Tell master channeld has sent the error message. msgtype,channeld_send_error_reply,1108 +# Tell channeld about the latest channel_update +msgtype,channeld_channel_update,1001 +msgdata,channeld_channel_update,len,u16, +msgdata,channeld_channel_update,msg,u8,len + +# Tell lightningd we used the latest channel_update for an error. +msgtype,channeld_used_channel_update,1102 + # Ask channeld to quiesce. msgtype,channeld_dev_quiesce,1009 msgtype,channeld_dev_quiesce_reply,1109 diff --git a/gossipd/gossip_generation.c b/gossipd/gossip_generation.c index 2653f479a..adef74e5e 100644 --- a/gossipd/gossip_generation.c +++ b/gossipd/gossip_generation.c @@ -598,7 +598,7 @@ static void defer_update(struct daemon *daemon, } /* If there is a pending update for this local channel, apply immediately. */ -bool local_channel_update_latest(struct daemon *daemon, struct chan *chan) +static bool local_channel_update_latest(struct daemon *daemon, struct chan *chan) { struct deferred_update *du; diff --git a/gossipd/gossip_generation.h b/gossipd/gossip_generation.h index adc3f81db..3d8f257ab 100644 --- a/gossipd/gossip_generation.h +++ b/gossipd/gossip_generation.h @@ -35,9 +35,6 @@ bool nannounce_different(struct gossip_store *gs, /* Should we announce our own node? Called at strategic places. */ void maybe_send_own_node_announce(struct daemon *daemon, bool startup); -/* Flush any pending changes to this channel. */ -bool local_channel_update_latest(struct daemon *daemon, struct chan *chan); - /* Disable this local channel (lazily) */ void local_disable_chan(struct daemon *daemon, const struct chan *chan, int direction); diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 6e1209612..77c484e80 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -277,65 +277,6 @@ static u8 *handle_channel_update_msg(struct peer *peer, const u8 *msg) return NULL; } -/*~ This is when channeld asks us for a channel_update for a local channel. - * It does that to fill in the error field when lightningd fails an HTLC and - * sets the UPDATE bit in the error type. lightningd is too important to - * fetch this itself, so channeld does it (channeld has to talk to us for - * other things anyway, so why not?). */ -static bool handle_get_local_channel_update(struct peer *peer, const u8 *msg) -{ - struct short_channel_id scid; - struct chan *chan; - const u8 *update; - struct routing_state *rstate = peer->daemon->rstate; - int direction; - - if (!fromwire_gossipd_get_update(msg, &scid)) { - status_broken("peer %s sent bad gossip_get_update %s", - type_to_string(tmpctx, struct node_id, &peer->id), - tal_hex(tmpctx, msg)); - return false; - } - - /* It's possible that the channel has just closed (though v. unlikely) */ - chan = get_channel(rstate, &scid); - if (!chan) { - status_unusual("peer %s scid %s: unknown channel", - type_to_string(tmpctx, struct node_id, &peer->id), - type_to_string(tmpctx, struct short_channel_id, - &scid)); - update = NULL; - goto out; - } - - /* Since we're going to send it out, make sure it's up-to-date. */ - local_channel_update_latest(peer->daemon, chan); - - if (!local_direction(rstate, chan, &direction)) { - status_peer_broken(&peer->id, "Chan %s is not local?", - type_to_string(tmpctx, struct short_channel_id, - &scid)); - update = NULL; - goto out; - } - - /* It's possible this is zero, if we've never sent a channel_update - * for that channel. */ - if (!is_halfchan_defined(&chan->half[direction])) - update = NULL; - else - update = gossip_store_get(tmpctx, rstate->gs, - chan->half[direction].bcast.index); -out: - status_peer_debug(&peer->id, "schanid %s: %s update", - type_to_string(tmpctx, struct short_channel_id, &scid), - update ? "got" : "no"); - - msg = towire_gossipd_get_update_reply(NULL, update); - daemon_conn_send(peer->dc, take(msg)); - return true; -} - static u8 *handle_node_announce(struct peer *peer, const u8 *msg) { bool was_unknown = false; @@ -781,19 +722,12 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, /* Must be a gossipd_peerd_wire_type asking us to do something. */ switch ((enum gossipd_peerd_wire)fromwire_peektype(msg)) { - case WIRE_GOSSIPD_GET_UPDATE: - ok = handle_get_local_channel_update(peer, msg); - goto handled_cmd; case WIRE_GOSSIPD_LOCAL_CHANNEL_UPDATE: ok = handle_local_channel_update(peer->daemon, &peer->id, msg); goto handled_cmd; case WIRE_GOSSIPD_LOCAL_CHANNEL_ANNOUNCEMENT: ok = handle_local_channel_announcement(peer->daemon, peer, msg); goto handled_cmd; - - /* These are the ones we send, not them */ - case WIRE_GOSSIPD_GET_UPDATE_REPLY: - break; } if (fromwire_peektype(msg) == WIRE_GOSSIP_STORE_PRIVATE_CHANNEL) { diff --git a/gossipd/gossipd_peerd_wire.csv b/gossipd/gossipd_peerd_wire.csv index 10c48adea..9b86cbf27 100644 --- a/gossipd/gossipd_peerd_wire.csv +++ b/gossipd/gossipd_peerd_wire.csv @@ -2,16 +2,6 @@ #include #include -# Channel daemon can ask for updates for a specific channel, for sending -# errors. -msgtype,gossipd_get_update,3501 -msgdata,gossipd_get_update,short_channel_id,short_channel_id, - -# If channel isn't known, update will be empty. -msgtype,gossipd_get_update_reply,3601 -msgdata,gossipd_get_update_reply,len,u16, -msgdata,gossipd_get_update_reply,update,u8,len - # Send this channel_update. msgtype,gossipd_local_channel_update,3504 msgdata,gossipd_local_channel_update,short_channel_id,short_channel_id, diff --git a/gossipd/test/run-onion_message.c b/gossipd/test/run-onion_message.c index 5ccc425f6..5babc51c9 100644 --- a/gossipd/test/run-onion_message.c +++ b/gossipd/test/run-onion_message.c @@ -88,9 +88,6 @@ bool fromwire_gossipd_get_addrs(const void *p UNNEEDED, struct node_id *id UNNEE /* Generated stub for fromwire_gossipd_get_txout_reply */ bool fromwire_gossipd_get_txout_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct amount_sat *satoshis UNNEEDED, u8 **outscript UNNEEDED) { fprintf(stderr, "fromwire_gossipd_get_txout_reply called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_get_update */ -bool fromwire_gossipd_get_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_get_update called!\n"); abort(); } /* Generated stub for fromwire_gossipd_init */ bool fromwire_gossipd_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, const struct chainparams **chainparams UNNEEDED, struct feature_set **our_features UNNEEDED, struct node_id *id UNNEEDED, u8 rgb[3] UNNEEDED, u8 alias[32] UNNEEDED, struct wireaddr **announcable UNNEEDED, u32 **dev_gossip_time UNNEEDED, bool *dev_fast_gossip UNNEEDED, bool *dev_fast_gossip_prune UNNEEDED) { fprintf(stderr, "fromwire_gossipd_init called!\n"); abort(); } @@ -199,9 +196,6 @@ void json_object_end(struct json_stream *js UNNEEDED) /* Generated stub for json_object_start */ void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED) { fprintf(stderr, "json_object_start called!\n"); abort(); } -/* Generated stub for local_channel_update_latest */ -bool local_channel_update_latest(struct daemon *daemon UNNEEDED, struct chan *chan UNNEEDED) -{ fprintf(stderr, "local_channel_update_latest called!\n"); abort(); } /* Generated stub for local_disable_chan */ void local_disable_chan(struct daemon *daemon UNNEEDED, const struct chan *chan UNNEEDED, int direction UNNEEDED) { fprintf(stderr, "local_disable_chan called!\n"); abort(); } @@ -323,9 +317,6 @@ u8 *towire_gossipd_get_addrs_reply(const tal_t *ctx UNNEEDED, const struct wirea /* Generated stub for towire_gossipd_get_txout */ u8 *towire_gossipd_get_txout(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED) { fprintf(stderr, "towire_gossipd_get_txout called!\n"); abort(); } -/* Generated stub for towire_gossipd_get_update_reply */ -u8 *towire_gossipd_get_update_reply(const tal_t *ctx UNNEEDED, const u8 *update UNNEEDED) -{ fprintf(stderr, "towire_gossipd_get_update_reply called!\n"); abort(); } /* Generated stub for towire_gossipd_got_onionmsg_to_us */ u8 *towire_gossipd_got_onionmsg_to_us(const tal_t *ctx UNNEEDED, bool obs2 UNNEEDED, const struct pubkey *node_alias UNNEEDED, const struct secret *self_id UNNEEDED, const struct pubkey *reply_blinding UNNEEDED, const struct pubkey *reply_first_node UNNEEDED, const struct onionmsg_path **reply_path UNNEEDED, const u8 *rawmsg UNNEEDED) { fprintf(stderr, "towire_gossipd_got_onionmsg_to_us called!\n"); abort(); } diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index be3748e07..d8333673f 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -504,6 +504,10 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_PING_REPLY: ping_reply(sd, msg); break; + case WIRE_CHANNELD_USED_CHANNEL_UPDATE: + /* This tells gossipd we used it. */ + get_channel_update(sd->channel); + break; #if EXPERIMENTAL_FEATURES case WIRE_CHANNELD_UPGRADED: handle_channel_upgrade(sd->channel, msg); @@ -525,6 +529,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_FEERATES: case WIRE_CHANNELD_BLOCKHEIGHT: case WIRE_CHANNELD_SPECIFIC_FEERATES: + case WIRE_CHANNELD_CHANNEL_UPDATE: case WIRE_CHANNELD_DEV_MEMLEAK: case WIRE_CHANNELD_DEV_QUIESCE: /* Replies go to requests. */ @@ -717,7 +722,8 @@ void peer_start_channeld(struct channel *channel, : (u32 *)&ld->dev_disable_commit, NULL), pbases, - reestablish_only); + reestablish_only, + channel->channel_update); /* We don't expect a response: we are triggered by funding_depth_cb. */ subd_send_msg(channel->owner, take(initmsg)); @@ -1008,6 +1014,20 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd, return command_still_pending(cmd); } +void channel_replace_update(struct channel *channel, u8 *update TAKES) +{ + tal_free(channel->channel_update); + channel->channel_update = tal_dup_talarr(channel, u8, update); + + /* Keep channeld up-to-date */ + if (!channel->owner || !streq(channel->owner->name, "channeld")) + return; + + subd_send_msg(channel->owner, + take(towire_channeld_channel_update(NULL, + channel->channel_update))); +} + #if DEVELOPER static struct command_result *json_dev_feerate(struct command *cmd, const char *buffer, diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index 2f80661b3..db8fa838b 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -39,4 +39,8 @@ void channel_record_open(struct channel *channel); /* A channel has unrecoverably fallen behind */ void channel_fallen_behind(struct channel *channel, const u8 *msg); + +/* Fresh channel_update for this channel. */ +void channel_replace_update(struct channel *channel, u8 *update TAKES); + #endif /* LIGHTNING_LIGHTNINGD_CHANNEL_CONTROL_H */ diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 5859fd675..33038d3e3 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -131,8 +132,7 @@ static void handle_local_channel_update(struct lightningd *ld, const u8 *msg) return; } - tal_free(channel->channel_update); - channel->channel_update = tal_steal(channel, update); + channel_replace_update(channel, take(update)); } const u8 *get_channel_update(struct channel *channel)