Browse Source

df-reconnects: allow tx-sigs in channeld iff we're reconnecting

There's a case where a dropped funding_locked will result in the peer
moving onto channeld, while we stay in dualopend. As we haven't
received their funding_locked, we retransmit tx_sigs, which channeld
will need to handle.

With the patch the peer drops it on the floor; the peer will resend
funding_locked on reconnect, which will correctly advance us to
channeld and CHANNELD_NORMAL
ppa
niftynei 4 years ago
committed by Christian Decker
parent
commit
99a621dd99
  1. 36
      channeld/channeld.c
  2. 5
      openingd/dualopend.c
  3. 6
      tests/test_connection.py

36
channeld/channeld.c

@ -185,6 +185,9 @@ struct peer {
/* Penalty bases for this channel / peer. */ /* Penalty bases for this channel / peer. */
struct penalty_base **pbases; 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); 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, type_to_string(msg, struct channel_id,
&peer->channel_id)); &peer->channel_id));
peer->tx_sigs_allowed = false;
peer->funding_locked[REMOTE] = true; peer->funding_locked[REMOTE] = true;
wire_sync_write(MASTER_FD, wire_sync_write(MASTER_FD,
take(towire_channeld_got_funding_locked(NULL, take(towire_channeld_got_funding_locked(NULL,
@ -1727,6 +1731,34 @@ static bool channeld_handle_custommsg(const u8 *msg)
#endif #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) static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg)
{ {
struct channel_id channel_id; 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_OPEN_CHANNEL2:
case WIRE_ACCEPT_CHANNEL2: case WIRE_ACCEPT_CHANNEL2:
case WIRE_TX_SIGNATURES: case WIRE_TX_SIGNATURES:
handle_unexpected_tx_sigs(peer, msg);
return;
case WIRE_BLACKLIST_PODLE: case WIRE_BLACKLIST_PODLE:
#endif #endif
break; break;
@ -2543,6 +2577,8 @@ static void peer_reconnect(struct peer *peer,
send_fail_or_fulfill(peer, htlc); 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."); peer_billboard(true, "Reconnected, and reestablished.");
/* BOLT #2: /* BOLT #2:

5
openingd/dualopend.c

@ -2539,7 +2539,10 @@ static void do_reconnect_dance(struct state *state)
} }
if (state->funding_locked[LOCAL]) { 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); send_funding_locked(state);
} }

6
tests/test_connection.py

@ -427,7 +427,11 @@ def test_reconnect_no_update(node_factory, executor):
# For channeld reconnection # For channeld reconnection
l1.rpc.connect(l2.info["id"], "localhost", l2.port) l1.rpc.connect(l2.info["id"], "localhost", l2.port)
fundchannel_exec = executor.submit(l1.fundchannel, l2, 10**6, False) 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() l1.stop()
# For closingd reconnection # For closingd reconnection

Loading…
Cancel
Save