From dd79813a75a5459eaa22ae8b074fec612972648b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 26 Jul 2019 11:41:19 +0930 Subject: [PATCH] common: add peer_error flag to treat this error as "soft". The spec says to close the channel if they send us an error, but we need to be more lenient to preserve channels with other implementations. Signed-off-by: Rusty Russell --- common/peer_failed.c | 4 ++-- common/peer_status_wire.csv | 2 ++ lightningd/invoice.c | 1 - lightningd/onchain_control.c | 1 + lightningd/opening_control.c | 1 + lightningd/peer_control.c | 10 ++++++++++ lightningd/peer_control.h | 1 + lightningd/subd.c | 9 ++++++--- lightningd/subd.h | 4 +++- lightningd/test/run-find_my_abspath.c | 2 +- 10 files changed, 27 insertions(+), 8 deletions(-) diff --git a/common/peer_failed.c b/common/peer_failed.c index 7eb8a51f0..cc4051dc5 100644 --- a/common/peer_failed.c +++ b/common/peer_failed.c @@ -42,7 +42,7 @@ void peer_failed(struct per_peer_state *pps, /* Tell master the error so it can re-xmit. */ msg = towire_status_peer_error(NULL, channel_id, - desc, pps, + desc, false, pps, err); peer_billboard(true, desc); tal_free(desc); @@ -59,7 +59,7 @@ void peer_failed_received_errmsg(struct per_peer_state *pps, if (!channel_id) channel_id = &all_channels; - msg = towire_status_peer_error(NULL, channel_id, desc, pps, NULL); + msg = towire_status_peer_error(NULL, channel_id, desc, false, pps, NULL); peer_billboard(true, "Received error from peer: %s", desc); peer_fatal_continue(take(msg), pps); } diff --git a/common/peer_status_wire.csv b/common/peer_status_wire.csv index 19af5ef9d..57e918725 100644 --- a/common/peer_status_wire.csv +++ b/common/peer_status_wire.csv @@ -5,6 +5,8 @@ msgtype,status_peer_error,0xFFF4 # This is implied if error_for_them, but master tries not to parse packets. msgdata,status_peer_error,channel,channel_id, msgdata,status_peer_error,desc,wirestring, +# Take a deep breath, then try reconnecting to the precious little snowflake. +msgdata,status_peer_error,soft_error,bool, msgdata,status_peer_error,pps,per_peer_state, msgdata,status_peer_error,len,u16, msgdata,status_peer_error,error_for_them,u8,len diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 66ccb7e7f..ae9efe861 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -61,7 +61,6 @@ static void json_add_invoice(struct json_stream *response, "amount_received_msat"); json_add_u64(response, "paid_at", inv->paid_timestamp); } - if (inv->description) json_add_string(response, "description", inv->description); diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 08d7cd28c..0c9765ce9 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -416,6 +416,7 @@ static void onchain_error(struct channel *channel, struct per_peer_state *pps UNUSED, const struct channel_id *channel_id UNUSED, const char *desc, + bool soft_error UNUSED, const u8 *err_for_them UNUSED) { /* FIXME: re-launch? */ diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 9253e7266..8432d30a1 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -712,6 +712,7 @@ static void opening_channel_errmsg(struct uncommitted_channel *uc, struct per_peer_state *pps, const struct channel_id *channel_id UNUSED, const char *desc, + bool soft_error UNUSED, const u8 *err_for_them UNUSED) { /* Close fds, if any. */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 98430f7f9..d301aed0b 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -390,6 +390,7 @@ void channel_errmsg(struct channel *channel, struct per_peer_state *pps, const struct channel_id *channel_id UNUSED, const char *desc, + bool soft_error, const u8 *err_for_them) { notify_disconnect(channel->peer->ld, &channel->peer->id); @@ -407,6 +408,15 @@ void channel_errmsg(struct channel *channel, err_for_them, tal_count(err_for_them), 0); + /* Other implementations chose to ignore errors early on. Not + * surprisingly, they now spew out spurious errors frequently, + * and we would close the channel on them. */ + if (soft_error) { + channel_fail_reconnect_later(channel, "%s: (ignoring) %s", + channel->owner->name, desc); + return; + } + /* BOLT #1: * * A sending node: diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 8ad197f17..6c52aacf1 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -78,6 +78,7 @@ void channel_errmsg(struct channel *channel, struct per_peer_state *pps, const struct channel_id *channel_id, const char *desc, + bool soft_error, const u8 *err_for_them); u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx); diff --git a/lightningd/subd.c b/lightningd/subd.c index f961b0cfc..339c47b16 100644 --- a/lightningd/subd.c +++ b/lightningd/subd.c @@ -370,9 +370,10 @@ static bool handle_peer_error(struct subd *sd, const u8 *msg, int fds[3]) char *desc; struct per_peer_state *pps; u8 *err_for_them; + bool soft_error; if (!fromwire_status_peer_error(msg, msg, - &channel_id, &desc, + &channel_id, &desc, &soft_error, &pps, &err_for_them)) return false; @@ -380,7 +381,7 @@ static bool handle_peer_error(struct subd *sd, const u8 *msg, int fds[3]) /* Don't free sd; we may be about to free channel. */ sd->channel = NULL; - sd->errcb(channel, pps, &channel_id, desc, err_for_them); + sd->errcb(channel, pps, &channel_id, desc, soft_error, err_for_them); return true; } @@ -561,7 +562,7 @@ static void destroy_subd(struct subd *sd) sd->errcb(channel, NULL, NULL, tal_fmt(sd, "Owning subdaemon %s died (%i)", sd->name, status), - NULL); + false, NULL); if (!outer_transaction) db_commit_transaction(db); } @@ -611,6 +612,7 @@ static struct subd *new_subd(struct lightningd *ld, struct per_peer_state *pps, const struct channel_id *channel_id, const char *desc, + bool soft_error, const u8 *err_for_them), void (*billboardcb)(void *channel, bool perm, @@ -701,6 +703,7 @@ struct subd *new_channel_subd_(struct lightningd *ld, struct per_peer_state *pps, const struct channel_id *channel_id, const char *desc, + bool soft_error, const u8 *err_for_them), void (*billboardcb)(void *channel, bool perm, const char *happenings), diff --git a/lightningd/subd.h b/lightningd/subd.h index 2d21bc43e..62ec672aa 100644 --- a/lightningd/subd.h +++ b/lightningd/subd.h @@ -46,6 +46,7 @@ struct subd { struct per_peer_state *pps, const struct channel_id *channel_id, const char *desc, + bool soft_error, const u8 *err_for_them); /* Callback to display information for listpeers RPC */ @@ -120,6 +121,7 @@ struct subd *new_channel_subd_(struct lightningd *ld, struct per_peer_state *pps, const struct channel_id *channel_id, const char *desc, + bool soft_error, const u8 *err_for_them), void (*billboardcb)(void *channel, bool perm, const char *happenings), @@ -133,7 +135,7 @@ struct subd *new_channel_subd_(struct lightningd *ld, (channel), \ struct per_peer_state *, \ const struct channel_id *, \ - const char *, const u8 *), \ + const char *, bool, const u8 *), \ typesafe_cb_postargs(void, void *, (billboardcb), \ (channel), bool, \ const char *), \ diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 2a3b219a1..0b0b09161 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -73,7 +73,7 @@ bool fromwire_status_fail(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, enu bool fromwire_status_peer_billboard(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *perm UNNEEDED, wirestring **happenings UNNEEDED) { fprintf(stderr, "fromwire_status_peer_billboard called!\n"); abort(); } /* Generated stub for fromwire_status_peer_error */ -bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct channel_id *channel UNNEEDED, wirestring **desc UNNEEDED, struct per_peer_state **pps UNNEEDED, u8 **error_for_them UNNEEDED) +bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct channel_id *channel UNNEEDED, wirestring **desc UNNEEDED, bool *soft_error UNNEEDED, struct per_peer_state **pps UNNEEDED, u8 **error_for_them UNNEEDED) { fprintf(stderr, "fromwire_status_peer_error called!\n"); abort(); } /* Generated stub for get_log_book */ struct log_book *get_log_book(const struct log *log UNNEEDED)