Skip to content

Commit bdbb292

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 376468f commit bdbb292

File tree

5 files changed

+89
-17
lines changed

5 files changed

+89
-17
lines changed

.msggen.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3727,7 +3727,8 @@
37273727
"SetChannel.channels[].peer_id": 1,
37283728
"SetChannel.channels[].short_channel_id": 3,
37293729
"SetChannel.channels[].warning_htlcmax_too_high": 9,
3730-
"SetChannel.channels[].warning_htlcmin_too_low": 7
3730+
"SetChannel.channels[].warning_htlcmin_too_low": 7,
3731+
"SetChannel.channels[].announce": 11
37313732
},
37323733
"SetchannelRequest": {
37333734
"SetChannel.enforcedelay": 6,
@@ -3736,7 +3737,8 @@
37363737
"SetChannel.htlcmax": 5,
37373738
"SetChannel.htlcmin": 4,
37383739
"SetChannel.id": 1,
3739-
"SetChannel.ignorefeelimits": 7
3740+
"SetChannel.ignorefeelimits": 7,
3741+
"SetChannel.announce": 8
37403742
},
37413743
"SetchannelResponse": {
37423744
"SetChannel.channels[]": 1
@@ -13134,6 +13136,10 @@
1313413136
"added": "pre-v0.10.1",
1313513137
"deprecated": null
1313613138
},
13139+
"SetChannel.channels[].announce": {
13140+
"added": "v25.05",
13141+
"deprecated": null
13142+
},
1313713143
"SetChannel.enforcedelay": {
1313813144
"added": "pre-v0.10.1",
1313913145
"deprecated": null
@@ -13162,6 +13168,10 @@
1316213168
"added": "v23.08",
1316313169
"deprecated": null
1316413170
},
13171+
"SetChannel.announce": {
13172+
"added": "v25.05",
13173+
"deprecated": null
13174+
},
1316513175
"SetConfig": {
1316613176
"added": "pre-v0.10.1",
1316713177
"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:
@@ -962,6 +970,22 @@ void channel_gossip_update(struct channel *channel)
962970
update_gossip_state(channel);
963971
}
964972

973+
/* Upgrade a private channel to public (announce it on the network) */
974+
void channel_gossip_set_announce(struct channel *channel)
975+
{
976+
struct channel_gossip *cg = channel->channel_gossip;
977+
978+
/* Ignore unsaved channels */
979+
if (!cg)
980+
return;
981+
982+
/* Clear any cached private update, we'll need a new one! */
983+
cg->cupdate = tal_free(cg->cupdate);
984+
985+
/* Re-derive and transition gossip state now that flag is set */
986+
update_gossip_state(channel);
987+
}
988+
965989
void channel_gossip_got_announcement_sigs(struct channel *channel,
966990
struct short_channel_id scid,
967991
const secp256k1_ecdsa_signature *node_sig,
@@ -982,11 +1006,10 @@ void channel_gossip_got_announcement_sigs(struct channel *channel,
9821006
return;
9831007
case CGOSSIP_PRIVATE_WAITING_FOR_USABLE:
9841008
case CGOSSIP_PRIVATE:
985-
log_unusual(channel->log, "They sent an announcement_signatures message for a private channel? Ignoring.");
986-
u8 *warning = towire_warningfmt(NULL,
987-
&channel->cid,
988-
"You sent announcement_signatures for private channel");
989-
msg_to_peer(channel->peer, take(warning));
1009+
/* Peer may have upgraded their side to public already.
1010+
* Stash sigs so if we also upgrade, we have them ready. */
1011+
log_info(channel->log, "Stashing announcement_signatures from peer for private channel (in case we upgrade to public)");
1012+
stash_remote_announce_sigs(channel, scid, node_sig, bitcoin_sig);
9901013
return;
9911014
case CGOSSIP_WAITING_FOR_USABLE:
9921015
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
@@ -3259,6 +3259,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
32593259
struct amount_msat *htlc_max,
32603260
u32 delaysecs,
32613261
bool *ignore_fee_limits,
3262+
bool *announce,
32623263
struct json_stream *response)
32633264
{
32643265
bool warn_cannot_set_min = false, warn_cannot_set_max = false;
@@ -3309,6 +3310,11 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
33093310
if (ignore_fee_limits)
33103311
channel->ignore_fee_limits = *ignore_fee_limits;
33113312

3313+
/* Upgrade private channel to public */
3314+
if (announce && *announce) {
3315+
channel->channel_flags |= CHANNEL_FLAGS_ANNOUNCE_CHANNEL;
3316+
}
3317+
33123318
/* Tell channeld about the new acceptable feerates */
33133319
if (channel->owner
33143320
&& streq(channel->owner->name, "channeld")
@@ -3319,6 +3325,10 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
33193325
/* save values to database */
33203326
wallet_channel_save(cmd->ld->wallet, channel);
33213327

3328+
/* After saving, trigger gossip state update for announce change */
3329+
if (announce && *announce)
3330+
channel_gossip_set_announce(channel);
3331+
33223332
/* write JSON response entry */
33233333
json_object_start(response, NULL);
33243334
json_add_node_id(response, "peer_id", &channel->peer->id);
@@ -3345,6 +3355,8 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
33453355
if (warn_cannot_set_max)
33463356
json_add_string(response, "warning_htlcmax_too_high",
33473357
"Set maximum_htlc_out_msat to maximum possible in channel");
3358+
json_add_bool(response, "announce",
3359+
(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL) != 0);
33483360
json_object_end(response);
33493361
}
33503362

@@ -3358,7 +3370,7 @@ static struct command_result *json_setchannel(struct command *cmd,
33583370
struct channel **channels;
33593371
u32 *base, *ppm, *delaysecs;
33603372
struct amount_msat *htlc_min, *htlc_max;
3361-
bool *ignore_fee_limits;
3373+
bool *ignore_fee_limits, *announce;
33623374

33633375
/* Parse the JSON command */
33643376
if (!param_check(cmd, buffer, params,
@@ -3369,6 +3381,7 @@ static struct command_result *json_setchannel(struct command *cmd,
33693381
p_opt("htlcmax", param_msat, &htlc_max),
33703382
p_opt_def("enforcedelay", param_number, &delaysecs, 600),
33713383
p_opt("ignorefeelimits", param_bool, &ignore_fee_limits),
3384+
p_opt("announce", param_bool, &announce),
33723385
NULL))
33733386
return command_param_failed();
33743387

@@ -3379,6 +3392,12 @@ static struct command_result *json_setchannel(struct command *cmd,
33793392
"htlcmax cannot be less than htlcmin");
33803393
}
33813394

3395+
/* Cannot set announce=false (public to private is not possible) */
3396+
if (announce && !*announce) {
3397+
return command_fail(cmd, LIGHTNINGD,
3398+
"Cannot set a public channel back to private");
3399+
}
3400+
33823401
if (command_check_only(cmd))
33833402
return command_check_done(cmd);
33843403

@@ -3401,7 +3420,7 @@ static struct command_result *json_setchannel(struct command *cmd,
34013420
set_channel_config(cmd, channel, base, ppm,
34023421
htlc_min, htlc_max,
34033422
*delaysecs, ignore_fee_limits,
3404-
response);
3423+
announce, response);
34053424
}
34063425
}
34073426
/* single peer should be updated */
@@ -3410,7 +3429,7 @@ static struct command_result *json_setchannel(struct command *cmd,
34103429
set_channel_config(cmd, channels[i], base, ppm,
34113430
htlc_min, htlc_max,
34123431
*delaysecs, ignore_fee_limits,
3413-
response);
3432+
announce, response);
34143433
}
34153434
}
34163435

0 commit comments

Comments
 (0)