diff --git a/channeld/channeld.c b/channeld/channeld.c index 554919fa254e..add6ca68745b 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1928,6 +1928,7 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_REPLY_SHORT_CHANNEL_IDS_END: case WIRE_PING: case WIRE_PONG: + case WIRE_WARNING: case WIRE_ERROR: case WIRE_ONION_MESSAGE: abort(); diff --git a/common/peer_failed.c b/common/peer_failed.c index 7206f325dcb0..05c717b69b1a 100644 --- a/common/peer_failed.c +++ b/common/peer_failed.c @@ -49,7 +49,7 @@ void peer_failed(struct per_peer_state *pps, peer_fatal_continue(take(msg), pps); } -/* We're failing because peer sent us an error message */ +/* We're failing because peer sent us an error/warning message */ void peer_failed_received_errmsg(struct per_peer_state *pps, const char *desc, const struct channel_id *channel_id, @@ -62,7 +62,7 @@ void peer_failed_received_errmsg(struct per_peer_state *pps, channel_id = &all_channels; msg = towire_status_peer_error(NULL, channel_id, desc, soft_error, pps, NULL); - peer_billboard(true, "Received error from peer: %s", desc); + peer_billboard(true, "Received %s", desc); peer_fatal_continue(take(msg), pps); } diff --git a/common/read_peer_msg.c b/common/read_peer_msg.c index 44794dd20666..fb561f9067ca 100644 --- a/common/read_peer_msg.c +++ b/common/read_peer_msg.c @@ -68,11 +68,16 @@ u8 *peer_or_gossip_sync_read(const tal_t *ctx, bool is_peer_error(const tal_t *ctx, const u8 *msg, const struct channel_id *channel_id, - char **desc, bool *all_channels) + char **desc, bool *all_channels, + bool *warning) { struct channel_id err_chanid; - if (fromwire_peektype(msg) != WIRE_ERROR) + if (fromwire_peektype(msg) == WIRE_ERROR) + *warning = false; + else if (fromwire_peektype(msg) == WIRE_WARNING) + *warning = true; + else return false; *desc = sanitize_error(ctx, msg, &err_chanid); @@ -153,7 +158,7 @@ bool handle_peer_gossip_or_error(struct per_peer_state *pps, const u8 *msg TAKES) { char *err; - bool all_channels; + bool all_channels, warning; struct channel_id actual; #if DEVELOPER @@ -180,12 +185,13 @@ bool handle_peer_gossip_or_error(struct per_peer_state *pps, return true; } - if (is_peer_error(tmpctx, msg, channel_id, &err, &all_channels)) { + if (is_peer_error(tmpctx, msg, channel_id, &err, &all_channels, + &warning)) { if (err) peer_failed_received_errmsg(pps, err, all_channels ? NULL : channel_id, - soft_error); + warning || soft_error); /* Ignore unknown channel errors. */ goto handled; diff --git a/common/read_peer_msg.h b/common/read_peer_msg.h index ae6a575f3374..51919526a20c 100644 --- a/common/read_peer_msg.h +++ b/common/read_peer_msg.h @@ -34,13 +34,14 @@ u8 *peer_or_gossip_sync_read(const tal_t *ctx, * @channel_id: the channel id of the current channel. * @desc: set to non-NULL if this describes a channel we care about. * @all_channels: set to true if this applies to all channels. + * @warning: set to true if this is a warning, not an error. * * If @desc is NULL, ignore this message. Otherwise, that's usually passed * to peer_failed_received_errmsg(). */ bool is_peer_error(const tal_t *ctx, const u8 *msg, const struct channel_id *channel_id, - char **desc, bool *all_channels); + char **desc, bool *all_channels, bool *warning); /** * is_wrong_channel - if it's a message about a different channel, return true diff --git a/common/wire_error.c b/common/wire_error.c index 67f6b773f295..7bd1c5d4f7d8 100644 --- a/common/wire_error.c +++ b/common/wire_error.c @@ -53,11 +53,16 @@ char *sanitize_error(const tal_t *ctx, const u8 *errmsg, struct channel_id dummy; u8 *data; size_t i; + bool warning; if (!channel_id) channel_id = &dummy; - if (!fromwire_error(ctx, errmsg, channel_id, &data)) + if (fromwire_error(ctx, errmsg, channel_id, &data)) + warning = false; + else if (fromwire_warning(ctx, errmsg, channel_id, &data)) + warning = true; + else return tal_fmt(ctx, "Invalid ERROR message '%s'", tal_hex(ctx, errmsg)); @@ -79,9 +84,10 @@ char *sanitize_error(const tal_t *ctx, const u8 *errmsg, } } - return tal_fmt(ctx, "channel %s: %.*s", - channel_id_is_all(channel_id) - ? "ALL" - : type_to_string(ctx, struct channel_id, channel_id), + return tal_fmt(ctx, "%s%s%s: %.*s", + warning ? "warning" : "error", + channel_id_is_all(channel_id) ? "": " channel ", + channel_id_is_all(channel_id) ? "" + : type_to_string(tmpctx, struct channel_id, channel_id), (int)tal_count(data), (char *)data); } diff --git a/common/wire_error.h b/common/wire_error.h index bf9ffa09bc09..fdccff3f11cb 100644 --- a/common/wire_error.h +++ b/common/wire_error.h @@ -43,10 +43,10 @@ u8 *towire_errorfmtv(const tal_t *ctx, bool channel_id_is_all(const struct channel_id *channel_id); /** - * sanitize_error - extract and sanitize contents of WIRE_ERROR. + * sanitize_error - extract and sanitize contents of WIRE_ERROR/WIRE_WARNING. * * @ctx: context to allocate from - * @errmsg: the wire_error + * @errmsg: the wire_error or wire_warning * @channel: (out) channel it's referring to, or NULL if don't care. */ char *sanitize_error(const tal_t *ctx, const u8 *errmsg, diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index d6906ff41830..13c242dba902 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -736,6 +736,7 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, goto handled_relay; /* These are non-gossip messages (!is_msg_for_gossipd()) */ + case WIRE_WARNING: case WIRE_INIT: case WIRE_ERROR: case WIRE_OPEN_CHANNEL: diff --git a/openingd/dualopend.c b/openingd/dualopend.c index c5cc84971cf0..9bb7a655113b 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -972,7 +972,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) u8 *msg; bool from_gossipd; char *err; - bool all_channels; + bool all_channels, warning; struct channel_id actual; /* The event loop is responsible for freeing tmpctx, so our @@ -1011,7 +1011,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) /* A helper which decodes an error. */ if (is_peer_error(tmpctx, msg, &state->channel_id, - &err, &all_channels)) { + &err, &all_channels, &warning)) { /* BOLT #1: * * - if no existing channel is referred to by the @@ -1355,6 +1355,7 @@ static bool run_tx_interactive(struct state *state, break; case WIRE_INIT: case WIRE_ERROR: + case WIRE_WARNING: case WIRE_OPEN_CHANNEL: case WIRE_ACCEPT_CHANNEL: case WIRE_FUNDING_CREATED: diff --git a/openingd/openingd.c b/openingd/openingd.c index fc1066089382..9ad57a86d86c 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -199,7 +199,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, u8 *msg; bool from_gossipd; char *err; - bool all_channels; + bool all_channels, warning; struct channel_id actual; /* The event loop is responsible for freeing tmpctx, so our @@ -238,7 +238,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, /* A helper which decodes an error. */ if (is_peer_error(tmpctx, msg, &state->channel_id, - &err, &all_channels)) { + &err, &all_channels, &warning)) { /* BOLT #1: * * - if no existing channel is referred to by the @@ -262,7 +262,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, NULL, false); } negotiation_aborted(state, am_opener, - tal_fmt(tmpctx, "They sent error %s", + tal_fmt(tmpctx, "They sent %s", err)); /* Return NULL so caller knows to stop negotiating. */ return NULL; diff --git a/wire/extracted_peer_warning.patch b/wire/extracted_peer_warning.patch new file mode 100644 index 000000000000..6dc9e7c5bdac --- /dev/null +++ b/wire/extracted_peer_warning.patch @@ -0,0 +1,13 @@ +--- wire/peer_exp_wire.csv 2021-01-14 11:00:27.526336550 +1030 ++++ - 2021-01-21 15:31:37.071118999 +1030 +@@ -10,6 +10,10 @@ + msgdata,error,channel_id,channel_id, + msgdata,error,len,u16, + msgdata,error,data,byte,len ++msgtype,warning,1 ++msgdata,warning,channel_id,channel_id, ++msgdata,warning,len,u16, ++msgdata,warning,data,byte,len + msgtype,ping,18 + msgdata,ping,num_pong_bytes,u16, + msgdata,ping,byteslen,u16, diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 2581d3ead241..82bd3009b82c 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -4,6 +4,7 @@ static bool unknown_type(enum peer_wire t) { switch (t) { + case WIRE_WARNING: case WIRE_INIT: case WIRE_ERROR: case WIRE_OPEN_CHANNEL: @@ -64,6 +65,7 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_PONG: case WIRE_ONION_MESSAGE: return true; + case WIRE_WARNING: case WIRE_INIT: case WIRE_ERROR: case WIRE_OPEN_CHANNEL: diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 01061d9fc555..4ced58c8015b 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -10,6 +10,10 @@ msgtype,error,17 msgdata,error,channel_id,channel_id, msgdata,error,len,u16, msgdata,error,data,byte,len +msgtype,warning,1 +msgdata,warning,channel_id,channel_id, +msgdata,warning,len,u16, +msgdata,warning,data,byte,len msgtype,ping,18 msgdata,ping,num_pong_bytes,u16, msgdata,ping,byteslen,u16,