Skip to content

Commit bc299ce

Browse files
committed
channeld: handle upgrade match.
We don't actually set desired_type yet, but this handles it. Changelog-EXPERIMENTAL: Protocol: we can now upgrade old channels to `option_static_remotekey` from lightning/bolts#868 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 573438d commit bc299ce

File tree

7 files changed

+197
-3
lines changed

7 files changed

+197
-3
lines changed

channeld/channeld.c

+112-1
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,50 @@ static bool handle_master_request_later(struct peer *peer, const u8 *msg)
368368
}
369369
return false;
370370
}
371+
372+
static bool channel_type_eq(const struct channel_type *a,
373+
const struct channel_type *b)
374+
{
375+
return featurebits_eq(a->features, b->features);
376+
}
377+
378+
static bool match_type(const struct channel_type *desired,
379+
const struct channel_type *current,
380+
struct channel_type **upgradable)
381+
{
382+
/* Missing fields are possible. */
383+
if (!desired || !current)
384+
return false;
385+
386+
if (channel_type_eq(desired, current))
387+
return true;
388+
389+
for (size_t i = 0; i < tal_count(upgradable); i++) {
390+
if (channel_type_eq(desired, upgradable[i]))
391+
return true;
392+
}
393+
394+
return false;
395+
}
396+
397+
static void set_channel_type(struct channel *channel,
398+
const struct channel_type *type)
399+
{
400+
const struct channel_type *cur = channel_type(tmpctx, channel);
401+
402+
if (channel_type_eq(cur, type))
403+
return;
404+
405+
/* We only allow one upgrade at the moment, so that's it. */
406+
assert(!channel->option_static_remotekey);
407+
assert(feature_offered(type->features, OPT_STATIC_REMOTEKEY));
408+
409+
/* Do upgrade, tell master. */
410+
channel->option_static_remotekey = true;
411+
status_unusual("Upgraded channel to [%s]",
412+
fmt_featurebits(tmpctx, type->features));
413+
wire_sync_write(MASTER_FD, take(towire_channeld_upgraded(NULL, true)));
414+
}
371415
#else /* !EXPERIMENTAL_FEATURES */
372416
static bool handle_master_request_later(struct peer *peer, const u8 *msg)
373417
{
@@ -2499,7 +2543,8 @@ static void peer_reconnect(struct peer *peer,
24992543
&my_current_per_commitment_point, NULL);
25002544

25012545
#if EXPERIMENTAL_FEATURES
2502-
send_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx);
2546+
/* Subtle: we free tmpctx below as we loop, so tal off peer */
2547+
send_tlvs = tlv_channel_reestablish_tlvs_new(peer);
25032548
/* BOLT-upgrade_protocol #2:
25042549
* A node sending `channel_reestablish`, if it supports upgrading channels:
25052550
* - MUST set `next_to_send` the commitment number of the next
@@ -2797,6 +2842,71 @@ static void peer_reconnect(struct peer *peer,
27972842
fmt_featurebits(tmpctx,
27982843
recv_tlvs->upgradable[i]->features));
27992844
}
2845+
2846+
/* BOLT-upgrade_protocol #2:
2847+
*
2848+
* A node receiving `channel_reestablish`:
2849+
* - if it has to retransmit `commitment_signed` or `revoke_and_ack`:
2850+
* - MUST consider the channel feature change failed.
2851+
*/
2852+
if (retransmit_commitment_signed || retransmit_revoke_and_ack) {
2853+
status_debug("No upgrade: we retransmitted");
2854+
/* BOLT-upgrade_protocol #2:
2855+
*
2856+
* - if `next_to_send` is missing, or not equal to the
2857+
* `next_commitment_number` it sent:
2858+
* - MUST consider the channel feature change failed.
2859+
*/
2860+
} else if (!recv_tlvs->next_to_send) {
2861+
status_debug("No upgrade: no next_to_send received");
2862+
} else if (*recv_tlvs->next_to_send != peer->next_index[LOCAL]) {
2863+
status_debug("No upgrade: they're retransmitting");
2864+
/* BOLT-upgrade_protocol #2:
2865+
*
2866+
* - if updates are pending on either sides' commitment transaction:
2867+
* - MUST consider the channel feature change failed.
2868+
*/
2869+
/* Note that we can have HTLCs we *want* to add or remove
2870+
* but haven't yet: thats OK! */
2871+
} else if (pending_updates(peer->channel, LOCAL, true)
2872+
|| pending_updates(peer->channel, REMOTE, true)) {
2873+
status_debug("No upgrade: pending changes");
2874+
} else {
2875+
const struct tlv_channel_reestablish_tlvs *initr, *ninitr;
2876+
const struct channel_type *type;
2877+
2878+
if (peer->channel->opener == LOCAL) {
2879+
initr = send_tlvs;
2880+
ninitr = recv_tlvs;
2881+
} else {
2882+
initr = recv_tlvs;
2883+
ninitr = send_tlvs;
2884+
}
2885+
2886+
/* BOLT-upgrade_protocol #2:
2887+
*
2888+
* - if `desired_type` matches `current_type` or any
2889+
* `upgradable` `upgrades`:
2890+
* - MUST consider the channel type to be `desired_type`.
2891+
* - otherwise:
2892+
* - MUST consider the channel feature change failed.
2893+
* - if there is a `current_type` field:
2894+
* - MUST consider the channel type to be `current_type`.
2895+
*/
2896+
/* Note: returns NULL on missing fields, aka NULL */
2897+
if (match_type(initr->desired_type,
2898+
ninitr->current_type, ninitr->upgradable))
2899+
type = initr->desired_type;
2900+
else if (ninitr->current_type)
2901+
type = ninitr->current_type;
2902+
else
2903+
type = NULL;
2904+
2905+
if (type)
2906+
set_channel_type(peer->channel, type);
2907+
}
2908+
tal_free(send_tlvs);
2909+
28002910
#endif /* EXPERIMENTAL_FEATURES */
28012911

28022912
/* Corner case: we didn't send shutdown before because update_add_htlc
@@ -3246,6 +3356,7 @@ static void req_in(struct peer *peer, const u8 *msg)
32463356
case WIRE_CHANNELD_DEV_MEMLEAK_REPLY:
32473357
case WIRE_CHANNELD_SEND_ERROR_REPLY:
32483358
case WIRE_CHANNELD_DEV_QUIESCE_REPLY:
3359+
case WIRE_CHANNELD_UPGRADED:
32493360
break;
32503361
}
32513362

channeld/channeld_wire.csv

+4
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,7 @@ msgtype,channeld_send_error_reply,1108
221221
# Ask channeld to quiesce.
222222
msgtype,channeld_dev_quiesce,1009
223223
msgtype,channeld_dev_quiesce_reply,1109
224+
225+
# Tell master we're upgrading the commitment tx.
226+
msgtype,channeld_upgraded,1011
227+
msgdata,channeld_upgraded,option_static_remotekey,bool,

channeld/channeld_wiregen.c

+25-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

channeld/channeld_wiregen.h

+8-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/features.c

+14
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,20 @@ u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES)
476476
return result;
477477
}
478478

479+
bool featurebits_eq(const u8 *f1, const u8 *f2)
480+
{
481+
size_t len = tal_bytelen(f1);
482+
483+
if (tal_bytelen(f2) > len)
484+
len = tal_bytelen(f2);
485+
486+
for (size_t i = 0; i < len * 8; i++) {
487+
if (feature_is_set(f1, i) != feature_is_set(f2, i))
488+
return false;
489+
}
490+
return true;
491+
}
492+
479493
struct feature_set *fromwire_feature_set(const tal_t *ctx,
480494
const u8 **cursor, size_t *max)
481495
{

common/features.h

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ void set_feature_bit(u8 **ptr, u32 bit);
7171
/* Given two featurebit vectors, combine them by applying a logical OR. */
7272
u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES);
7373

74+
/* Are these two feature bitsets functionally equal (one may have
75+
* trailing zeroes)? */
76+
bool featurebits_eq(const u8 *f1, const u8 *f2);
77+
7478
/* Good for debugging: returns comma-separated string of bits. */
7579
const char *fmt_featurebits(const tal_t *ctx, const u8 *featurebits);
7680

lightningd/channel_control.c

+30
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,29 @@ void forget_channel(struct channel *channel, const char *why)
370370
forget(channel);
371371
}
372372

373+
#if EXPERIMENTAL_FEATURES
374+
static void handle_channel_upgrade(struct channel *channel,
375+
const u8 *msg)
376+
{
377+
bool option_static_remotekey;
378+
379+
if (!fromwire_channeld_upgraded(msg, &option_static_remotekey)) {
380+
channel_internal_error(channel, "bad handle_channel_upgrade: %s",
381+
tal_hex(tmpctx, msg));
382+
return;
383+
}
384+
385+
channel->static_remotekey_start[LOCAL] = channel->next_index[LOCAL];
386+
channel->static_remotekey_start[REMOTE] = channel->next_index[REMOTE];
387+
log_debug(channel->log,
388+
"option_static_remotekey enabled at %"PRIu64"/%"PRIu64,
389+
channel->static_remotekey_start[LOCAL],
390+
channel->static_remotekey_start[REMOTE]);
391+
392+
wallet_channel_save(channel->peer->ld->wallet, channel);
393+
}
394+
#endif /* EXPERIMENTAL_FEATURES */
395+
373396
static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
374397
{
375398
enum channeld_wire t = fromwire_peektype(msg);
@@ -405,6 +428,13 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
405428
case WIRE_CHANNELD_SEND_ERROR_REPLY:
406429
handle_error_channel(sd->channel, msg);
407430
break;
431+
#if EXPERIMENTAL_FEATURES
432+
case WIRE_CHANNELD_UPGRADED:
433+
handle_channel_upgrade(sd->channel, msg);
434+
break;
435+
#else
436+
case WIRE_CHANNELD_UPGRADED:
437+
#endif
408438
/* And we never get these from channeld. */
409439
case WIRE_CHANNELD_INIT:
410440
case WIRE_CHANNELD_FUNDING_DEPTH:

0 commit comments

Comments
 (0)