channeld: import updated channel_upgrade spec.

It now uses raw bitfields instead of a subtype, and only allows a single
option for any upgrade.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2021-10-08 10:10:30 +10:30 committed by Christian Decker
parent 55dbe82162
commit 7157a92ea6
7 changed files with 93 additions and 81 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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);

View file

@ -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")

View file

@ -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,