Skip to content

Commit 5ae3369

Browse files
setchannel: allow upgrading private channels to public
Add an `announce` parameter to the `setchannel` RPC command that allows upgrading an existing private (unannounced) channel to a public (announced) channel. When set to true, the channel_flags are updated to set the CHANNEL_FLAGS_ANNOUNCE_CHANNEL bit, and the gossip state machine transitions from the private states into the public announcement flow. Both peers must independently set announce=true for the channel announcement to complete, as the protocol requires announcement signatures from both sides. To facilitate this, announcement_signatures received while a channel is still private are now stashed rather than rejected, so they are available immediately if/when the local side upgrades. State transitions added: - CGOSSIP_PRIVATE -> CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS - CGOSSIP_PRIVATE -> CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH - CGOSSIP_PRIVATE -> CGOSSIP_ANNOUNCED Setting announce=false (public to private) is rejected as this is not possible once a channel has been announced. Changelog-Added: `setchannel` now accepts an `announce` parameter to upgrade private channels to public. Fixes #7438
1 parent 199ecd2 commit 5ae3369

5 files changed

Lines changed: 89 additions & 17 deletions

File tree

.msggen.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4011,7 +4011,8 @@
40114011
"SetChannel.channels[].peer_id": 1,
40124012
"SetChannel.channels[].short_channel_id": 3,
40134013
"SetChannel.channels[].warning_htlcmax_too_high": 9,
4014-
"SetChannel.channels[].warning_htlcmin_too_low": 7
4014+
"SetChannel.channels[].warning_htlcmin_too_low": 7,
4015+
"SetChannel.channels[].announce": 11
40154016
},
40164017
"SetchannelRequest": {
40174018
"SetChannel.enforcedelay": 6,
@@ -4020,7 +4021,8 @@
40204021
"SetChannel.htlcmax": 5,
40214022
"SetChannel.htlcmin": 4,
40224023
"SetChannel.id": 1,
4023-
"SetChannel.ignorefeelimits": 7
4024+
"SetChannel.ignorefeelimits": 7,
4025+
"SetChannel.announce": 8
40244026
},
40254027
"SetchannelResponse": {
40264028
"SetChannel.channels[]": 1
@@ -13561,6 +13563,10 @@
1356113563
"added": "pre-v0.10.1",
1356213564
"deprecated": null
1356313565
},
13566+
"SetChannel.channels[].announce": {
13567+
"added": "v25.05",
13568+
"deprecated": null
13569+
},
1356413570
"SetChannel.enforcedelay": {
1356513571
"added": "pre-v0.10.1",
1356613572
"deprecated": null
@@ -13589,6 +13595,10 @@
1358913595
"added": "v23.08",
1359013596
"deprecated": null
1359113597
},
13598+
"SetChannel.announce": {
13599+
"added": "v25.05",
13600+
"deprecated": null
13601+
},
1359213602
"SetConfig": {
1359313603
"added": "v23.08",
1359413604
"deprecated": null

doc/schemas/setchannel.json

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"$schema": "../rpc-schema-draft.json",
33
"type": "object",
44
"rpc": "setchannel",
5-
"title": "Command for configuring fees / htlc range advertized for a channel",
5+
"title": "Command for configuring fees / htlc range advertized for a channel, and upgrading private channels to public",
66
"description": [
7-
"The **setchannel** RPC command sets channel specific routing fees, and `htlc_minimum_msat` or `htlc_maximum_msat` as defined in BOLT #7. The channel has to be in normal or awaiting state. This can be checked by **listpeers** reporting a *state* of CHANNELD_NORMAL or CHANNELD_AWAITING_LOCKIN for the channel.",
7+
"The **setchannel** RPC command sets channel specific routing fees, and `htlc_minimum_msat` or `htlc_maximum_msat` as defined in BOLT #7. It can also upgrade a private (unannounced) channel to a public (announced) channel using the *announce* parameter. The channel has to be in normal or awaiting state. This can be checked by **listpeers** reporting a *state* of CHANNELD_NORMAL or CHANNELD_AWAITING_LOCKIN for the channel.",
88
"",
99
"These changes (for a public channel) will be broadcast to the rest of the network (though many nodes limit the rate of such changes they will accept: we allow 2 a day, with a few extra occasionally)."
1010
],
@@ -59,6 +59,13 @@
5959
"description": [
6060
"If set to True means to allow the peer to set the commitment transaction fees (or closing transaction fees) to any value they want. This is dangerous: they could set an exorbitant fee (so HTLCs are unenforcable), or a tiny fee (so that commitment transactions cannot be relayed), but avoids channel breakage in case of feerate disagreements. (Note: the global `ignore_fee_limits` setting overrides this)."
6161
]
62+
},
63+
"announce": {
64+
"added": "v25.05",
65+
"type": "boolean",
66+
"description": [
67+
"If set to True, upgrades a private channel to a public channel. The channel will be announced to the network once both sides have exchanged announcement signatures and the funding transaction has at least 6 confirmations. Note: the peer must also independently set their side to public (e.g. via the same command) for the announcement to succeed. Cannot be set to false (public channels cannot be made private again)."
68+
]
6269
}
6370
}
6471
},
@@ -83,7 +90,8 @@
8390
"fee_proportional_millionths",
8491
"minimum_htlc_out_msat",
8592
"maximum_htlc_out_msat",
86-
"ignore_fee_limits"
93+
"ignore_fee_limits",
94+
"announce"
8795
],
8896
"properties": {
8997
"peer_id": {
@@ -146,6 +154,13 @@
146154
"description": [
147155
"The requested htlcmax was greater than the channel capacity, so we set it to the channel capacity."
148156
]
157+
},
158+
"announce": {
159+
"type": "boolean",
160+
"added": "v25.05",
161+
"description": [
162+
"Whether the channel is set to be announced to the network."
163+
]
149164
}
150165
}
151166
}
@@ -190,7 +205,8 @@
190205
"fee_proportional_millionths": 10,
191206
"minimum_htlc_out_msat": 0,
192207
"maximum_htlc_out_msat": 990000000,
193-
"ignore_fee_limits": true
208+
"ignore_fee_limits": true,
209+
"announce": true
194210
}
195211
]
196212
}
@@ -216,7 +232,8 @@
216232
"fee_proportional_millionths": 300,
217233
"minimum_htlc_out_msat": 0,
218234
"maximum_htlc_out_msat": 990000000,
219-
"ignore_fee_limits": false
235+
"ignore_fee_limits": false,
236+
"announce": true
220237
}
221238
]
222239
}

lightningd/channel_gossip.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,14 @@ static struct state_transition allowed_transitions[] = {
146146
"Channel closed before 6 confirms, but now has 6 confirms so could be announced." },
147147
{ CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, CGOSSIP_CHANNEL_ANNOUNCED_DYING,
148148
"Channel hit announced depth, but closed" },
149+
150+
/* Private to public upgrade */
151+
{ CGOSSIP_PRIVATE, CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS,
152+
"Private channel upgraded to public, waiting for peer announcement sigs" },
153+
{ CGOSSIP_PRIVATE, CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH,
154+
"Private channel upgraded to public, already have peer sigs" },
155+
{ CGOSSIP_PRIVATE, CGOSSIP_ANNOUNCED,
156+
"Private channel upgraded to public, already at announce depth" },
149157
};
150158

151159
static void check_state_transition(const struct channel *channel,
@@ -285,14 +293,14 @@ static void check_channel_gossip(const struct channel *channel)
285293
assert(is_private(channel));
286294
assert(!is_dead(channel));
287295
assert(!is_usable(channel));
288-
assert(!cg->remote_sigs);
296+
/* remote_sigs may be stashed if peer upgraded their side first */
289297
assert(!cg->refresh_timer);
290298
return;
291299
case CGOSSIP_PRIVATE:
292300
assert(is_private(channel));
293301
assert(!is_dead(channel));
294302
assert(is_usable(channel));
295-
assert(!cg->remote_sigs);
303+
/* remote_sigs may be stashed if peer upgraded their side first */
296304
assert(!cg->refresh_timer);
297305
return;
298306
case CGOSSIP_WAITING_FOR_USABLE:
@@ -971,6 +979,22 @@ void channel_gossip_update(struct channel *channel)
971979
update_gossip_state(channel);
972980
}
973981

982+
/* Upgrade a private channel to public (announce it on the network) */
983+
void channel_gossip_set_announce(struct channel *channel)
984+
{
985+
struct channel_gossip *cg = channel->channel_gossip;
986+
987+
/* Ignore unsaved channels */
988+
if (!cg)
989+
return;
990+
991+
/* Clear any cached private update, we'll need a new one! */
992+
cg->cupdate = tal_free(cg->cupdate);
993+
994+
/* Re-derive and transition gossip state now that flag is set */
995+
update_gossip_state(channel);
996+
}
997+
974998
void channel_gossip_got_announcement_sigs(struct channel *channel,
975999
struct short_channel_id scid,
9761000
const secp256k1_ecdsa_signature *node_sig,
@@ -991,11 +1015,10 @@ void channel_gossip_got_announcement_sigs(struct channel *channel,
9911015
return;
9921016
case CGOSSIP_PRIVATE_WAITING_FOR_USABLE:
9931017
case CGOSSIP_PRIVATE:
994-
log_unusual(channel->log, "They sent an announcement_signatures message for a private channel? Ignoring.");
995-
u8 *warning = towire_warningfmt(NULL,
996-
&channel->cid,
997-
"You sent announcement_signatures for private channel");
998-
msg_to_peer(channel->peer, take(warning));
1018+
/* Peer may have upgraded their side to public already.
1019+
* Stash sigs so if we also upgrade, we have them ready. */
1020+
log_info(channel->log, "Stashing announcement_signatures from peer for private channel (in case we upgrade to public)");
1021+
stash_remote_announce_sigs(channel, scid, node_sig, bitcoin_sig);
9991022
return;
10001023
case CGOSSIP_WAITING_FOR_USABLE:
10011024
case CGOSSIP_WAITING_FOR_SCID:

lightningd/channel_gossip.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ void channel_gossip_startup_done(struct lightningd *ld);
1919
/* Something about channel/blockchain changed: update if required */
2020
void channel_gossip_update(struct channel *channel);
2121

22+
/* Upgrade a private channel to public (announce it on the network) */
23+
void channel_gossip_set_announce(struct channel *channel);
24+
2225
/* Short channel id changed (splice, or reorg). */
2326
void channel_gossip_scid_changed(struct channel *channel);
2427

lightningd/peer_control.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3358,6 +3358,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
33583358
struct amount_msat *htlc_max,
33593359
u32 delaysecs,
33603360
bool *ignore_fee_limits,
3361+
bool *announce,
33613362
struct json_stream *response)
33623363
{
33633364
bool warn_cannot_set_min = false, warn_cannot_set_max = false;
@@ -3408,6 +3409,11 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
34083409
if (ignore_fee_limits)
34093410
channel->ignore_fee_limits = *ignore_fee_limits;
34103411

3412+
/* Upgrade private channel to public */
3413+
if (announce && *announce) {
3414+
channel->channel_flags |= CHANNEL_FLAGS_ANNOUNCE_CHANNEL;
3415+
}
3416+
34113417
/* Tell channeld about the new acceptable feerates */
34123418
if (channel->owner
34133419
&& streq(channel->owner->name, "channeld")
@@ -3418,6 +3424,10 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
34183424
/* save values to database */
34193425
wallet_channel_save(cmd->ld->wallet, channel);
34203426

3427+
/* After saving, trigger gossip state update for announce change */
3428+
if (announce && *announce)
3429+
channel_gossip_set_announce(channel);
3430+
34213431
/* write JSON response entry */
34223432
json_object_start(response, NULL);
34233433
json_add_node_id(response, "peer_id", &channel->peer->id);
@@ -3444,6 +3454,8 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
34443454
if (warn_cannot_set_max)
34453455
json_add_string(response, "warning_htlcmax_too_high",
34463456
"Set maximum_htlc_out_msat to maximum possible in channel");
3457+
json_add_bool(response, "announce",
3458+
(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL) != 0);
34473459
json_object_end(response);
34483460
}
34493461

@@ -3457,7 +3469,7 @@ static struct command_result *json_setchannel(struct command *cmd,
34573469
struct channel **channels;
34583470
u32 *base, *ppm, *delaysecs;
34593471
struct amount_msat *htlc_min, *htlc_max;
3460-
bool *ignore_fee_limits;
3472+
bool *ignore_fee_limits, *announce;
34613473

34623474
/* Parse the JSON command */
34633475
if (!param_check(cmd, buffer, params,
@@ -3468,6 +3480,7 @@ static struct command_result *json_setchannel(struct command *cmd,
34683480
p_opt("htlcmax", param_msat, &htlc_max),
34693481
p_opt_def("enforcedelay", param_number, &delaysecs, 600),
34703482
p_opt("ignorefeelimits", param_bool, &ignore_fee_limits),
3483+
p_opt("announce", param_bool, &announce),
34713484
NULL))
34723485
return command_param_failed();
34733486

@@ -3478,6 +3491,12 @@ static struct command_result *json_setchannel(struct command *cmd,
34783491
"htlcmax cannot be less than htlcmin");
34793492
}
34803493

3494+
/* Cannot set announce=false (public to private is not possible) */
3495+
if (announce && !*announce) {
3496+
return command_fail(cmd, LIGHTNINGD,
3497+
"Cannot set a public channel back to private");
3498+
}
3499+
34813500
if (command_check_only(cmd))
34823501
return command_check_done(cmd);
34833502

@@ -3500,7 +3519,7 @@ static struct command_result *json_setchannel(struct command *cmd,
35003519
set_channel_config(cmd, channel, base, ppm,
35013520
htlc_min, htlc_max,
35023521
*delaysecs, ignore_fee_limits,
3503-
response);
3522+
announce, response);
35043523
}
35053524
}
35063525
/* single peer should be updated */
@@ -3509,7 +3528,7 @@ static struct command_result *json_setchannel(struct command *cmd,
35093528
set_channel_config(cmd, channels[i], base, ppm,
35103529
htlc_min, htlc_max,
35113530
*delaysecs, ignore_fee_limits,
3512-
response);
3531+
announce, response);
35133532
}
35143533
}
35153534

0 commit comments

Comments
 (0)