Browse Source

lightningd: re-allow closing negotiation when CLOSINGD_COMPLETE

d822ba1ee accidentally removed this case, which is important: if the
other side didn't get our final matching closing_signed, it will
reconnect and try again.  We consider the channel no longer "active"
and thus ignore it, and get upset when it send the
`channel_reestablish` message.

We could just consider CLOSINGD_COMPLETE to be active, but then we'd
have to wait for the closing transaction to be mined before we'd allow
another connection.

We can't special case it when the peer reconnects, because there
could be (in theory) multiple channels for that peer in CLOSINGD_COMPLETE,
and we don't know which one to reestablish.

So, we need to catch this when they send the reestablish, and hand
that msg to closingd to do negotiation again.  We already have code
to note that we're in CLOSINGD_COMPLETE and thus ignore any result
it gives us.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
d2b4e09e27
  1. 27
      closingd/closing.c
  2. 2
      closingd/closing_wire.csv
  3. 3
      lightningd/channel_control.c
  4. 8
      lightningd/closing_control.c
  5. 5
      lightningd/closing_control.h
  6. 13
      lightningd/peer_control.c
  7. 5
      wallet/test/run-wallet.c

27
closingd/closing.c

@ -81,7 +81,8 @@ static void do_reconnect(struct crypto_state *cs,
u64 gossip_index, u64 gossip_index,
const struct channel_id *channel_id, const struct channel_id *channel_id,
const u64 next_index[NUM_SIDES], const u64 next_index[NUM_SIDES],
u64 revocations_received) u64 revocations_received,
const u8 *channel_reestablish)
{ {
u8 *msg; u8 *msg;
struct channel_id their_channel_id; struct channel_id their_channel_id;
@ -104,20 +105,25 @@ static void do_reconnect(struct crypto_state *cs,
if (!sync_crypto_write(cs, PEER_FD, take(msg))) if (!sync_crypto_write(cs, PEER_FD, take(msg)))
peer_failed_connection_lost(); peer_failed_connection_lost();
/* They might have already send reestablish, which triggered us */
while (!channel_reestablish) {
clean_tmpctx();
/* Wait for them to say something interesting */ /* Wait for them to say something interesting */
while ((msg = read_peer_msg(tmpctx, cs, gossip_index, channel_id, channel_reestablish
= read_peer_msg(tmpctx, cs, gossip_index, channel_id,
sync_crypto_write_arg, sync_crypto_write_arg,
status_fail_io, status_fail_io,
NULL)) == NULL) NULL);
clean_tmpctx(); }
if (!fromwire_channel_reestablish(msg, &their_channel_id, if (!fromwire_channel_reestablish(channel_reestablish, &their_channel_id,
&next_local_commitment_number, &next_local_commitment_number,
&next_remote_revocation_number)) { &next_remote_revocation_number)) {
peer_failed(cs, gossip_index, channel_id, peer_failed(cs, gossip_index, channel_id,
"bad reestablish msg: %s %s", "bad reestablish msg: %s %s",
wire_type_name(fromwire_peektype(msg)), wire_type_name(fromwire_peektype(channel_reestablish)),
tal_hex(tmpctx, msg)); tal_hex(tmpctx, channel_reestablish));
} }
status_trace("Got reestablish commit=%"PRIu64" revoke=%"PRIu64, status_trace("Got reestablish commit=%"PRIu64" revoke=%"PRIu64,
next_local_commitment_number, next_local_commitment_number,
@ -443,6 +449,7 @@ int main(int argc, char *argv[])
u64 gossip_index; u64 gossip_index;
enum side whose_turn; enum side whose_turn;
bool deprecated_api; bool deprecated_api;
u8 *channel_reestablish;
subdaemon_setup(argc, argv); subdaemon_setup(argc, argv);
@ -466,7 +473,8 @@ int main(int argc, char *argv[])
&next_index[LOCAL], &next_index[LOCAL],
&next_index[REMOTE], &next_index[REMOTE],
&revocations_received, &revocations_received,
&deprecated_api)) &deprecated_api,
&channel_reestablish))
master_badmsg(WIRE_CLOSING_INIT, msg); master_badmsg(WIRE_CLOSING_INIT, msg);
status_trace("satoshi_out = %"PRIu64"/%"PRIu64, status_trace("satoshi_out = %"PRIu64"/%"PRIu64,
@ -483,7 +491,8 @@ int main(int argc, char *argv[])
if (reconnected) if (reconnected)
do_reconnect(&cs, gossip_index, &channel_id, do_reconnect(&cs, gossip_index, &channel_id,
next_index, revocations_received); next_index, revocations_received,
channel_reestablish);
peer_billboard(true, "Negotiating closing fee between %"PRIu64 peer_billboard(true, "Negotiating closing fee between %"PRIu64
" and %"PRIu64" satoshi (ideal %"PRIu64")", " and %"PRIu64" satoshi (ideal %"PRIu64")",

2
closingd/closing_wire.csv

@ -26,6 +26,8 @@ closing_init,,next_index_remote,u64
closing_init,,revocations_received,u64 closing_init,,revocations_received,u64
# This means we allow closing negotiations out of bounds. # This means we allow closing negotiations out of bounds.
closing_init,,deprecated_api,bool closing_init,,deprecated_api,bool
closing_init,,channel_reestablish_len,u16
closing_init,,channel_reestablish,channel_reestablish_len*u8
# We received an offer, save signature. # We received an offer, save signature.
closing_received_signature,2002 closing_received_signature,2002

Can't render this file because it has a wrong number of fields in line 3.

3
lightningd/channel_control.c

@ -114,7 +114,8 @@ static void peer_start_closingd_after_shutdown(struct channel *channel,
} }
/* This sets channel->owner, closes down channeld. */ /* This sets channel->owner, closes down channeld. */
peer_start_closingd(channel, &cs, gossip_index, fds[0], fds[1], false); peer_start_closingd(channel, &cs, gossip_index, fds[0], fds[1],
false, NULL);
channel_set_state(channel, CHANNELD_SHUTTING_DOWN, CLOSINGD_SIGEXCHANGE); channel_set_state(channel, CHANNELD_SHUTTING_DOWN, CLOSINGD_SIGEXCHANGE);
} }

8
lightningd/closing_control.c

@ -121,10 +121,11 @@ static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds UNUSE
} }
void peer_start_closingd(struct channel *channel, void peer_start_closingd(struct channel *channel,
struct crypto_state *cs, const struct crypto_state *cs,
u64 gossip_index, u64 gossip_index,
int peer_fd, int gossip_fd, int peer_fd, int gossip_fd,
bool reconnected) bool reconnected,
const u8 *channel_reestablish)
{ {
u8 *initmsg; u8 *initmsg;
u64 minfee, startfee, feelimit; u64 minfee, startfee, feelimit;
@ -204,7 +205,8 @@ void peer_start_closingd(struct channel *channel,
channel->next_index[LOCAL], channel->next_index[LOCAL],
channel->next_index[REMOTE], channel->next_index[REMOTE],
num_revocations, num_revocations,
deprecated_apis); deprecated_apis,
channel_reestablish);
/* We don't expect a response: it will give us feedback on /* We don't expect a response: it will give us feedback on
* signatures sent and received, then closing_complete. */ * signatures sent and received, then closing_complete. */

5
lightningd/closing_control.h

@ -7,9 +7,10 @@ struct channel_id;
struct crypto_state; struct crypto_state;
void peer_start_closingd(struct channel *channel, void peer_start_closingd(struct channel *channel,
struct crypto_state *cs, const struct crypto_state *cs,
u64 gossip_index, u64 gossip_index,
int peer_fd, int gossip_fd, int peer_fd, int gossip_fd,
bool reconnected); bool reconnected,
const u8 *channel_reestablish);
#endif /* LIGHTNING_LIGHTNINGD_CLOSING_CONTROL_H */ #endif /* LIGHTNING_LIGHTNINGD_CLOSING_CONTROL_H */

13
lightningd/peer_control.c

@ -502,7 +502,7 @@ void peer_connected(struct lightningd *ld, const u8 *msg,
channel->peer->addr = addr; channel->peer->addr = addr;
peer_start_closingd(channel, &cs, gossip_index, peer_start_closingd(channel, &cs, gossip_index,
peer_fd, gossip_fd, peer_fd, gossip_fd,
true); true, NULL);
goto connected; goto connected;
} }
abort(); abort();
@ -590,6 +590,17 @@ void peer_sent_nongossip(struct lightningd *ld,
error = channel->error; error = channel->error;
goto send_error; goto send_error;
} }
/* Reestablish for a now-closed channel? They might have
* missed final update, so do the closing negotiation dance
* again. */
if (fromwire_peektype(in_msg) == WIRE_CHANNEL_REESTABLISH
&& channel
&& channel->state == CLOSINGD_COMPLETE) {
peer_start_closingd(channel, cs, gossip_index,
peer_fd, gossip_fd, true, in_msg);
return;
}
} }
/* Weird request. */ /* Weird request. */

5
wallet/test/run-wallet.c

@ -333,10 +333,11 @@ bool peer_start_channeld(struct channel *channel UNNEEDED,
{ fprintf(stderr, "peer_start_channeld called!\n"); abort(); } { fprintf(stderr, "peer_start_channeld called!\n"); abort(); }
/* Generated stub for peer_start_closingd */ /* Generated stub for peer_start_closingd */
void peer_start_closingd(struct channel *channel UNNEEDED, void peer_start_closingd(struct channel *channel UNNEEDED,
struct crypto_state *cs UNNEEDED, const struct crypto_state *cs UNNEEDED,
u64 gossip_index UNNEEDED, u64 gossip_index UNNEEDED,
int peer_fd UNNEEDED, int gossip_fd UNNEEDED, int peer_fd UNNEEDED, int gossip_fd UNNEEDED,
bool reconnected UNNEEDED) bool reconnected UNNEEDED,
const u8 *channel_reestablish UNNEEDED)
{ fprintf(stderr, "peer_start_closingd called!\n"); abort(); } { fprintf(stderr, "peer_start_closingd called!\n"); abort(); }
/* Generated stub for sanitize_error */ /* Generated stub for sanitize_error */
char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED,

Loading…
Cancel
Save