Skip to content

Commit 5e4c1b7

Browse files
rustyrussellendothermicdev
authored andcommitted
lightningd: redo closing negotiation even if we consider channel closed.
This corner case started triggering on my machine with latest Bitcoind. This test sabotages the closing negotiation, and as a result l1 doesn't see l2's CLOSING_SIGNED. l2 is happy, however, and it is in CLOSINGD_COMPLETE. When l1 reconnects, it gets an error, and this causes it to drop the unilateral tx to chain. This unilateral tx from l1 replaces or races the mutual close tx from l2, causing a unilateral close, which breaks our test. Though this is a corner case, it's much friendlier to allow the closing negotiation again until we actually see the close onchain. This fixes the tests here, too. ``` def test_closing_negotiation_reconnect(node_factory, bitcoind): disconnects = ['-WIRE_CLOSING_SIGNED', '+WIRE_CLOSING_SIGNED'] l1, l2 = node_factory.line_graph(2, opts=[{'disconnect': disconnects, 'may_reconnect': True}, {'may_reconnect': True}]) l1.pay(l2, 200000000) assert bitcoind.rpc.getmempoolinfo()['size'] == 0 l1.rpc.close(l2.info['id']) l1.daemon.wait_for_log(r'State changed from CHANNELD_NORMAL to CHANNELD_SHUTTING_DOWN') l2.daemon.wait_for_log(r'State changed from CHANNELD_NORMAL to CHANNELD_SHUTTING_DOWN') # Now verify that the closing tx is in the mempool. bitcoind.generate_block(6, wait_for_mempool=1) sync_blockheight(bitcoind, [l1, l2]) for n in [l1, l2]: # Ensure we actually got a mutual close. > n.daemon.wait_for_log(r'Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by MUTUAL_CLOSE') tests/test_closing.py:275: ``` Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Fixed: Protocol: We now renegotiate an interrupted close, even if we don't need it, instead of sending an error.
1 parent a4aa777 commit 5e4c1b7

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

lightningd/peer_control.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1869,8 +1869,26 @@ void peer_spoke(struct lightningd *ld, const u8 *msg)
18691869
if (channel) {
18701870
/* In this case, we'll send an error below, but send reestablish reply first
18711871
* in case they lost their state and need it */
1872-
if (msgtype == WIRE_CHANNEL_REESTABLISH && channel_state_closed(channel->state))
1872+
if (msgtype == WIRE_CHANNEL_REESTABLISH && channel_state_closed(channel->state)) {
1873+
/* Maybe we know it's closed, but they don't? Happy to negotiate again. */
1874+
if (channel->state == CLOSINGD_COMPLETE) {
1875+
pfd = sockpair(tmpctx, channel, &other_fd, &error);
1876+
if (!pfd)
1877+
goto send_error;
1878+
1879+
/* Tell channeld to handle reestablish, then it will call closingd */
1880+
if (peer_start_channeld(channel,
1881+
pfd,
1882+
NULL, true,
1883+
NULL)) {
1884+
goto tell_connectd;
1885+
}
1886+
error = towire_warningfmt(tmpctx, &channel_id,
1887+
"Trouble in paradise?");
1888+
goto send_error;
1889+
}
18731890
send_reestablish(ld, channel);
1891+
}
18741892

18751893
/* If we have a canned error for this channel, send it now */
18761894
if (channel->error) {

lightningd/test/run-invoice-select-inchan.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,10 @@ bool peer_start_channeld(struct channel *channel UNNEEDED,
908908
bool reconnected UNNEEDED,
909909
bool reestablish_only UNNEEDED)
910910
{ fprintf(stderr, "peer_start_channeld called!\n"); abort(); }
911+
/* Generated stub for peer_start_closingd */
912+
void peer_start_closingd(struct channel *channel UNNEEDED,
913+
struct peer_fd *peer_fd UNNEEDED)
914+
{ fprintf(stderr, "peer_start_closingd called!\n"); abort(); }
911915
/* Generated stub for peer_start_dualopend */
912916
bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED,
913917
struct channel *channel UNNEEDED)

wallet/test/run-wallet.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,10 @@ bool peer_start_channeld(struct channel *channel UNNEEDED,
929929
bool reconnected UNNEEDED,
930930
bool reestablish_only UNNEEDED)
931931
{ fprintf(stderr, "peer_start_channeld called!\n"); abort(); }
932+
/* Generated stub for peer_start_closingd */
933+
void peer_start_closingd(struct channel *channel UNNEEDED,
934+
struct peer_fd *peer_fd UNNEEDED)
935+
{ fprintf(stderr, "peer_start_closingd called!\n"); abort(); }
932936
/* Generated stub for peer_start_dualopend */
933937
bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED,
934938
struct channel *channel UNNEEDED)

0 commit comments

Comments
 (0)