diff --git a/channeld/channeld.c b/channeld/channeld.c index 623b989f0..e0c304a0a 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -185,6 +185,9 @@ struct peer { /* Penalty bases for this channel / peer. */ struct penalty_base **pbases; + + /* We allow a 'tx-sigs' message between reconnect + funding_locked */ + bool tx_sigs_allowed; }; static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer); @@ -561,6 +564,7 @@ static void handle_peer_funding_locked(struct peer *peer, const u8 *msg) type_to_string(msg, struct channel_id, &peer->channel_id)); + peer->tx_sigs_allowed = false; peer->funding_locked[REMOTE] = true; wire_sync_write(MASTER_FD, take(towire_channeld_got_funding_locked(NULL, @@ -1727,6 +1731,34 @@ static bool channeld_handle_custommsg(const u8 *msg) #endif } +#if EXPERIMENTAL_FEATURES +static void handle_unexpected_tx_sigs(struct peer *peer, const u8 *msg) +{ + const struct witness_stack **ws; + struct channel_id cid; + struct bitcoin_txid txid; + + /* In a rare case, a v2 peer may re-send a tx_sigs message. + * This happens when they've/we've exchanged funding_locked, + * but they did not receive our funding_locked. */ + if (!fromwire_tx_signatures(tmpctx, msg, &cid, &txid, + cast_const3(struct witness_stack ***, &ws))) + peer_failed(peer->pps, + &peer->channel_id, + "Bad tx_signatures %s", + tal_hex(msg, msg)); + + status_info("Unexpected `tx_signatures` from peer. %s", + peer->tx_sigs_allowed ? "Allowing." : "Failing."); + + if (!peer->tx_sigs_allowed) + peer_failed(peer->pps, &peer->channel_id, + "Unexpected `tx_signatures`"); + + peer->tx_sigs_allowed = false; +} +#endif /* EXPERIMENTAL_FEATURES */ + static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) { struct channel_id channel_id; @@ -1877,6 +1909,8 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_OPEN_CHANNEL2: case WIRE_ACCEPT_CHANNEL2: case WIRE_TX_SIGNATURES: + handle_unexpected_tx_sigs(peer, msg); + return; case WIRE_BLACKLIST_PODLE: #endif break; @@ -2543,6 +2577,8 @@ static void peer_reconnect(struct peer *peer, send_fail_or_fulfill(peer, htlc); } + /* We allow peer to send us tx-sigs, until funding locked received */ + peer->tx_sigs_allowed = true; peer_billboard(true, "Reconnected, and reestablished."); /* BOLT #2: diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 0ff258342..39506d848 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -2539,7 +2539,10 @@ static void do_reconnect_dance(struct state *state) } if (state->funding_locked[LOCAL]) { - status_debug("we've got locked, sending locked"); + status_debug("Retransmitting funding_locked for channel %s", + type_to_string(tmpctx, + struct channel_id, + &state->channel_id)); send_funding_locked(state); } diff --git a/tests/test_connection.py b/tests/test_connection.py index 3f736eb2b..7063be802 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -427,7 +427,11 @@ def test_reconnect_no_update(node_factory, executor): # For channeld reconnection l1.rpc.connect(l2.info["id"], "localhost", l2.port) fundchannel_exec = executor.submit(l1.fundchannel, l2, 10**6, False) - l1.daemon.wait_for_log(r"channeld.* Retransmitting funding_locked for channel") + if l1.config('experimental-dual-fund'): + l2.daemon.wait_for_log(r"Unexpected `tx_signatures` from peer. Allowing.") + l1.daemon.wait_for_log(r"dualopend.* Retransmitting funding_locked for channel") + else: + l1.daemon.wait_for_log(r"channeld.* Retransmitting funding_locked for channel") l1.stop() # For closingd reconnection