Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

channeld: handle reestablish from previous release with EXPERIMENTAL_FEATURES #4830

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 120 additions & 48 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,37 +332,32 @@ static bool handle_master_request_later(struct peer *peer, const u8 *msg)
return false;
}

static bool match_type(const struct channel_type *desired,
const struct channel_type *current,
struct channel_type **upgradable)
/* Compare, with false if either is NULL */
static bool match_type(const u8 *t1, const u8 *t2)
{
/* Missing fields are possible. */
if (!desired || !current)
if (!t1 || !t2)
return false;

if (channel_type_eq(desired, current))
return true;

return channel_type_eq_any(desired, upgradable);
return featurebits_eq(t1, t2);
}

static void set_channel_type(struct channel *channel,
const struct channel_type *type)
static void set_channel_type(struct channel *channel, const u8 *type)
{
const struct channel_type *cur = channel->type;

if (channel_type_eq(cur, type))
if (featurebits_eq(cur->features, type))
return;

/* We only allow one upgrade at the moment, so that's it. */
assert(!channel_has(channel, OPT_STATIC_REMOTEKEY));
assert(feature_offered(type->features, OPT_STATIC_REMOTEKEY));
assert(feature_offered(type, OPT_STATIC_REMOTEKEY));

/* Do upgrade, tell master. */
tal_free(channel->type);
channel->type = channel_type_dup(channel, type);
channel->type = channel_type_from(channel, type);
status_unusual("Upgraded channel to [%s]",
fmt_featurebits(tmpctx, type->features));
fmt_featurebits(tmpctx, type));
wire_sync_write(MASTER_FD,
take(towire_channeld_upgraded(NULL, channel->type)));
}
Expand Down Expand Up @@ -2650,6 +2645,43 @@ static bool capture_premature_msg(const u8 ***shit_lnd_says, const u8 *msg)
return true;
}

#if EXPERIMENTAL_FEATURES
/* Unwrap a channel_type into a raw byte array for the wire: can be NULL */
static u8 *to_bytearr(const tal_t *ctx,
const struct channel_type *channel_type TAKES)
{
u8 *ret;
bool steal;

steal = taken(channel_type);
if (!channel_type)
return NULL;

if (steal) {
ret = tal_steal(ctx, channel_type->features);
tal_free(channel_type);
} else
ret = tal_dup_talarr(ctx, u8, channel_type->features);
return ret;
}

/* This is the no-tlvs version, where we can't handle old tlvs */
static bool fromwire_channel_reestablish_notlvs(const void *p, struct channel_id *channel_id, u64 *next_commitment_number, u64 *next_revocation_number, struct secret *your_last_per_commitment_secret, struct pubkey *my_current_per_commitment_point)
{
const u8 *cursor = p;
size_t plen = tal_count(p);

if (fromwire_u16(&cursor, &plen) != WIRE_CHANNEL_REESTABLISH)
return false;
fromwire_channel_id(&cursor, &plen, channel_id);
*next_commitment_number = fromwire_u64(&cursor, &plen);
*next_revocation_number = fromwire_u64(&cursor, &plen);
fromwire_secret(&cursor, &plen, your_last_per_commitment_secret);
fromwire_pubkey(&cursor, &plen, my_current_per_commitment_point);
return cursor != NULL;
}
#endif

static void peer_reconnect(struct peer *peer,
const struct secret *last_remote_per_commit_secret,
u8 *reestablish_only)
Expand Down Expand Up @@ -2686,6 +2718,14 @@ static void peer_reconnect(struct peer *peer,
#if EXPERIMENTAL_FEATURES
/* Subtle: we free tmpctx below as we loop, so tal off peer */
send_tlvs = tlv_channel_reestablish_tlvs_new(peer);

/* FIXME: v0.10.1 would send a different tlv set, due to older spec.
* That did *not* offer OPT_QUIESCE, so in that case don't send tlvs. */
if (!feature_negotiated(peer->our_features,
peer->their_features,
OPT_QUIESCE))
goto skip_tlvs;

/* BOLT-upgrade_protocol #2:
* A node sending `channel_reestablish`, if it supports upgrading channels:
* - MUST set `next_to_send` the commitment number of the next
Expand All @@ -2699,8 +2739,10 @@ static void peer_reconnect(struct peer *peer,
* channel.
*/
if (peer->channel->opener == LOCAL)
send_tlvs->desired_type = channel_desired_type(send_tlvs,
peer->channel);
send_tlvs->desired_channel_type =
to_bytearr(send_tlvs,
take(channel_desired_type(NULL,
peer->channel)));
else {
/* BOLT-upgrade_protocol #2:
* - otherwise:
Expand All @@ -2710,11 +2752,15 @@ static void peer_reconnect(struct peer *peer,
* to.
* - MAY not set `upgradable` if it would be empty.
*/
send_tlvs->current_type = tal_dup(send_tlvs, struct channel_type,
peer->channel->type);
send_tlvs->upgradable = channel_upgradable_types(send_tlvs,
peer->channel);
send_tlvs->current_channel_type
= to_bytearr(send_tlvs, peer->channel->type);
send_tlvs->upgradable_channel_type
= to_bytearr(send_tlvs,
take(channel_upgradable_type(NULL,
peer->channel)));
}

skip_tlvs:
#endif

/* BOLT #2:
Expand Down Expand Up @@ -2799,24 +2845,50 @@ static void peer_reconnect(struct peer *peer,
got_reestablish:
#if EXPERIMENTAL_FEATURES
recv_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx);
#endif

/* FIXME: v0.10.1 would send a different tlv set, due to older spec.
* That did *not* offer OPT_QUIESCE, so in that case ignore tlvs. */
if (!feature_negotiated(peer->our_features,
peer->their_features,
OPT_QUIESCE)) {
if (!fromwire_channel_reestablish_notlvs(msg,
&channel_id,
&next_commitment_number,
&next_revocation_number,
&last_local_per_commitment_secret,
&remote_current_per_commitment_point))
peer_failed_warn(peer->pps,
&peer->channel_id,
"bad reestablish msg: %s %s",
peer_wire_name(fromwire_peektype(msg)),
tal_hex(msg, msg));
} else if (!fromwire_channel_reestablish(msg,
&channel_id,
&next_commitment_number,
&next_revocation_number,
&last_local_per_commitment_secret,
&remote_current_per_commitment_point,
recv_tlvs)) {
peer_failed_warn(peer->pps,
&peer->channel_id,
"bad reestablish msg: %s %s",
peer_wire_name(fromwire_peektype(msg)),
tal_hex(msg, msg));
}
#else /* !EXPERIMENTAL_FEATURES */
if (!fromwire_channel_reestablish(msg,
&channel_id,
&next_commitment_number,
&next_revocation_number,
&last_local_per_commitment_secret,
&remote_current_per_commitment_point
#if EXPERIMENTAL_FEATURES
, recv_tlvs
#endif
)) {
&remote_current_per_commitment_point)) {
peer_failed_warn(peer->pps,
&peer->channel_id,
"bad reestablish msg: %s %s",
peer_wire_name(fromwire_peektype(msg)),
tal_hex(msg, msg));
}
#endif

if (!channel_id_eq(&channel_id, &peer->channel_id)) {
peer_failed_err(peer->pps,
Expand Down Expand Up @@ -2991,20 +3063,19 @@ static void peer_reconnect(struct peer *peer,
maybe_send_shutdown(peer);

#if EXPERIMENTAL_FEATURES
if (recv_tlvs->desired_type)
status_debug("They sent desired_type [%s]",
if (recv_tlvs->desired_channel_type)
status_debug("They sent desired_channel_type [%s]",
fmt_featurebits(tmpctx,
recv_tlvs->desired_type->features));
if (recv_tlvs->current_type)
status_debug("They sent current_type [%s]",
recv_tlvs->desired_channel_type));
if (recv_tlvs->current_channel_type)
status_debug("They sent current_channel_type [%s]",
fmt_featurebits(tmpctx,
recv_tlvs->current_type->features));
recv_tlvs->current_channel_type));

for (size_t i = 0; i < tal_count(recv_tlvs->upgradable); i++) {
if (recv_tlvs->upgradable_channel_type)
status_debug("They offered upgrade to [%s]",
fmt_featurebits(tmpctx,
recv_tlvs->upgradable[i]->features));
}
recv_tlvs->upgradable_channel_type));

/* BOLT-upgrade_protocol #2:
*
Expand Down Expand Up @@ -3036,7 +3107,7 @@ static void peer_reconnect(struct peer *peer,
status_debug("No upgrade: pending changes");
} else {
const struct tlv_channel_reestablish_tlvs *initr, *ninitr;
const struct channel_type *type;
const u8 *type;

if (peer->channel->opener == LOCAL) {
initr = send_tlvs;
Expand All @@ -3048,20 +3119,21 @@ static void peer_reconnect(struct peer *peer,

/* BOLT-upgrade_protocol #2:
*
* - if `desired_type` matches `current_type` or any
* `upgradable` `upgrades`:
* - MUST consider the channel type to be `desired_type`.
* - if `desired_channel_type` matches `current_channel_type` or any
* `upgradable_channel_type`:
* - MUST consider the channel type to be `desired_channel_type`.
* - otherwise:
* - MUST consider the channel feature change failed.
* - if there is a `current_type` field:
* - MUST consider the channel type to be `current_type`.
* - MUST consider the channel type change failed.
* - if there is a `current_channel_type` field:
* - MUST consider the channel type to be `current_channel_type`.
*/
/* Note: returns NULL on missing fields, aka NULL */
if (match_type(initr->desired_type,
ninitr->current_type, ninitr->upgradable))
type = initr->desired_type;
else if (ninitr->current_type)
type = ninitr->current_type;
if (match_type(initr->desired_channel_type,
ninitr->current_channel_type)
|| match_type(initr->desired_channel_type,
ninitr->upgradable_channel_type))
type = initr->desired_channel_type;
else if (ninitr->current_channel_type)
type = ninitr->current_channel_type;
else
type = NULL;

Expand Down
18 changes: 8 additions & 10 deletions common/channel_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,6 @@ bool channel_type_eq(const struct channel_type *a,
return featurebits_eq(a->features, b->features);
}

bool channel_type_eq_any(const struct channel_type *t,
struct channel_type **arr)
{
for (size_t i = 0; i < tal_count(arr); i++) {
if (channel_type_eq(t, arr[i]))
return true;
}
return false;
}

struct channel_type *channel_type_dup(const tal_t *ctx,
const struct channel_type *t)
{
Expand All @@ -104,6 +94,14 @@ struct channel_type *channel_type_dup(const tal_t *ctx,
return ret;
}

struct channel_type *channel_type_from(const tal_t *ctx,
const u8 *features TAKES)
{
struct channel_type *ret = tal(ctx, struct channel_type);
ret->features = tal_dup_talarr(ret, u8, features);
return ret;
}

struct channel_type *channel_type_accept(const tal_t *ctx,
const u8 *t,
const struct feature_set *our_features,
Expand Down
8 changes: 4 additions & 4 deletions common/channel_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ struct channel_type *channel_type_anchor_outputs(const tal_t *ctx);
struct channel_type *channel_type_dup(const tal_t *ctx,
const struct channel_type *t);

/* Convert feature bits to channel_type */
struct channel_type *channel_type_from(const tal_t *ctx,
const u8 *features TAKES);

/* Derive channel type from feature negotiation */
struct channel_type *default_channel_type(const tal_t *ctx,
const struct feature_set *our_features,
Expand All @@ -26,10 +30,6 @@ bool channel_type_has(const struct channel_type *type, int feature);
bool channel_type_eq(const struct channel_type *a,
const struct channel_type *b);

/* Is channel_type_eq() for any type in this array? */
bool channel_type_eq_any(const struct channel_type *t,
struct channel_type **arr);

/* Return channel_type if this is acceptable, otherwise NULL */
struct channel_type *channel_type_accept(const tal_t *ctx,
const u8 *t,
Expand Down
6 changes: 5 additions & 1 deletion common/features.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ static const struct feature_style feature_styles[] = {
.copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT,
[NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT,
[CHANNEL_FEATURE] = FEATURE_DONT_REPRESENT } },
{ OPT_QUIESCE,
.copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT,
[NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT,
[CHANNEL_FEATURE] = FEATURE_DONT_REPRESENT } },
};

struct dependency {
Expand Down Expand Up @@ -393,7 +397,7 @@ const char *feature_name(const tal_t *ctx, size_t f)
"option_dual_fund",
"option_amp", /* 30/31 */ /* https://github.com/lightningnetwork/lightning-rfc/pull/658 */
NULL,
"option_upgrade_channel", /* https://github.com/lightningnetwork/lightning-rfc/pull/868 */
"option_quiesce", /* https://github.com/lightningnetwork/lightning-rfc/pull/869 */
NULL,
"option_onion_messages", /* https://github.com/lightningnetwork/lightning-rfc/pull/759 */
"option_want_peer_backup", /* 40/41 */ /* https://github.com/lightningnetwork/lightning-rfc/pull/881 */
Expand Down
5 changes: 5 additions & 0 deletions common/features.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ const char *fmt_featurebits(const tal_t *ctx, const u8 *featurebits);
*/
#define OPT_DUAL_FUND 28

/* BOLT-quiescent #9:
* | 34/35 | `option_quiesce` | ... IN ...
*/
#define OPT_QUIESCE 34

/* BOLT-1ede04a1a3225581e265b3ce96984ba88253a4a4 #9:
*
* | 38/39 | `option_onion_messages` |... INC+ ...
Expand Down
10 changes: 4 additions & 6 deletions common/initial_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,13 @@ u32 channel_blockheight(const struct channel *channel, enum side side)
channel->opener, side);
}

struct channel_type **channel_upgradable_types(const tal_t *ctx,
const struct channel *channel)
struct channel_type *channel_upgradable_type(const tal_t *ctx,
const struct channel *channel)
{
struct channel_type **arr = tal_arr(ctx, struct channel_type *, 0);

if (!channel_has(channel, OPT_STATIC_REMOTEKEY))
tal_arr_expand(&arr, channel_type_static_remotekey(arr));
return channel_type_static_remotekey(ctx);

return arr;
return NULL;
}

struct channel_type *channel_desired_type(const tal_t *ctx,
Expand Down
12 changes: 4 additions & 8 deletions common/initial_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,11 @@ u32 channel_feerate(const struct channel *channel, enum side side);
*/
u32 channel_blockheight(const struct channel *channel, enum side side);

/* BOLT-upgrade_protocol #2:
* Channel features are explicitly enumerated as `channel_type` bitfields,
* using odd features bits.
*/
/* What features can we upgrade? (Returns NULL if none). */
struct channel_type **channel_upgradable_types(const tal_t *ctx,
const struct channel *channel);
/* What can we upgrade to? (Returns NULL if none). */
struct channel_type *channel_upgradable_type(const tal_t *ctx,
const struct channel *channel);

/* What features do we want? */
/* What channel type do we want? */
struct channel_type *channel_desired_type(const tal_t *ctx,
const struct channel *channel);

Expand Down
2 changes: 1 addition & 1 deletion external/lnprototest
Loading