On master f80895bac, channeld sent a warning through peer_failed_warn_nodisconnect and began exiting. connectd then decrypted the peer's channel-scoped WIRE_ERROR and queued it to that subdaemon after lightningd had begun killing it. channeld never received the error, so the channel remained open.
BOLT #1 requires a receiving node, upon receiving a channel-scoped error, to:
MUST fail the channel referred to by channel_id, if that channel is with the sending node.
BOLT #1 requirements
Forwarding WIRE_ERROR directly from connectd to lightningd when a matching subdaemon exists fixes the race. End-to-end regtest validation confirmed that lightningd failed the channel, and broadcasted the commitment:
diff --git a/connectd/multiplex.c b/connectd/multiplex.c
index 1051645f..696e9e1b 100644
--- a/connectd/multiplex.c
+++ b/connectd/multiplex.c
@@ -1493,6 +1493,15 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn,
/* If we don't find a subdaemon for this, create a new one. */
subd = find_subd(peer, &channel_id);
+ if (subd && type == WIRE_ERROR) {
+ daemon_conn_send(peer->daemon->master,
+ take(towire_connectd_peer_spoke(NULL, &peer->id,
+ peer->counter,
+ type,
+ &channel_id,
+ is_peer_error(tmpctx, decrypted))));
+ return next_read(peer_conn, peer);
+ }
if (!subd) {
enum peer_wire t = fromwire_peektype(decrypted);
On master
f80895bac,channeldsent a warning throughpeer_failed_warn_nodisconnectand began exiting.connectdthen decrypted the peer's channel-scopedWIRE_ERRORand queued it to that subdaemon afterlightningdhad begun killing it.channeldnever received the error, so the channel remained open.BOLT #1 requires a receiving node, upon receiving a channel-scoped
error, to:BOLT #1 requirements
Forwarding
WIRE_ERRORdirectly fromconnectdtolightningdwhen a matching subdaemon exists fixes the race. End-to-end regtest validation confirmed thatlightningdfailed the channel, and broadcasted the commitment: