mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
channeld: keep local copy of latest channel_update for errors.
Now we don't ask gossipd, but lightningd keeps channeld up-to-date. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
5065bd6fc2
commit
e8554c862a
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Can't render this file because it has a wrong number of fields in line 13.
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -2,16 +2,6 @@
|
||||
#include <bitcoin/short_channel_id.h>
|
||||
#include <common/amount.h>
|
||||
|
||||
# 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,
|
||||
|
|
@ -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(); }
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <lightningd/bitcoind.h>
|
||||
#include <lightningd/chaintopology.h>
|
||||
#include <lightningd/channel.h>
|
||||
#include <lightningd/channel_control.h>
|
||||
#include <lightningd/gossip_control.h>
|
||||
#include <lightningd/hsm_control.h>
|
||||
#include <lightningd/jsonrpc.h>
|
||||
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user