Browse Source

df: actually run 'reconnect' code

ppa
niftynei 4 years ago
committed by Christian Decker
parent
commit
9cffa769b8
  1. 186
      openingd/dualopend.c

186
openingd/dualopend.c

@ -2358,6 +2358,186 @@ static void try_read_gossip_store(struct state *state)
sync_crypto_write(state->pps, take(msg));
}
/* Try to handle a custommsg Returns true if it was a custom message and has
* been handled, false if the message was not handled.
*/
static bool dualopend_handle_custommsg(const u8 *msg)
{
#if DEVELOPER
enum peer_wire type = fromwire_peektype(msg);
if (type % 2 == 1 && !peer_wire_is_defined(type)) {
/* The message is not part of the messages we know how to
* handle. Assuming this is a custommsg, we just forward it to the
* master. */
wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg)));
return true;
} else {
return false;
}
#else
return false;
#endif
}
/* BOLT #2:
*
* A receiving node:
* - if `option_static_remotekey` applies to the commitment transaction:
* - if `next_revocation_number` is greater than expected above, AND
* `your_last_per_commitment_secret` is correct for that
* `next_revocation_number` minus 1:
*...
* - otherwise, if it supports `option_data_loss_protect`:
* - if `next_revocation_number` is greater than expected above,
* AND `your_last_per_commitment_secret` is correct for that
* `next_revocation_number` minus 1:
*/
static void
check_future_dataloss_fields(struct state *state,
u64 next_revocation_number,
const struct secret *last_local_per_commit_secret)
{
const u8 *msg;
bool correct;
/* We're always at zero in dualopend */
assert(next_revocation_number > 0);
msg = towire_hsmd_check_future_secret(NULL,
next_revocation_number - 1,
last_local_per_commit_secret);
wire_sync_write(HSM_FD, take(msg));
msg = wire_sync_read(tmpctx, HSM_FD);
if (!fromwire_hsmd_check_future_secret_reply(msg, &correct))
status_failed(STATUS_FAIL_HSM_IO,
"Bad hsm_check_future_secret_reply: %s",
tal_hex(tmpctx, msg));
if (!correct)
peer_failed(state->pps,
&state->channel_id,
"bad future last_local_per_commit_secret: %"PRIu64
" vs %d",
next_revocation_number, 0);
/* Oh shit, they really are from the future! */
peer_billboard(true, "They have future commitment number %"PRIu64
" vs our %d. We must wait for them to close!",
next_revocation_number, 0);
/* BOLT #2:
* - MUST NOT broadcast its commitment transaction.
* - SHOULD fail the channel.
*/
wire_sync_write(REQ_FD,
take(towire_dualopend_fail_fallen_behind(NULL)));
/* We have to send them an error to trigger dropping to chain. */
peer_failed(state->pps, &state->channel_id,
"Awaiting unilateral close");
}
static void do_reconnect_dance(struct state *state)
{
u8 *msg;
struct channel_id cid;
/* Note: BOLT #2 uses these names! */
u64 next_commitment_number, next_revocation_number;
struct secret last_local_per_commit_secret,
last_remote_per_commit_secret;
struct pubkey remote_current_per_commit_point;
/* BOLT #2:
* - if `next_revocation_number` equals 0:
* - MUST set `your_last_per_commitment_secret` to all zeroes
*/
/* We always have no revocations in dualopend */
memset(&last_remote_per_commit_secret, 0,
sizeof(last_remote_per_commit_secret));
/* We always send reconnect/reestablish */
msg = towire_channel_reestablish
(NULL, &state->channel_id, 1, 0,
&last_remote_per_commit_secret,
&state->first_per_commitment_point[LOCAL]);
sync_crypto_write(state->pps, take(msg));
peer_billboard(false, "Sent reestablish, waiting for theirs");
bool soft_error = state->funding_locked[REMOTE]
|| state->funding_locked[LOCAL];
/* Read until they say something interesting (don't forward
* gossip *to* them yet: we might try sending channel_update
* before we've reestablished channel). */
do {
clean_tmpctx();
msg = sync_crypto_read(tmpctx, state->pps);
} while (dualopend_handle_custommsg(msg)
|| handle_peer_gossip_or_error(state->pps,
&state->channel_id,
soft_error, msg));
if (!fromwire_channel_reestablish
(msg, &cid,
&next_commitment_number,
&next_revocation_number,
&last_local_per_commit_secret,
&remote_current_per_commit_point))
peer_failed(state->pps,
&state->channel_id,
"Bad reestablish msg: %s %s",
peer_wire_name(fromwire_peektype(msg)),
tal_hex(msg, msg));
check_channel_id(state, &cid, &state->channel_id);
status_debug("Got dualopend reestablish commit=%"PRIu64
" revoke=%"PRIu64,
next_commitment_number,
next_revocation_number);
/* BOLT #2:
* - if it has not sent `revoke_and_ack`, AND
* `next_revocation_number` is not equal to 0:
* - SHOULD fail the channel.
*/
/* It's possible that we've opened an outdated copy of the
* database, and the peer is very much ahead of us.
*/
if (next_revocation_number != 0) {
/* Remote claims it's ahead of us: can it prove it?
* Does not return. */
check_future_dataloss_fields(state,
next_revocation_number,
&last_local_per_commit_secret);
}
if (next_commitment_number != 1)
peer_failed(state->pps,
&state->channel_id,
"bad reestablish commitment_number: %"PRIu64
" vs %d",
next_commitment_number, 1);
/* It's possible we sent our sigs, but they didn't get them.
* Resend our signatures, just in case */
if (psbt_side_finalized(state->psbt, state->our_role)
&& !state->funding_locked[REMOTE]) {
msg = psbt_to_tx_sigs_msg(NULL, state, state->psbt);
sync_crypto_write(state->pps, take(msg));
}
if (state->funding_locked[LOCAL]) {
status_debug("we've got locked, sending locked");
send_funding_locked(state);
}
peer_billboard(true, "Reconnected, and reestablished.");
}
/*~ Is this message of type `error` with the special zero-id
* "fail-everything"? If lightningd asked us to send such a thing, we're
* done. */
@ -2664,6 +2844,12 @@ int main(int argc, char *argv[])
pollfd[2].fd = state->pps->peer_fd;
pollfd[2].events = POLLIN;
/* Do reconnect, if need be */
if (state->channel) {
do_reconnect_dance(state);
state->reconnected = true;
}
/* We exit when we get a conclusion to write to lightningd: either
* opening_funder_reply or opening_fundee. */
msg = NULL;

Loading…
Cancel
Save