diff --git a/.msggen.json b/.msggen.json index 534debac2ac8..9fe7d5ba3bb8 100644 --- a/.msggen.json +++ b/.msggen.json @@ -3727,7 +3727,8 @@ "SetChannel.channels[].peer_id": 1, "SetChannel.channels[].short_channel_id": 3, "SetChannel.channels[].warning_htlcmax_too_high": 9, - "SetChannel.channels[].warning_htlcmin_too_low": 7 + "SetChannel.channels[].warning_htlcmin_too_low": 7, + "SetChannel.channels[].announce": 11 }, "SetchannelRequest": { "SetChannel.enforcedelay": 6, @@ -3736,7 +3737,8 @@ "SetChannel.htlcmax": 5, "SetChannel.htlcmin": 4, "SetChannel.id": 1, - "SetChannel.ignorefeelimits": 7 + "SetChannel.ignorefeelimits": 7, + "SetChannel.announce": 8 }, "SetchannelResponse": { "SetChannel.channels[]": 1 @@ -13134,6 +13136,10 @@ "added": "pre-v0.10.1", "deprecated": null }, + "SetChannel.channels[].announce": { + "added": "v25.05", + "deprecated": null + }, "SetChannel.enforcedelay": { "added": "pre-v0.10.1", "deprecated": null @@ -13162,6 +13168,10 @@ "added": "v23.08", "deprecated": null }, + "SetChannel.announce": { + "added": "v25.05", + "deprecated": null + }, "SetConfig": { "added": "pre-v0.10.1", "deprecated": null diff --git a/doc/schemas/setchannel.json b/doc/schemas/setchannel.json index 64bf012b3fa4..58dfe2185879 100644 --- a/doc/schemas/setchannel.json +++ b/doc/schemas/setchannel.json @@ -2,9 +2,9 @@ "$schema": "../rpc-schema-draft.json", "type": "object", "rpc": "setchannel", - "title": "Command for configuring fees / htlc range advertized for a channel", + "title": "Command for configuring fees / htlc range advertized for a channel, and upgrading private channels to public", "description": [ - "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.", + "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.", "", "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)." ], @@ -59,6 +59,13 @@ "description": [ "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)." ] + }, + "announce": { + "added": "v25.05", + "type": "boolean", + "description": [ + "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)." + ] } } }, @@ -83,7 +90,8 @@ "fee_proportional_millionths", "minimum_htlc_out_msat", "maximum_htlc_out_msat", - "ignore_fee_limits" + "ignore_fee_limits", + "announce" ], "properties": { "peer_id": { @@ -146,6 +154,13 @@ "description": [ "The requested htlcmax was greater than the channel capacity, so we set it to the channel capacity." ] + }, + "announce": { + "type": "boolean", + "added": "v25.05", + "description": [ + "Whether the channel is set to be announced to the network." + ] } } } @@ -190,7 +205,8 @@ "fee_proportional_millionths": 10, "minimum_htlc_out_msat": 0, "maximum_htlc_out_msat": 990000000, - "ignore_fee_limits": true + "ignore_fee_limits": true, + "announce": true } ] } @@ -216,7 +232,8 @@ "fee_proportional_millionths": 300, "minimum_htlc_out_msat": 0, "maximum_htlc_out_msat": 990000000, - "ignore_fee_limits": false + "ignore_fee_limits": false, + "announce": true } ] } diff --git a/lightningd/channel_gossip.c b/lightningd/channel_gossip.c index 01207818a5d5..c4a5033565c0 100644 --- a/lightningd/channel_gossip.c +++ b/lightningd/channel_gossip.c @@ -146,6 +146,14 @@ static struct state_transition allowed_transitions[] = { "Channel closed before 6 confirms, but now has 6 confirms so could be announced." }, { CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, CGOSSIP_CHANNEL_ANNOUNCED_DYING, "Channel hit announced depth, but closed" }, + + /* Private to public upgrade */ + { CGOSSIP_PRIVATE, CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, + "Private channel upgraded to public, waiting for peer announcement sigs" }, + { CGOSSIP_PRIVATE, CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, + "Private channel upgraded to public, already have peer sigs" }, + { CGOSSIP_PRIVATE, CGOSSIP_ANNOUNCED, + "Private channel upgraded to public, already at announce depth" }, }; static void check_state_transition(const struct channel *channel, @@ -285,14 +293,14 @@ static void check_channel_gossip(const struct channel *channel) assert(is_private(channel)); assert(!is_dead(channel)); assert(!is_usable(channel)); - assert(!cg->remote_sigs); + /* remote_sigs may be stashed if peer upgraded their side first */ assert(!cg->refresh_timer); return; case CGOSSIP_PRIVATE: assert(is_private(channel)); assert(!is_dead(channel)); assert(is_usable(channel)); - assert(!cg->remote_sigs); + /* remote_sigs may be stashed if peer upgraded their side first */ assert(!cg->refresh_timer); return; case CGOSSIP_WAITING_FOR_USABLE: @@ -962,6 +970,22 @@ void channel_gossip_update(struct channel *channel) update_gossip_state(channel); } +/* Upgrade a private channel to public (announce it on the network) */ +void channel_gossip_set_announce(struct channel *channel) +{ + struct channel_gossip *cg = channel->channel_gossip; + + /* Ignore unsaved channels */ + if (!cg) + return; + + /* Clear any cached private update, we'll need a new one! */ + cg->cupdate = tal_free(cg->cupdate); + + /* Re-derive and transition gossip state now that flag is set */ + update_gossip_state(channel); +} + void channel_gossip_got_announcement_sigs(struct channel *channel, struct short_channel_id scid, const secp256k1_ecdsa_signature *node_sig, @@ -982,11 +1006,10 @@ void channel_gossip_got_announcement_sigs(struct channel *channel, return; case CGOSSIP_PRIVATE_WAITING_FOR_USABLE: case CGOSSIP_PRIVATE: - log_unusual(channel->log, "They sent an announcement_signatures message for a private channel? Ignoring."); - u8 *warning = towire_warningfmt(NULL, - &channel->cid, - "You sent announcement_signatures for private channel"); - msg_to_peer(channel->peer, take(warning)); + /* Peer may have upgraded their side to public already. + * Stash sigs so if we also upgrade, we have them ready. */ + log_info(channel->log, "Stashing announcement_signatures from peer for private channel (in case we upgrade to public)"); + stash_remote_announce_sigs(channel, scid, node_sig, bitcoin_sig); return; case CGOSSIP_WAITING_FOR_USABLE: case CGOSSIP_WAITING_FOR_SCID: diff --git a/lightningd/channel_gossip.h b/lightningd/channel_gossip.h index 6b8e4e203262..8068f32dce93 100644 --- a/lightningd/channel_gossip.h +++ b/lightningd/channel_gossip.h @@ -19,6 +19,9 @@ void channel_gossip_startup_done(struct lightningd *ld); /* Something about channel/blockchain changed: update if required */ void channel_gossip_update(struct channel *channel); +/* Upgrade a private channel to public (announce it on the network) */ +void channel_gossip_set_announce(struct channel *channel); + /* Short channel id changed (splice, or reorg). */ void channel_gossip_scid_changed(struct channel *channel); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index ab26bb75840c..2c4ca9d21232 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -3259,6 +3259,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel, struct amount_msat *htlc_max, u32 delaysecs, bool *ignore_fee_limits, + bool *announce, struct json_stream *response) { 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, if (ignore_fee_limits) channel->ignore_fee_limits = *ignore_fee_limits; + /* Upgrade private channel to public */ + if (announce && *announce) { + channel->channel_flags |= CHANNEL_FLAGS_ANNOUNCE_CHANNEL; + } + /* Tell channeld about the new acceptable feerates */ if (channel->owner && streq(channel->owner->name, "channeld") @@ -3319,6 +3325,10 @@ static void set_channel_config(struct command *cmd, struct channel *channel, /* save values to database */ wallet_channel_save(cmd->ld->wallet, channel); + /* After saving, trigger gossip state update for announce change */ + if (announce && *announce) + channel_gossip_set_announce(channel); + /* write JSON response entry */ json_object_start(response, NULL); 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, if (warn_cannot_set_max) json_add_string(response, "warning_htlcmax_too_high", "Set maximum_htlc_out_msat to maximum possible in channel"); + json_add_bool(response, "announce", + (channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL) != 0); json_object_end(response); } @@ -3358,7 +3370,7 @@ static struct command_result *json_setchannel(struct command *cmd, struct channel **channels; u32 *base, *ppm, *delaysecs; struct amount_msat *htlc_min, *htlc_max; - bool *ignore_fee_limits; + bool *ignore_fee_limits, *announce; /* Parse the JSON command */ if (!param_check(cmd, buffer, params, @@ -3369,6 +3381,7 @@ static struct command_result *json_setchannel(struct command *cmd, p_opt("htlcmax", param_msat, &htlc_max), p_opt_def("enforcedelay", param_number, &delaysecs, 600), p_opt("ignorefeelimits", param_bool, &ignore_fee_limits), + p_opt("announce", param_bool, &announce), NULL)) return command_param_failed(); @@ -3379,6 +3392,12 @@ static struct command_result *json_setchannel(struct command *cmd, "htlcmax cannot be less than htlcmin"); } + /* Cannot set announce=false (public to private is not possible) */ + if (announce && !*announce) { + return command_fail(cmd, LIGHTNINGD, + "Cannot set a public channel back to private"); + } + if (command_check_only(cmd)) return command_check_done(cmd); @@ -3401,7 +3420,7 @@ static struct command_result *json_setchannel(struct command *cmd, set_channel_config(cmd, channel, base, ppm, htlc_min, htlc_max, *delaysecs, ignore_fee_limits, - response); + announce, response); } } /* single peer should be updated */ @@ -3410,7 +3429,7 @@ static struct command_result *json_setchannel(struct command *cmd, set_channel_config(cmd, channels[i], base, ppm, htlc_min, htlc_max, *delaysecs, ignore_fee_limits, - response); + announce, response); } }