diff --git a/channeld/channeld.c b/channeld/channeld.c index 93c1477ce..d453df252 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2524,6 +2524,8 @@ static void peer_reconnect(struct peer *peer, * - MAY not set `upgradable` if it would be empty. */ send_tlvs->current_type = channel_type(send_tlvs, peer->channel); + send_tlvs->upgradable = channel_upgradable_types(send_tlvs, + peer->channel); } #endif @@ -2780,6 +2782,23 @@ static void peer_reconnect(struct peer *peer, /* (If we had sent `closing_signed`, we'd be in closingd). */ maybe_send_shutdown(peer); +#if EXPERIMENTAL_FEATURES + if (recv_tlvs->desired_type) + status_debug("They sent desired_type [%s]", + fmt_featurebits(tmpctx, + recv_tlvs->desired_type->features)); + if (recv_tlvs->current_type) + status_debug("They sent current_type [%s]", + fmt_featurebits(tmpctx, + recv_tlvs->current_type->features)); + + for (size_t i = 0; i < tal_count(recv_tlvs->upgradable); i++) { + status_debug("They offered upgrade to [%s]", + fmt_featurebits(tmpctx, + recv_tlvs->upgradable[i]->features)); + } +#endif /* EXPERIMENTAL_FEATURES */ + /* Corner case: we didn't send shutdown before because update_add_htlc * pending, but now they're cleared by restart, and we're actually * complete. In that case, their `shutdown` will trigger us. */ diff --git a/common/initial_channel.c b/common/initial_channel.c index 9ca0da0df..e62f49d93 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -186,6 +186,17 @@ struct channel_type *channel_type(const tal_t *ctx, return new_channel_type(ctx); } + +struct channel_type **channel_upgradable_types(const tal_t *ctx, + const struct channel *channel) +{ + struct channel_type **arr = tal_arr(ctx, struct channel_type *, 0); + + if (!channel->option_static_remotekey) + tal_arr_expand(&arr, type_static_remotekey(arr)); + + return arr; +} #endif /* EXPERIMENTAL_FEATURES */ static char *fmt_channel_view(const tal_t *ctx, const struct channel_view *view) diff --git a/common/initial_channel.h b/common/initial_channel.h index 788c33f71..f756cd0b0 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -147,6 +147,10 @@ u32 channel_feerate(const struct channel *channel, enum side side); */ struct channel_type *channel_type(const tal_t *ctx, const struct channel *channel); + +/* What features can we upgrade? (Returns NULL if none). */ +struct channel_type **channel_upgradable_types(const tal_t *ctx, + const struct channel *channel); #endif /* EXPERIMENTAL_FEATURES */ #endif /* LIGHTNING_COMMON_INITIAL_CHANNEL_H */ diff --git a/tests/test_connection.py b/tests/test_connection.py index e2ede44df..89920f59d 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -3478,6 +3478,22 @@ def test_openchannel_init_alternate(node_factory, executor): print("nothing to do") +@unittest.skipIf(not EXPERIMENTAL_FEATURES, "upgrade protocol not available") +@pytest.mark.developer("dev-force-features required") +def test_upgrade_statickey(node_factory, executor): + """l1 doesn't have option_static_remotekey, l2 offers it.""" + l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, + 'dev-force-features': ["-13", "-21"]}, + {'may_reconnect': True}]) + + 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 \[\]", + r"They offered upgrade to \[13\]"]) + l2.daemon.wait_for_log(r"They sent desired_type \[\]") + + @unittest.skipIf(not EXPERIMENTAL_FEATURES, "quiescence is experimental") @pytest.mark.developer("quiescence triggering is dev only") def test_quiescence(node_factory, executor):