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

EXPERIMENTAL: channel upgrade support #4532

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
203 changes: 196 additions & 7 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ static void maybe_send_stfu(struct peer *peer)
if (!peer->stfu)
return;

if (!peer->stfu_sent[LOCAL] && !pending_updates(peer->channel, LOCAL)) {
if (!peer->stfu_sent[LOCAL] && !pending_updates(peer->channel, LOCAL, false)) {
u8 *msg = towire_stfu(NULL, &peer->channel_id,
peer->stfu_initiator == LOCAL);
sync_crypto_write(peer->pps, take(msg));
Expand Down Expand Up @@ -323,7 +323,7 @@ static void handle_stfu(struct peer *peer, const u8 *stfu)
}

/* Sanity check */
if (pending_updates(peer->channel, REMOTE))
if (pending_updates(peer->channel, REMOTE, false))
peer_failed_warn(peer->pps, &peer->channel_id,
"STFU but you still have updates pending?");

Expand Down Expand Up @@ -368,6 +368,50 @@ static bool handle_master_request_later(struct peer *peer, const u8 *msg)
}
return false;
}

static bool channel_type_eq(const struct channel_type *a,
const struct channel_type *b)
{
return featurebits_eq(a->features, b->features);
}

static bool match_type(const struct channel_type *desired,
const struct channel_type *current,
struct channel_type **upgradable)
{
/* Missing fields are possible. */
if (!desired || !current)
return false;

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

for (size_t i = 0; i < tal_count(upgradable); i++) {
if (channel_type_eq(desired, upgradable[i]))
return true;
}

return false;
}

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

if (channel_type_eq(cur, type))
return;

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

/* Do upgrade, tell master. */
channel->option_static_remotekey = true;
status_unusual("Upgraded channel to [%s]",
fmt_featurebits(tmpctx, type->features));
wire_sync_write(MASTER_FD, take(towire_channeld_upgraded(NULL, true)));
}
#else /* !EXPERIMENTAL_FEATURES */
static bool handle_master_request_later(struct peer *peer, const u8 *msg)
{
Expand Down Expand Up @@ -1141,7 +1185,7 @@ static void send_commit(struct peer *peer)
/* FIXME: We occasionally desynchronize with LND here, so
* don't stress things by having more than one feerate change
* in-flight! */
if (feerate_changes_done(peer->channel->fee_states)) {
if (feerate_changes_done(peer->channel->fee_states, false)) {
u8 *msg;

if (!channel_update_feerate(peer->channel, feerate_target))
Expand Down Expand Up @@ -1930,12 +1974,19 @@ static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg)
u64 next_revocation_number;
struct secret your_last_per_commitment_secret;
struct pubkey my_current_per_commitment_point;
#if EXPERIMENTAL_FEATURES
struct tlv_channel_reestablish_tlvs *tlvs = tlv_channel_reestablish_tlvs_new(tmpctx);
#endif

if (!fromwire_channel_reestablish(msg, &channel_id,
&next_commitment_number,
&next_revocation_number,
&your_last_per_commitment_secret,
&my_current_per_commitment_point))
&my_current_per_commitment_point
#if EXPERIMENTAL_FEATURES
, tlvs
#endif
))
peer_failed_warn(peer->pps, &peer->channel_id,
"Bad channel_reestablish %s", tal_hex(peer, msg));

Expand Down Expand Up @@ -2474,6 +2525,9 @@ static void peer_reconnect(struct peer *peer,
struct secret last_local_per_commitment_secret;
bool dataloss_protect, check_extra_fields;
const u8 **premature_msgs = tal_arr(peer, const u8 *, 0);
#if EXPERIMENTAL_FEATURES
struct tlv_channel_reestablish_tlvs *send_tlvs, *recv_tlvs;
#endif

dataloss_protect = feature_negotiated(peer->our_features,
peer->their_features,
Expand All @@ -2488,6 +2542,39 @@ static void peer_reconnect(struct peer *peer,
get_per_commitment_point(peer->next_index[LOCAL] - 1,
&my_current_per_commitment_point, NULL);

#if EXPERIMENTAL_FEATURES
/* Subtle: we free tmpctx below as we loop, so tal off peer */
send_tlvs = tlv_channel_reestablish_tlvs_new(peer);
/* 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
* `commitment_signed` it expects to send.
*/
send_tlvs->next_to_send = tal_dup(send_tlvs, u64, &peer->next_index[REMOTE]);

/* BOLT-upgrade_protocol #2:
* - if it initiated the channel:
* - MUST set `desired_type` to the channel_type it wants for the
* channel.
*/
if (peer->channel->opener == LOCAL)
send_tlvs->desired_type = channel_desired_type(send_tlvs,
peer->channel);
else {
/* BOLT-upgrade_protocol #2:
* - otherwise:
* - MUST set `current_type` to the current channel_type of the
* channel.
* - MUST set `upgradable` to the channel types it could change
* to.
* - 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

/* BOLT #2:
*
* - upon reconnection:
Expand Down Expand Up @@ -2525,14 +2612,22 @@ static void peer_reconnect(struct peer *peer,
peer->revocations_received,
last_remote_per_commit_secret,
/* Can send any (valid) point here */
&peer->remote_per_commit);
&peer->remote_per_commit
#if EXPERIMENTAL_FEATURES
, send_tlvs
#endif
);
} else {
msg = towire_channel_reestablish
(NULL, &peer->channel_id,
peer->next_index[LOCAL],
peer->revocations_received,
last_remote_per_commit_secret,
&my_current_per_commitment_point);
&my_current_per_commitment_point
#if EXPERIMENTAL_FEATURES
, send_tlvs
#endif
);
}

sync_crypto_write(peer->pps, take(msg));
Expand All @@ -2552,12 +2647,20 @@ static void peer_reconnect(struct peer *peer,
msg) ||
capture_premature_msg(&premature_msgs, msg));

#if EXPERIMENTAL_FEATURES
recv_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx);
#endif

if (!fromwire_channel_reestablish(msg,
&channel_id,
&next_commitment_number,
&next_revocation_number,
&last_local_per_commitment_secret,
&remote_current_per_commitment_point)) {
&remote_current_per_commitment_point
#if EXPERIMENTAL_FEATURES
, recv_tlvs
#endif
)) {
peer_failed_warn(peer->pps,
&peer->channel_id,
"bad reestablish msg: %s %s",
Expand Down Expand Up @@ -2725,6 +2828,88 @@ 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));
}

/* BOLT-upgrade_protocol #2:
*
* A node receiving `channel_reestablish`:
* - if it has to retransmit `commitment_signed` or `revoke_and_ack`:
* - MUST consider the channel feature change failed.
*/
if (retransmit_commitment_signed || retransmit_revoke_and_ack) {
status_debug("No upgrade: we retransmitted");
/* BOLT-upgrade_protocol #2:
*
* - if `next_to_send` is missing, or not equal to the
* `next_commitment_number` it sent:
* - MUST consider the channel feature change failed.
*/
} else if (!recv_tlvs->next_to_send) {
status_debug("No upgrade: no next_to_send received");
} else if (*recv_tlvs->next_to_send != peer->next_index[LOCAL]) {
status_debug("No upgrade: they're retransmitting");
/* BOLT-upgrade_protocol #2:
*
* - if updates are pending on either sides' commitment transaction:
* - MUST consider the channel feature change failed.
*/
/* Note that we can have HTLCs we *want* to add or remove
* but haven't yet: thats OK! */
} else if (pending_updates(peer->channel, LOCAL, true)
|| pending_updates(peer->channel, REMOTE, true)) {
status_debug("No upgrade: pending changes");
} else {
const struct tlv_channel_reestablish_tlvs *initr, *ninitr;
const struct channel_type *type;

if (peer->channel->opener == LOCAL) {
initr = send_tlvs;
ninitr = recv_tlvs;
} else {
initr = recv_tlvs;
ninitr = send_tlvs;
}

/* BOLT-upgrade_protocol #2:
*
* - if `desired_type` matches `current_type` or any
* `upgradable` `upgrades`:
* - MUST consider the channel type to be `desired_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`.
*/
/* 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;
else
type = NULL;

if (type)
set_channel_type(peer->channel, type);
}
tal_free(send_tlvs);

#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. */
Expand Down Expand Up @@ -3172,6 +3357,7 @@ static void req_in(struct peer *peer, const u8 *msg)
case WIRE_CHANNELD_DEV_MEMLEAK_REPLY:
case WIRE_CHANNELD_SEND_ERROR_REPLY:
case WIRE_CHANNELD_DEV_QUIESCE_REPLY:
case WIRE_CHANNELD_UPGRADED:
break;
}

Expand Down Expand Up @@ -3279,6 +3465,9 @@ static void init_channel(struct peer *peer)
master_badmsg(WIRE_CHANNELD_INIT, msg);
}

status_debug("option_static_remotekey = %u, option_anchor_outputs = %u",
option_static_remotekey, option_anchor_outputs);

/* Keeping an array of pointers is better since it allows us to avoid
* extra allocations later. */
peer->pbases = tal_arr(peer, struct penalty_base *, 0);
Expand Down
4 changes: 4 additions & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,7 @@ msgtype,channeld_send_error_reply,1108
# Ask channeld to quiesce.
msgtype,channeld_dev_quiesce,1009
msgtype,channeld_dev_quiesce_reply,1109

# Tell master we're upgrading the commitment tx.
msgtype,channeld_upgraded,1011
msgdata,channeld_upgraded,option_static_remotekey,bool,
26 changes: 25 additions & 1 deletion channeld/channeld_wiregen.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion channeld/channeld_wiregen.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading