Browse Source

channeld: don't assume we offered option_data_loss_protect.

Check it was negotiated.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
plugin-6
Rusty Russell 6 years ago
parent
commit
54623a9ff5
  1. 1
      channeld/Makefile
  2. 68
      channeld/channeld.c

1
channeld/Makefile

@ -43,6 +43,7 @@ CHANNELD_COMMON_OBJS := \
common/daemon_conn.o \ common/daemon_conn.o \
common/derive_basepoints.o \ common/derive_basepoints.o \
common/dev_disconnect.o \ common/dev_disconnect.o \
common/features.o \
common/gen_status_wire.o \ common/gen_status_wire.o \
common/gen_peer_status_wire.o \ common/gen_peer_status_wire.o \
common/htlc_state.o \ common/htlc_state.o \

68
channeld/channeld.c

@ -28,6 +28,7 @@
#include <channeld/gen_channel_wire.h> #include <channeld/gen_channel_wire.h>
#include <common/crypto_sync.h> #include <common/crypto_sync.h>
#include <common/dev_disconnect.h> #include <common/dev_disconnect.h>
#include <common/features.h>
#include <common/htlc_tx.h> #include <common/htlc_tx.h>
#include <common/key_derive.h> #include <common/key_derive.h>
#include <common/memleak.h> #include <common/memleak.h>
@ -1893,16 +1894,6 @@ static void check_future_dataloss_fields(struct peer *peer,
assert(next_remote_revocation_number > peer->next_index[LOCAL] - 1); assert(next_remote_revocation_number > peer->next_index[LOCAL] - 1);
/* They don't support option_data_loss_protect, we fail it due to
* unexpected number */
if (!last_local_per_commit_secret)
peer_failed(&peer->cs,
&peer->channel_id,
"bad reestablish revocation_number: %"PRIu64
" vs %"PRIu64,
next_remote_revocation_number,
peer->next_index[LOCAL] - 1);
msg = towire_hsm_check_future_secret(NULL, msg = towire_hsm_check_future_secret(NULL,
next_remote_revocation_number - 1, next_remote_revocation_number - 1,
last_local_per_commit_secret); last_local_per_commit_secret);
@ -2035,8 +2026,12 @@ static void peer_reconnect(struct peer *peer,
const struct htlc *htlc; const struct htlc *htlc;
u8 *msg; u8 *msg;
struct pubkey my_current_per_commitment_point, struct pubkey my_current_per_commitment_point,
*remote_current_per_commitment_point; remote_current_per_commitment_point;
struct secret *last_local_per_commitment_secret; struct secret last_local_per_commitment_secret;
bool dataloss_protect;
dataloss_protect = local_feature_negotiated(peer->localfeatures,
LOCAL_DATA_LOSS_PROTECT);
get_per_commitment_point(peer->next_index[LOCAL]-1, get_per_commitment_point(peer->next_index[LOCAL]-1,
&my_current_per_commitment_point, NULL); &my_current_per_commitment_point, NULL);
@ -2064,12 +2059,20 @@ static void peer_reconnect(struct peer *peer,
* - MUST set `your_last_per_commitment_secret` to the last * - MUST set `your_last_per_commitment_secret` to the last
* `per_commitment_secret` it received * `per_commitment_secret` it received
*/ */
if (dataloss_protect) {
msg = towire_channel_reestablish_option_data_loss_protect msg = towire_channel_reestablish_option_data_loss_protect
(NULL, &peer->channel_id, (NULL, &peer->channel_id,
peer->next_index[LOCAL], peer->next_index[LOCAL],
peer->revocations_received, peer->revocations_received,
last_remote_per_commit_secret, last_remote_per_commit_secret,
&my_current_per_commitment_point); &my_current_per_commitment_point);
} else {
msg = towire_channel_reestablish
(NULL, &peer->channel_id,
peer->next_index[LOCAL],
peer->revocations_received);
}
sync_crypto_write(&peer->cs, PEER_FD, take(msg)); sync_crypto_write(&peer->cs, PEER_FD, take(msg));
peer_billboard(false, "Sent reestablish, waiting for theirs"); peer_billboard(false, "Sent reestablish, waiting for theirs");
@ -2083,22 +2086,20 @@ static void peer_reconnect(struct peer *peer,
} while (handle_peer_gossip_or_error(PEER_FD, GOSSIP_FD, &peer->cs, } while (handle_peer_gossip_or_error(PEER_FD, GOSSIP_FD, &peer->cs,
&peer->channel_id, msg)); &peer->channel_id, msg));
remote_current_per_commitment_point = tal(tmpctx, struct pubkey); if (dataloss_protect) {
last_local_per_commitment_secret = tal(tmpctx, struct secret);
/* We support option, so check for theirs. */
if (!fromwire_channel_reestablish_option_data_loss_protect(msg, if (!fromwire_channel_reestablish_option_data_loss_protect(msg,
&channel_id, &channel_id,
&next_local_commitment_number, &next_local_commitment_number,
&next_remote_revocation_number, &next_remote_revocation_number,
last_local_per_commitment_secret, &last_local_per_commitment_secret,
remote_current_per_commitment_point)) { &remote_current_per_commitment_point)) {
/* We don't have these, so free and NULL them */ peer_failed(&peer->cs,
remote_current_per_commitment_point &peer->channel_id,
= tal_free(remote_current_per_commitment_point); "bad reestablish dataloss msg: %s %s",
last_local_per_commitment_secret wire_type_name(fromwire_peektype(msg)),
= tal_free(last_local_per_commitment_secret); tal_hex(msg, msg));
}
} else {
if (!fromwire_channel_reestablish(msg, &channel_id, if (!fromwire_channel_reestablish(msg, &channel_id,
&next_local_commitment_number, &next_local_commitment_number,
&next_remote_revocation_number)) { &next_remote_revocation_number)) {
@ -2171,12 +2172,22 @@ static void peer_reconnect(struct peer *peer,
next_remote_revocation_number, next_remote_revocation_number,
peer->next_index[LOCAL]); peer->next_index[LOCAL]);
} else if (next_remote_revocation_number > peer->next_index[LOCAL] - 1) { } else if (next_remote_revocation_number > peer->next_index[LOCAL] - 1) {
if (!dataloss_protect)
/* They don't support option_data_loss_protect, we
* fail it due to unexpected number */
peer_failed(&peer->cs,
&peer->channel_id,
"bad reestablish revocation_number: %"PRIu64
" vs %"PRIu64,
next_remote_revocation_number,
peer->next_index[LOCAL] - 1);
/* Remote claims it's ahead of us: can it prove it? /* Remote claims it's ahead of us: can it prove it?
* Does not return. */ * Does not return. */
check_future_dataloss_fields(peer, check_future_dataloss_fields(peer,
next_remote_revocation_number, next_remote_revocation_number,
last_local_per_commitment_secret, &last_local_per_commitment_secret,
remote_current_per_commitment_point); &remote_current_per_commitment_point);
} else } else
retransmit_revoke_and_ack = false; retransmit_revoke_and_ack = false;
@ -2218,10 +2229,11 @@ static void peer_reconnect(struct peer *peer,
retransmit_commitment_signed = false; retransmit_commitment_signed = false;
/* After we checked basic sanity, we check dataloss fields if any */ /* After we checked basic sanity, we check dataloss fields if any */
if (dataloss_protect)
check_current_dataloss_fields(peer, check_current_dataloss_fields(peer,
next_remote_revocation_number, next_remote_revocation_number,
last_local_per_commitment_secret, &last_local_per_commitment_secret,
remote_current_per_commitment_point); &remote_current_per_commitment_point);
/* We have to re-send in the same order we sent originally: /* We have to re-send in the same order we sent originally:
* revoke_and_ack (usually) alters our next commitment. */ * revoke_and_ack (usually) alters our next commitment. */

Loading…
Cancel
Save