diff --git a/channeld/channeld.c b/channeld/channeld.c index ab814c127..9d2ea7b37 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -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))); } @@ -2650,6 +2645,27 @@ 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; +} +#endif + static void peer_reconnect(struct peer *peer, const struct secret *last_remote_per_commit_secret, u8 *reestablish_only) @@ -2699,8 +2715,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: @@ -2710,10 +2728,12 @@ 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))); } #endif @@ -2991,20 +3011,19 @@ got_reestablish: 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: * @@ -3036,7 +3055,7 @@ got_reestablish: 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; @@ -3048,20 +3067,21 @@ got_reestablish: /* 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; diff --git a/common/channel_type.c b/common/channel_type.c index 9a7abf0c2..890b191c6 100644 --- a/common/channel_type.c +++ b/common/channel_type.c @@ -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) { @@ -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, diff --git a/common/channel_type.h b/common/channel_type.h index e34ee52bf..858dc6471 100644 --- a/common/channel_type.h +++ b/common/channel_type.h @@ -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, @@ -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, diff --git a/common/initial_channel.c b/common/initial_channel.c index 9cf82ef81..28c99ff05 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -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, diff --git a/common/initial_channel.h b/common/initial_channel.h index 03e8140ba..7dc75eade 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -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); diff --git a/tests/test_connection.py b/tests/test_connection.py index 2082b49f4..79940d9b2 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -3499,9 +3499,9 @@ def test_upgrade_statickey(node_factory, executor): l1.rpc.disconnect(l2.info['id'], force=True) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) - l1.daemon.wait_for_logs([r"They sent current_type \[\]", + l1.daemon.wait_for_logs([r"They sent current_channel_type \[\]", r"They offered upgrade to \[12\]"]) - l2.daemon.wait_for_log(r"They sent desired_type \[12\]") + l2.daemon.wait_for_log(r"They sent desired_channel_type \[12\]") l1.daemon.wait_for_log('option_static_remotekey enabled at 1/1') l2.daemon.wait_for_log('option_static_remotekey enabled at 1/1') @@ -3514,8 +3514,8 @@ def test_upgrade_statickey(node_factory, executor): # They won't offer upgrade! assert not l1.daemon.is_in_log("They offered upgrade", start=l1.daemon.logsearch_start) - l1.daemon.wait_for_log(r"They sent current_type \[12\]") - l2.daemon.wait_for_log(r"They sent desired_type \[12\]") + l1.daemon.wait_for_log(r"They sent current_channel_type \[12\]") + l2.daemon.wait_for_log(r"They sent desired_channel_type \[12\]") @unittest.skipIf(not EXPERIMENTAL_FEATURES, "upgrade protocol not available") diff --git a/wire/extracted_peer_exp_upgradable.patch b/wire/extracted_peer_exp_upgradable.patch index 2f85d96ac..e5818692f 100644 --- a/wire/extracted_peer_exp_upgradable.patch +++ b/wire/extracted_peer_exp_upgradable.patch @@ -1,18 +1,18 @@ --- wire/peer_wire.csv 2021-05-09 15:44:59.166135652 +0930 +++ wire/peer_wire.csv.raw 2021-05-11 09:59:31.695459756 +0930 -@@ -221,6 +131,15 @@ +@@ -244,6 +140,15 @@ msgdata,channel_reestablish,next_revocation_number,u64, msgdata,channel_reestablish,your_last_per_commitment_secret,byte,32 msgdata,channel_reestablish,my_current_per_commitment_point,point, +msgdata,channel_reestablish,tlvs,channel_reestablish_tlvs, +tlvtype,channel_reestablish_tlvs,next_to_send,1 +tlvdata,channel_reestablish_tlvs,next_to_send,commitment_number,tu64, -+tlvtype,channel_reestablish_tlvs,desired_type,3 -+tlvdata,channel_reestablish_tlvs,desired_type,type,channel_type, -+tlvtype,channel_reestablish_tlvs,current_type,5 -+tlvdata,channel_reestablish_tlvs,current_type,type,channel_type, -+tlvtype,channel_reestablish_tlvs,upgradable,7 -+tlvdata,channel_reestablish_tlvs,upgradable,upgrades,channel_type,... ++tlvtype,channel_reestablish_tlvs,desired_channel_type,3 ++tlvdata,channel_reestablish_tlvs,desired_channel_type,type,byte,... ++tlvtype,channel_reestablish_tlvs,current_channel_type,5 ++tlvdata,channel_reestablish_tlvs,current_channel_type,type,byte,... ++tlvtype,channel_reestablish_tlvs,upgradable_channel_type,7 ++tlvdata,channel_reestablish_tlvs,upgradable_channel_type,type,byte,... msgtype,announcement_signatures,259 msgdata,announcement_signatures,channel_id,channel_id, msgdata,announcement_signatures,short_channel_id,short_channel_id,