channeld: send shutdown_complete even if reestablish_only.

This lets us transition (with a few supporting changes) to closingd,
which will happily let them mutual close with us.

We already handle the case where this mutual close is redundant (for
packet loss), so this is easy.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Protocol: We will now reestablish and negotiate mutual close on channels we've already closed (great if peer has lost their database).
This commit is contained in:
Rusty Russell 2021-06-15 14:37:15 +09:30
parent 44829d1361
commit ca0358f978
4 changed files with 20 additions and 13 deletions

View file

@ -918,6 +918,15 @@ static void maybe_send_shutdown(struct peer *peer)
billboard_update(peer); billboard_update(peer);
} }
static void send_shutdown_complete(struct peer *peer)
{
/* Now we can tell master shutdown is complete. */
wire_sync_write(MASTER_FD,
take(towire_channeld_shutdown_complete(NULL, peer->pps)));
per_peer_state_fdpass_send(MASTER_FD, peer->pps);
close(MASTER_FD);
}
/* This queues other traffic from the fd until we get reply. */ /* This queues other traffic from the fd until we get reply. */
static u8 *master_wait_sync_reply(const tal_t *ctx, static u8 *master_wait_sync_reply(const tal_t *ctx,
struct peer *peer, struct peer *peer,
@ -2929,10 +2938,17 @@ got_reestablish:
#endif /* EXPERIMENTAL_FEATURES */ #endif /* EXPERIMENTAL_FEATURES */
/* Now stop, we've been polite long enough. */ /* Now stop, we've been polite long enough. */
if (reestablish_only) if (reestablish_only) {
/* If we were successfully closing, we still go to closingd. */
if (shutdown_complete(peer)) {
send_shutdown_complete(peer);
daemon_shutdown();
exit(0);
}
peer_failed_err(peer->pps, peer_failed_err(peer->pps,
&peer->channel_id, &peer->channel_id,
"Channel is already closed"); "Channel is already closed");
}
/* Corner case: we didn't send shutdown before because update_add_htlc /* Corner case: we didn't send shutdown before because update_add_htlc
* pending, but now they're cleared by restart, and we're actually * pending, but now they're cleared by restart, and we're actually
@ -3594,15 +3610,6 @@ static void init_channel(struct peer *peer)
billboard_update(peer); billboard_update(peer);
} }
static void send_shutdown_complete(struct peer *peer)
{
/* Now we can tell master shutdown is complete. */
wire_sync_write(MASTER_FD,
take(towire_channeld_shutdown_complete(NULL, peer->pps)));
per_peer_state_fdpass_send(MASTER_FD, peer->pps);
close(MASTER_FD);
}
static void try_read_gossip_store(struct peer *peer) static void try_read_gossip_store(struct peer *peer)
{ {
u8 *msg = gossip_store_next(tmpctx, peer->pps); u8 *msg = gossip_store_next(tmpctx, peer->pps);

View file

@ -318,7 +318,8 @@ static void peer_start_closingd_after_shutdown(struct channel *channel,
peer_start_closingd(channel, pps); peer_start_closingd(channel, pps);
/* We might have reconnected, so already be here. */ /* We might have reconnected, so already be here. */
if (channel->state != CLOSINGD_SIGEXCHANGE) if (!channel_closed(channel)
&& channel->state != CLOSINGD_SIGEXCHANGE)
channel_set_state(channel, channel_set_state(channel,
CHANNELD_SHUTTING_DOWN, CHANNELD_SHUTTING_DOWN,
CLOSINGD_SIGEXCHANGE, CLOSINGD_SIGEXCHANGE,

View file

@ -145,7 +145,7 @@ static void peer_closing_complete(struct channel *channel, const u8 *msg)
channel_set_billboard(channel, false, NULL); channel_set_billboard(channel, false, NULL);
/* Retransmission only, ignore closing. */ /* Retransmission only, ignore closing. */
if (channel->state == CLOSINGD_COMPLETE) if (channel_closed(channel))
return; return;
/* Channel gets dropped to chain cooperatively. */ /* Channel gets dropped to chain cooperatively. */

View file

@ -2786,7 +2786,6 @@ def test_htlc_rexmit_while_closing(node_factory, executor):
fut2.result(TIMEOUT) fut2.result(TIMEOUT)
@pytest.mark.xfail(strict=True)
@pytest.mark.openchannel('v1') @pytest.mark.openchannel('v1')
@pytest.mark.developer("needs dev_disconnect") @pytest.mark.developer("needs dev_disconnect")
def test_you_forgot_closed_channel(node_factory, executor): def test_you_forgot_closed_channel(node_factory, executor):