lightningd: setchannel can set ignorefeelimits.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `setchannel` adds a new `ignorefeelimits` parameter to allow peer to set arbitrary commitment transaction fees on a per-channel basis.
This commit is contained in:
Rusty Russell
2023-07-21 16:49:22 +09:30
parent f8d50fb690
commit b529e79621
15 changed files with 97 additions and 38 deletions

View File

@@ -1402,6 +1402,7 @@
"SetChannel.channels[].channel_id": 2, "SetChannel.channels[].channel_id": 2,
"SetChannel.channels[].fee_base_msat": 4, "SetChannel.channels[].fee_base_msat": 4,
"SetChannel.channels[].fee_proportional_millionths": 5, "SetChannel.channels[].fee_proportional_millionths": 5,
"SetChannel.channels[].ignore_fee_limits": 10,
"SetChannel.channels[].maximum_htlc_out_msat": 8, "SetChannel.channels[].maximum_htlc_out_msat": 8,
"SetChannel.channels[].minimum_htlc_out_msat": 6, "SetChannel.channels[].minimum_htlc_out_msat": 6,
"SetChannel.channels[].peer_id": 1, "SetChannel.channels[].peer_id": 1,
@@ -1415,7 +1416,8 @@
"SetChannel.feeppm": 3, "SetChannel.feeppm": 3,
"SetChannel.htlcmax": 5, "SetChannel.htlcmax": 5,
"SetChannel.htlcmin": 4, "SetChannel.htlcmin": 4,
"SetChannel.id": 1 "SetChannel.id": 1,
"SetChannel.ignorefeelimits": 7
}, },
"SetchannelResponse": { "SetchannelResponse": {
"SetChannel.channels[]": 1 "SetChannel.channels[]": 1
@@ -5018,6 +5020,10 @@
"added": "pre-v0.10.1", "added": "pre-v0.10.1",
"deprecated": false "deprecated": false
}, },
"SetChannel.channels[].ignore_fee_limits": {
"added": "v23.08",
"deprecated": false
},
"SetChannel.channels[].maximum_htlc_out_msat": { "SetChannel.channels[].maximum_htlc_out_msat": {
"added": "pre-v0.10.1", "added": "pre-v0.10.1",
"deprecated": false "deprecated": false
@@ -5066,6 +5072,10 @@
"added": "pre-v0.10.1", "added": "pre-v0.10.1",
"deprecated": false "deprecated": false
}, },
"SetChannel.ignorefeelimits": {
"added": "v23.08",
"deprecated": false
},
"SignInvoice": { "SignInvoice": {
"added": "v23.02", "added": "v23.02",
"deprecated": null "deprecated": null

View File

@@ -1639,6 +1639,7 @@ message SetchannelRequest {
optional Amount htlcmin = 4; optional Amount htlcmin = 4;
optional Amount htlcmax = 5; optional Amount htlcmax = 5;
optional uint32 enforcedelay = 6; optional uint32 enforcedelay = 6;
optional bool ignorefeelimits = 7;
} }
message SetchannelResponse { message SetchannelResponse {
@@ -1651,6 +1652,7 @@ message SetchannelChannels {
optional string short_channel_id = 3; optional string short_channel_id = 3;
Amount fee_base_msat = 4; Amount fee_base_msat = 4;
uint32 fee_proportional_millionths = 5; uint32 fee_proportional_millionths = 5;
optional bool ignore_fee_limits = 10;
Amount minimum_htlc_out_msat = 6; Amount minimum_htlc_out_msat = 6;
optional string warning_htlcmin_too_low = 7; optional string warning_htlcmin_too_low = 7;
Amount maximum_htlc_out_msat = 8; Amount maximum_htlc_out_msat = 8;

View File

@@ -1521,6 +1521,7 @@ impl From<responses::SetchannelChannels> for pb::SetchannelChannels {
short_channel_id: c.short_channel_id.map(|v| v.to_string()), // Rule #2 for type short_channel_id? short_channel_id: c.short_channel_id.map(|v| v.to_string()), // Rule #2 for type short_channel_id?
fee_base_msat: Some(c.fee_base_msat.into()), // Rule #2 for type msat fee_base_msat: Some(c.fee_base_msat.into()), // Rule #2 for type msat
fee_proportional_millionths: c.fee_proportional_millionths, // Rule #2 for type u32 fee_proportional_millionths: c.fee_proportional_millionths, // Rule #2 for type u32
ignore_fee_limits: c.ignore_fee_limits, // Rule #2 for type boolean?
minimum_htlc_out_msat: Some(c.minimum_htlc_out_msat.into()), // Rule #2 for type msat minimum_htlc_out_msat: Some(c.minimum_htlc_out_msat.into()), // Rule #2 for type msat
warning_htlcmin_too_low: c.warning_htlcmin_too_low, // Rule #2 for type string? warning_htlcmin_too_low: c.warning_htlcmin_too_low, // Rule #2 for type string?
maximum_htlc_out_msat: Some(c.maximum_htlc_out_msat.into()), // Rule #2 for type msat maximum_htlc_out_msat: Some(c.maximum_htlc_out_msat.into()), // Rule #2 for type msat
@@ -2214,6 +2215,7 @@ impl From<requests::SetchannelRequest> for pb::SetchannelRequest {
htlcmin: c.htlcmin.map(|f| f.into()), // Rule #2 for type msat? htlcmin: c.htlcmin.map(|f| f.into()), // Rule #2 for type msat?
htlcmax: c.htlcmax.map(|f| f.into()), // Rule #2 for type msat? htlcmax: c.htlcmax.map(|f| f.into()), // Rule #2 for type msat?
enforcedelay: c.enforcedelay, // Rule #2 for type u32? enforcedelay: c.enforcedelay, // Rule #2 for type u32?
ignorefeelimits: c.ignorefeelimits, // Rule #2 for type boolean?
} }
} }
} }
@@ -2880,6 +2882,7 @@ impl From<pb::SetchannelRequest> for requests::SetchannelRequest {
htlcmin: c.htlcmin.map(|a| a.into()), // Rule #1 for type msat? htlcmin: c.htlcmin.map(|a| a.into()), // Rule #1 for type msat?
htlcmax: c.htlcmax.map(|a| a.into()), // Rule #1 for type msat? htlcmax: c.htlcmax.map(|a| a.into()), // Rule #1 for type msat?
enforcedelay: c.enforcedelay, // Rule #1 for type u32? enforcedelay: c.enforcedelay, // Rule #1 for type u32?
ignorefeelimits: c.ignorefeelimits, // Rule #1 for type boolean?
} }
} }
} }

4
cln-rpc/src/model.rs generated
View File

@@ -1409,6 +1409,8 @@ pub mod requests {
pub htlcmax: Option<Amount>, pub htlcmax: Option<Amount>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub enforcedelay: Option<u32>, pub enforcedelay: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ignorefeelimits: Option<bool>,
} }
impl From<SetchannelRequest> for Request { impl From<SetchannelRequest> for Request {
@@ -4651,6 +4653,8 @@ pub mod responses {
pub short_channel_id: Option<ShortChannelId>, pub short_channel_id: Option<ShortChannelId>,
pub fee_base_msat: Amount, pub fee_base_msat: Amount,
pub fee_proportional_millionths: u32, pub fee_proportional_millionths: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub ignore_fee_limits: Option<bool>,
pub minimum_htlc_out_msat: Amount, pub minimum_htlc_out_msat: Amount,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub warning_htlcmin_too_low: Option<String>, pub warning_htlcmin_too_low: Option<String>,

File diff suppressed because one or more lines are too long

View File

@@ -1298,6 +1298,7 @@ def setchannel_channels2py(m):
"short_channel_id": m.short_channel_id, # PrimitiveField in generate_composite "short_channel_id": m.short_channel_id, # PrimitiveField in generate_composite
"fee_base_msat": amount2msat(m.fee_base_msat), # PrimitiveField in generate_composite "fee_base_msat": amount2msat(m.fee_base_msat), # PrimitiveField in generate_composite
"fee_proportional_millionths": m.fee_proportional_millionths, # PrimitiveField in generate_composite "fee_proportional_millionths": m.fee_proportional_millionths, # PrimitiveField in generate_composite
"ignore_fee_limits": m.ignore_fee_limits, # PrimitiveField in generate_composite
"minimum_htlc_out_msat": amount2msat(m.minimum_htlc_out_msat), # PrimitiveField in generate_composite "minimum_htlc_out_msat": amount2msat(m.minimum_htlc_out_msat), # PrimitiveField in generate_composite
"warning_htlcmin_too_low": m.warning_htlcmin_too_low, # PrimitiveField in generate_composite "warning_htlcmin_too_low": m.warning_htlcmin_too_low, # PrimitiveField in generate_composite
"maximum_htlc_out_msat": amount2msat(m.maximum_htlc_out_msat), # PrimitiveField in generate_composite "maximum_htlc_out_msat": amount2msat(m.maximum_htlc_out_msat), # PrimitiveField in generate_composite

View File

@@ -4,7 +4,7 @@ lightning-setchannel -- Command for configuring fees / htlc range advertized for
SYNOPSIS SYNOPSIS
-------- --------
**setchannel** *id* [*feebase*] [*feeppm*] [*htlcmin*] [*htlcmax*] [*enforcedelay*] **setchannel** *id* [*feebase*] [*feeppm*] [*htlcmin*] [*htlcmax*] [*enforcedelay*] [*ignorefeelimits*]
DESCRIPTION DESCRIPTION
----------- -----------
@@ -62,6 +62,13 @@ only applied to a single rate increase per channel (we don't remember
an arbitrary number of prior feerates) and if the node is restarted an arbitrary number of prior feerates) and if the node is restarted
the updated configuration is enforced immediately. the updated configuration is enforced immediately.
*ignorefeelimits* 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).
RETURN VALUE RETURN VALUE
------------ ------------
@@ -72,6 +79,7 @@ On success, an object containing **channels** is returned. It is an array of ob
- **channel\_id** (hex): The channel\_id of the channel (always 64 characters) - **channel\_id** (hex): The channel\_id of the channel (always 64 characters)
- **fee\_base\_msat** (msat): The resulting feebase (this is the BOLT #7 name) - **fee\_base\_msat** (msat): The resulting feebase (this is the BOLT #7 name)
- **fee\_proportional\_millionths** (u32): The resulting feeppm (this is the BOLT #7 name) - **fee\_proportional\_millionths** (u32): The resulting feeppm (this is the BOLT #7 name)
- **ignore\_fee\_limits** (boolean): If we are now allowing peer to set feerate on commitment transaction without restriction *(added v23.08)*
- **minimum\_htlc\_out\_msat** (msat): The resulting htlcmin we will advertize (the BOLT #7 name is htlc\_minimum\_msat) - **minimum\_htlc\_out\_msat** (msat): The resulting htlcmin we will advertize (the BOLT #7 name is htlc\_minimum\_msat)
- **maximum\_htlc\_out\_msat** (msat): The resulting htlcmax we will advertize (the BOLT #7 name is htlc\_maximum\_msat) - **maximum\_htlc\_out\_msat** (msat): The resulting htlcmax we will advertize (the BOLT #7 name is htlc\_maximum\_msat)
- **short\_channel\_id** (short\_channel\_id, optional): the short\_channel\_id (if locked in) - **short\_channel\_id** (short\_channel\_id, optional): the short\_channel\_id (if locked in)
@@ -107,4 +115,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning> Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:0175aaf74aa6d75640d0b79f68b552b1b700f93ad7576465c73de93af04d71e6) [comment]: # ( SHA256STAMP:5209ba4d4bbe2d897d9824f95a97fa48d968e83ffec2e4cfbd87df6fd90c48f0)

View File

@@ -332,7 +332,8 @@ falls below this.
Allow nodes which establish channels to us to set any fee they want. Allow nodes which establish channels to us to set any fee they want.
This may result in a channel which cannot be closed, should fees This may result in a channel which cannot be closed, should fees
increase, but make channels far more reliable since we never close it increase, but make channels far more reliable since we never close it
due to unreasonable fees. due to unreasonable fees. Note that this can be set on a per-channel
basis with lightning-setchannel(7).
* **commit-time**=*MILLISECONDS* * **commit-time**=*MILLISECONDS*

View File

@@ -23,6 +23,10 @@
}, },
"enforcedelay": { "enforcedelay": {
"type": "u32" "type": "u32"
},
"ignorefeelimits": {
"added": "v23.08",
"type": "boolean"
} }
} }
} }

View File

@@ -18,7 +18,8 @@
"fee_base_msat", "fee_base_msat",
"fee_proportional_millionths", "fee_proportional_millionths",
"minimum_htlc_out_msat", "minimum_htlc_out_msat",
"maximum_htlc_out_msat" "maximum_htlc_out_msat",
"ignore_fee_limits"
], ],
"properties": { "properties": {
"peer_id": { "peer_id": {
@@ -43,6 +44,11 @@
"type": "u32", "type": "u32",
"description": "The resulting feeppm (this is the BOLT #7 name)" "description": "The resulting feeppm (this is the BOLT #7 name)"
}, },
"ignore_fee_limits": {
"type": "boolean",
"added": "v23.08",
"description": "If we are now allowing peer to set feerate on commitment transaction without restriction"
},
"minimum_htlc_out_msat": { "minimum_htlc_out_msat": {
"type": "msat", "type": "msat",
"description": "The resulting htlcmin we will advertize (the BOLT #7 name is htlc_minimum_msat)" "description": "The resulting htlcmin we will advertize (the BOLT #7 name is htlc_minimum_msat)"

View File

@@ -24,7 +24,7 @@
#include <lightningd/peer_fd.h> #include <lightningd/peer_fd.h>
#include <wally_bip32.h> #include <wally_bip32.h>
static void update_feerates(struct lightningd *ld, const struct channel *channel) void channel_update_feerates(struct lightningd *ld, const struct channel *channel)
{ {
u8 *msg; u8 *msg;
u32 min_feerate, max_feerate; u32 min_feerate, max_feerate;
@@ -71,7 +71,7 @@ static void try_update_feerates(struct lightningd *ld, struct channel *channel)
if (!channel->owner) if (!channel->owner)
return; return;
update_feerates(ld, channel); channel_update_feerates(ld, channel);
} }
static void try_update_blockheight(struct lightningd *ld, static void try_update_blockheight(struct lightningd *ld,

View File

@@ -43,4 +43,6 @@ void channel_fallen_behind(struct channel *channel, const u8 *msg);
/* Fresh channel_update for this channel. */ /* Fresh channel_update for this channel. */
void channel_replace_update(struct channel *channel, u8 *update TAKES); void channel_replace_update(struct channel *channel, u8 *update TAKES);
/* Tell channel about new feerates (owner must be channeld!) */
void channel_update_feerates(struct lightningd *ld, const struct channel *channel);
#endif /* LIGHTNING_LIGHTNINGD_CHANNEL_CONTROL_H */ #endif /* LIGHTNING_LIGHTNINGD_CHANNEL_CONTROL_H */

View File

@@ -2686,6 +2686,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
struct amount_msat *htlc_min, struct amount_msat *htlc_min,
struct amount_msat *htlc_max, struct amount_msat *htlc_max,
u32 delaysecs, u32 delaysecs,
bool *ignore_fee_limits,
struct json_stream *response) struct json_stream *response)
{ {
bool warn_cannot_set_min = false, warn_cannot_set_max = false; bool warn_cannot_set_min = false, warn_cannot_set_max = false;
@@ -2733,12 +2734,18 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
} else } else
channel->htlc_maximum_msat = *htlc_max; channel->htlc_maximum_msat = *htlc_max;
} }
if (ignore_fee_limits)
channel->ignore_fee_limits = *ignore_fee_limits;
/* tell channeld to make a send_channel_update */ /* tell channeld to make a send_channel_update */
if (channel->owner && streq(channel->owner->name, "channeld")) if (channel->owner && streq(channel->owner->name, "channeld")) {
subd_send_msg(channel->owner, subd_send_msg(channel->owner,
take(towire_channeld_config_channel(NULL, base, ppm, take(towire_channeld_config_channel(NULL, base, ppm,
htlc_min, htlc_max))); htlc_min, htlc_max)));
/* Tell it about the new acceptable feerates */
if (ignore_fee_limits)
channel_update_feerates(cmd->ld, channel);
}
/* save values to database */ /* save values to database */
wallet_channel_save(cmd->ld->wallet, channel); wallet_channel_save(cmd->ld->wallet, channel);
@@ -2764,6 +2771,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
json_add_amount_msat(response, json_add_amount_msat(response,
"maximum_htlc_out_msat", "maximum_htlc_out_msat",
channel->htlc_maximum_msat); channel->htlc_maximum_msat);
json_add_bool(response, "ignore_fee_limits", channel->ignore_fee_limits);
if (warn_cannot_set_max) if (warn_cannot_set_max)
json_add_string(response, "warning_htlcmax_too_high", json_add_string(response, "warning_htlcmax_too_high",
"Set maximum_htlc_out_msat to maximum possible in channel"); "Set maximum_htlc_out_msat to maximum possible in channel");
@@ -2780,6 +2788,7 @@ static struct command_result *json_setchannel(struct command *cmd,
struct channel **channels; struct channel **channels;
u32 *base, *ppm, *delaysecs; u32 *base, *ppm, *delaysecs;
struct amount_msat *htlc_min, *htlc_max; struct amount_msat *htlc_min, *htlc_max;
bool *ignore_fee_limits;
/* Parse the JSON command */ /* Parse the JSON command */
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
@@ -2789,6 +2798,7 @@ static struct command_result *json_setchannel(struct command *cmd,
p_opt("htlcmin", param_msat, &htlc_min), p_opt("htlcmin", param_msat, &htlc_min),
p_opt("htlcmax", param_msat, &htlc_max), p_opt("htlcmax", param_msat, &htlc_max),
p_opt_def("enforcedelay", param_number, &delaysecs, 600), p_opt_def("enforcedelay", param_number, &delaysecs, 600),
p_opt("ignorefeelimits", param_bool, &ignore_fee_limits),
NULL)) NULL))
return command_param_failed(); return command_param_failed();
@@ -2818,7 +2828,8 @@ static struct command_result *json_setchannel(struct command *cmd,
continue; continue;
set_channel_config(cmd, channel, base, ppm, set_channel_config(cmd, channel, base, ppm,
htlc_min, htlc_max, htlc_min, htlc_max,
*delaysecs, response); *delaysecs, ignore_fee_limits,
response);
} }
} }
/* single peer should be updated */ /* single peer should be updated */
@@ -2826,7 +2837,8 @@ static struct command_result *json_setchannel(struct command *cmd,
for (size_t i = 0; i < tal_count(channels); i++) { for (size_t i = 0; i < tal_count(channels); i++) {
set_channel_config(cmd, channels[i], base, ppm, set_channel_config(cmd, channels[i], base, ppm,
htlc_min, htlc_max, htlc_min, htlc_max,
*delaysecs, response); *delaysecs, ignore_fee_limits,
response);
} }
} }

View File

@@ -124,6 +124,9 @@ const char **channel_type_name(const tal_t *ctx UNNEEDED, const struct channel_t
/* Generated stub for channel_unsaved_close_conn */ /* Generated stub for channel_unsaved_close_conn */
void channel_unsaved_close_conn(struct channel *channel UNNEEDED, const char *why UNNEEDED) void channel_unsaved_close_conn(struct channel *channel UNNEEDED, const char *why UNNEEDED)
{ fprintf(stderr, "channel_unsaved_close_conn called!\n"); abort(); } { fprintf(stderr, "channel_unsaved_close_conn called!\n"); abort(); }
/* Generated stub for channel_update_feerates */
void channel_update_feerates(struct lightningd *ld UNNEEDED, const struct channel *channel UNNEEDED)
{ fprintf(stderr, "channel_update_feerates called!\n"); abort(); }
/* Generated stub for channel_update_reserve */ /* Generated stub for channel_update_reserve */
void channel_update_reserve(struct channel *channel UNNEEDED, void channel_update_reserve(struct channel *channel UNNEEDED,
struct channel_config *their_config UNNEEDED, struct channel_config *their_config UNNEEDED,

View File

@@ -81,6 +81,9 @@ bool channel_tell_depth(struct lightningd *ld UNNEEDED,
/* Generated stub for channel_unsaved_close_conn */ /* Generated stub for channel_unsaved_close_conn */
void channel_unsaved_close_conn(struct channel *channel UNNEEDED, const char *why UNNEEDED) void channel_unsaved_close_conn(struct channel *channel UNNEEDED, const char *why UNNEEDED)
{ fprintf(stderr, "channel_unsaved_close_conn called!\n"); abort(); } { fprintf(stderr, "channel_unsaved_close_conn called!\n"); abort(); }
/* Generated stub for channel_update_feerates */
void channel_update_feerates(struct lightningd *ld UNNEEDED, const struct channel *channel UNNEEDED)
{ fprintf(stderr, "channel_update_feerates called!\n"); abort(); }
/* Generated stub for channel_update_reserve */ /* Generated stub for channel_update_reserve */
void channel_update_reserve(struct channel *channel UNNEEDED, void channel_update_reserve(struct channel *channel UNNEEDED,
struct channel_config *their_config UNNEEDED, struct channel_config *their_config UNNEEDED,