Browse Source

lightningd: implement receiving warnings.

This takes from the draft spec at https://github.com/lightningnetwork/lightning-rfc/pull/834

Note that if this draft does not get included, the peer will simply
ignore the warning message (we always close the connection afterwards
anyway).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Protocol: we now report the new (draft) warning message.
master
Rusty Russell 4 years ago
parent
commit
a7c5a1f1d2
  1. 1
      channeld/channeld.c
  2. 4
      common/peer_failed.c
  3. 16
      common/read_peer_msg.c
  4. 3
      common/read_peer_msg.h
  5. 16
      common/wire_error.c
  6. 4
      common/wire_error.h
  7. 1
      gossipd/gossipd.c
  8. 5
      openingd/dualopend.c
  9. 6
      openingd/openingd.c
  10. 13
      wire/extracted_peer_warning.patch
  11. 2
      wire/peer_wire.c
  12. 4
      wire/peer_wire.csv

1
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();

4
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);
}

16
common/read_peer_msg.c

@ -69,11 +69,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);
@ -154,7 +159,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
@ -181,12 +186,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;

3
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

16
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);
}

4
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,

1
gossipd/gossipd.c

@ -737,6 +737,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:

5
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:

6
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;

13
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,

2
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:

4
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,

Can't render this file because it has a wrong number of fields in line 2.
Loading…
Cancel
Save