mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
lightningd: new setchannel command.
Based on setchannelfee, but expanded to allow setting max htlc amount (and others in future?). The main differences: 1. It doesn't change values which are not specified (that would be hard to add fields to!) 2. It says exactly what all values are in any potentially changed channels. Changelog-Added: JSON-RPC: new `setchannel` command generalizes `setchannelfee`. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
4fdcee9a11
commit
66e264d6b3
@ -1176,6 +1176,31 @@ class LightningRpc(UnixDomainSocketRpc):
|
||||
}
|
||||
return self.call("setchannelfee", payload)
|
||||
|
||||
def setchannel(self, id, feebase=None, feeppm=None, htlcmax=None, enforcedelay=None):
|
||||
"""Set configuration a channel/peer {id} (or 'all').
|
||||
|
||||
{feebase} is a value in millisatoshi that is added as base fee
|
||||
to any routed payment.
|
||||
|
||||
{feeppm} is a value added proportionally per-millionths to any
|
||||
routed payment volume in satoshi.
|
||||
|
||||
{htlcmax} is the maximum (outgoing) htlc amount to allow and
|
||||
advertize.
|
||||
|
||||
{enforcedelay} is the number of seconds before enforcing this
|
||||
change.
|
||||
|
||||
"""
|
||||
payload = {
|
||||
"id": id,
|
||||
"feebase": feebase,
|
||||
"feeppm": feeppm,
|
||||
"htlcmax": htlcmax,
|
||||
"enforcedelay": enforcedelay,
|
||||
}
|
||||
return self.call("setchannel", payload)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Shut down the lightningd process.
|
||||
|
@ -65,6 +65,7 @@ MANPAGES := doc/lightning-cli.1 \
|
||||
doc/lightning-sendonion.7 \
|
||||
doc/lightning-sendonionmessage.7 \
|
||||
doc/lightning-sendpay.7 \
|
||||
doc/lightning-setchannel.7 \
|
||||
doc/lightning-setchannelfee.7 \
|
||||
doc/lightning-sendcustommsg.7 \
|
||||
doc/lightning-signmessage.7 \
|
||||
|
@ -97,6 +97,7 @@ c-lightning Documentation
|
||||
lightning-sendonionmessage <lightning-sendonionmessage.7.md>
|
||||
lightning-sendpay <lightning-sendpay.7.md>
|
||||
lightning-sendpsbt <lightning-sendpsbt.7.md>
|
||||
lightning-setchannel <lightning-setchannel.7.md>
|
||||
lightning-setchannelfee <lightning-setchannelfee.7.md>
|
||||
lightning-signmessage <lightning-signmessage.7.md>
|
||||
lightning-signpsbt <lightning-signpsbt.7.md>
|
||||
|
89
doc/lightning-setchannel.7.md
Normal file
89
doc/lightning-setchannel.7.md
Normal file
@ -0,0 +1,89 @@
|
||||
lightning-setchannel -- Command for configuring fees / maximum htlc on a lightning channel
|
||||
===========================================================================================
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
**setchannel** *id* [*feebase*] [*feeppm*] [*htlcmax*] [*enforcedelay*]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
The **setchannel** RPC command sets channel specific routing fees, and
|
||||
`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.
|
||||
|
||||
*id* is required and should contain a scid (short channel ID), channel
|
||||
id or peerid (pubkey) of the channel to be modified. If *id* is set to
|
||||
"all", the updates are applied to all channels in states
|
||||
CHANNELD\_NORMAL or CHANNELD\_AWAITING\_LOCKIN.
|
||||
|
||||
*feebase* is an optional value in millisatoshi that is added as base fee to
|
||||
any routed payment: if omitted, it is unchanged. It can be a whole number, or a whole
|
||||
number ending in *msat* or *sat*, or a number with three decimal places
|
||||
ending in *sat*, or a number with 1 to 11 decimal places ending in
|
||||
*btc*.
|
||||
|
||||
*feeppm* is an optional value that is added proportionally per-millionths
|
||||
to any routed payment volume in satoshi. For example, if ppm is 1,000
|
||||
and 1,000,000 satoshi is being routed through the channel, an
|
||||
proportional fee of 1,000 satoshi is added, resulting in a 0.1% fee.
|
||||
|
||||
*htlcmax* is an optional value that limits how large an HTLC we will
|
||||
send: if omitted, it is unchanged (the default is no effective
|
||||
limit). It can be a whole number, or a whole number ending in *msat*
|
||||
or *sat*, or a number with three decimal places ending in *sat*, or a
|
||||
number with 1 to 11 decimal places ending in *btc*.
|
||||
|
||||
*enforcedelay* is the number of seconds to delay before enforcing the
|
||||
new fees/htlc max (default 600, which is ten minutes). This gives the
|
||||
network a chance to catch up with the new rates and avoids rejecting
|
||||
HTLCs before they do. This only has an effect if rates are increased
|
||||
(we always allow users to overpay fees) or *htlcmax* is decreased, and
|
||||
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
|
||||
the updated configuration is enforced immediately.
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
|
||||
[comment]: # (GENERATE-FROM-SCHEMA-START)
|
||||
On success, an object containing **channels** is returned. It is an array of objects, where each object contains:
|
||||
- **peer_id** (pubkey): The node_id of the peer
|
||||
- **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_proportional_millionths** (u32): The resulting feeppm (this is the BOLT #7 name)
|
||||
- **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)
|
||||
|
||||
[comment]: # (GENERATE-FROM-SCHEMA-END)
|
||||
|
||||
ERRORS
|
||||
------
|
||||
|
||||
The following error codes may occur:
|
||||
- -1: Channel is in incorrect state, i.e. Catchall nonspecific error.
|
||||
- -32602: JSONRPC2\_INVALID\_PARAMS, i.e. Given id is not a channel ID
|
||||
or short channel ID.
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
|
||||
Michael Schmoock <<michael@schmoock.net>> is the author of this
|
||||
feature. Rusty Russell <<rusty@rustcorp.com.au>> is mainly
|
||||
responsible for the c-lightning project.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
lightningd-config(5), lightning-fundchannel(7),
|
||||
lightning-listchannels(7), lightning-listpeers(7)
|
||||
|
||||
RESOURCES
|
||||
---------
|
||||
|
||||
Main web site: <https://github.com/ElementsProject/lightning>
|
||||
|
||||
[comment]: # ( SHA256STAMP:25c6733af784e8a21a8eed4bcb0f12767ae49d16fe623187ae5313b5bb5cdd80)
|
53
doc/schemas/setchannel.schema.json
Normal file
53
doc/schemas/setchannel.schema.json
Normal file
@ -0,0 +1,53 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"channels"
|
||||
],
|
||||
"properties": {
|
||||
"channels": {
|
||||
"type": "array",
|
||||
"description": "channel(s) set, and their resulting configuration",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"peer_id",
|
||||
"channel_id",
|
||||
"fee_base_msat",
|
||||
"fee_proportional_millionths",
|
||||
"maximum_htlc_out_msat"
|
||||
],
|
||||
"properties": {
|
||||
"peer_id": {
|
||||
"type": "pubkey",
|
||||
"description": "The node_id of the peer"
|
||||
},
|
||||
"channel_id": {
|
||||
"type": "hex",
|
||||
"description": "The channel_id of the channel",
|
||||
"minLength": 64,
|
||||
"maxLength": 64
|
||||
},
|
||||
"short_channel_id": {
|
||||
"type": "short_channel_id",
|
||||
"description": "the short_channel_id (if locked in)"
|
||||
},
|
||||
"fee_base_msat": {
|
||||
"type": "msat",
|
||||
"description": "The resulting feebase (this is the BOLT #7 name)"
|
||||
},
|
||||
"fee_proportional_millionths": {
|
||||
"type": "u32",
|
||||
"description": "The resulting feeppm (this is the BOLT #7 name)"
|
||||
},
|
||||
"maximum_htlc_out_msat": {
|
||||
"type": "msat",
|
||||
"description": "The resulting htlcmax we will advertize (the BOLT #7 name is htlc_maximum_msat)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2007,13 +2007,20 @@ static struct command_result *param_msat_u32(struct command *cmd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void set_channel_fees(struct command *cmd, struct channel *channel,
|
||||
u32 base, u32 ppm, u32 delaysecs,
|
||||
struct json_stream *response)
|
||||
static void set_channel_config(struct command *cmd, struct channel *channel,
|
||||
u32 *base,
|
||||
u32 *ppm,
|
||||
struct amount_msat *htlc_max,
|
||||
u32 delaysecs,
|
||||
struct json_stream *response,
|
||||
bool add_details)
|
||||
{
|
||||
/* We only need to defer values if we *increase* them; we always
|
||||
* allow users to overpay fees. */
|
||||
if (base > channel->feerate_base || ppm > channel->feerate_ppm) {
|
||||
/* We only need to defer values if we *increase* fees (or drop
|
||||
* max); we always allow users to overpay fees. */
|
||||
if ((base && *base > channel->feerate_base)
|
||||
|| (ppm && *ppm > channel->feerate_ppm)
|
||||
|| (htlc_max
|
||||
&& amount_msat_less(*htlc_max, channel->htlc_maximum_msat))) {
|
||||
channel->old_feerate_timeout
|
||||
= timeabs_add(time_now(), time_from_sec(delaysecs));
|
||||
channel->old_feerate_base = channel->feerate_base;
|
||||
@ -2022,14 +2029,18 @@ static void set_channel_fees(struct command *cmd, struct channel *channel,
|
||||
}
|
||||
|
||||
/* set new values */
|
||||
channel->feerate_base = base;
|
||||
channel->feerate_ppm = ppm;
|
||||
if (base)
|
||||
channel->feerate_base = *base;
|
||||
if (ppm)
|
||||
channel->feerate_ppm = *ppm;
|
||||
if (htlc_max)
|
||||
channel->htlc_maximum_msat = *htlc_max;
|
||||
|
||||
/* tell channeld to make a send_channel_update */
|
||||
if (channel->owner && streq(channel->owner->name, "channeld"))
|
||||
subd_send_msg(channel->owner,
|
||||
take(towire_channeld_config_channel(NULL, &base, &ppm,
|
||||
NULL)));
|
||||
take(towire_channeld_config_channel(NULL, base, ppm,
|
||||
htlc_max)));
|
||||
|
||||
/* save values to database */
|
||||
wallet_channel_save(cmd->ld->wallet, channel);
|
||||
@ -2041,6 +2052,17 @@ static void set_channel_fees(struct command *cmd, struct channel *channel,
|
||||
type_to_string(tmpctx, struct channel_id, &channel->cid));
|
||||
if (channel->scid)
|
||||
json_add_short_channel_id(response, "short_channel_id", channel->scid);
|
||||
|
||||
/* setchannel lists these explicitly */
|
||||
if (add_details) {
|
||||
json_add_amount_msat_only(response, "fee_base_msat",
|
||||
amount_msat(channel->feerate_base));
|
||||
json_add_u32(response, "fee_proportional_millionths",
|
||||
channel->feerate_ppm);
|
||||
json_add_amount_msat_only(response,
|
||||
"maximum_htlc_out_msat",
|
||||
channel->htlc_maximum_msat);
|
||||
}
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
@ -2088,14 +2110,14 @@ static struct command_result *json_setchannelfee(struct command *cmd,
|
||||
channel->state != CHANNELD_AWAITING_LOCKIN &&
|
||||
channel->state != DUALOPEND_AWAITING_LOCKIN)
|
||||
continue;
|
||||
set_channel_fees(cmd, channel, *base, *ppm, *delaysecs,
|
||||
response);
|
||||
set_channel_config(cmd, channel, base, ppm, NULL,
|
||||
*delaysecs, response, false);
|
||||
}
|
||||
|
||||
/* single channel should be updated */
|
||||
} else {
|
||||
set_channel_fees(cmd, channel, *base, *ppm, *delaysecs,
|
||||
response);
|
||||
set_channel_config(cmd, channel, base, ppm, NULL,
|
||||
*delaysecs, response, false);
|
||||
}
|
||||
|
||||
/* Close and return response */
|
||||
@ -2117,6 +2139,75 @@ static const struct json_command setchannelfee_command = {
|
||||
};
|
||||
AUTODATA(json_command, &setchannelfee_command);
|
||||
|
||||
static struct command_result *json_setchannel(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct json_stream *response;
|
||||
struct peer *peer;
|
||||
struct channel *channel;
|
||||
u32 *base, *ppm, *delaysecs;
|
||||
struct amount_msat *htlc_max;
|
||||
|
||||
/* Parse the JSON command */
|
||||
if (!param(cmd, buffer, params,
|
||||
p_req("id", param_channel_or_all, &channel),
|
||||
p_opt("feebase", param_msat_u32, &base),
|
||||
p_opt("feeppm", param_number, &ppm),
|
||||
p_opt("htlcmax", param_msat, &htlc_max),
|
||||
p_opt_def("enforcedelay", param_number, &delaysecs, 600),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
if (channel
|
||||
&& channel->state != CHANNELD_NORMAL
|
||||
&& channel->state != CHANNELD_AWAITING_LOCKIN
|
||||
&& channel->state != DUALOPEND_AWAITING_LOCKIN)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Channel is in state %s", channel_state_name(channel));
|
||||
|
||||
/* Open JSON response object for later iteration */
|
||||
response = json_stream_success(cmd);
|
||||
json_array_start(response, "channels");
|
||||
|
||||
/* If the users requested 'all' channels we need to iterate */
|
||||
if (channel == NULL) {
|
||||
list_for_each(&cmd->ld->peers, peer, list) {
|
||||
channel = peer_active_channel(peer);
|
||||
if (!channel)
|
||||
continue;
|
||||
if (channel->state != CHANNELD_NORMAL &&
|
||||
channel->state != CHANNELD_AWAITING_LOCKIN &&
|
||||
channel->state != DUALOPEND_AWAITING_LOCKIN)
|
||||
continue;
|
||||
set_channel_config(cmd, channel, base, ppm, htlc_max,
|
||||
*delaysecs, response, true);
|
||||
}
|
||||
|
||||
/* single channel should be updated */
|
||||
} else {
|
||||
set_channel_config(cmd, channel, base, ppm, htlc_max,
|
||||
*delaysecs, response, true);
|
||||
}
|
||||
|
||||
/* Close and return response */
|
||||
json_array_end(response);
|
||||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
static const struct json_command setchannel_command = {
|
||||
"setchannel",
|
||||
"channels",
|
||||
json_setchannel,
|
||||
"Sets fees and/or htlc_max for channel with {id} "
|
||||
"(either peer ID, channel ID, short channel ID or 'all'). "
|
||||
"If {feebase}, {feeppm} or {htlcmax} is missing, it is unchanged."
|
||||
"{base} can also be defined in other units, for example '1sat'. "
|
||||
"If {id} is 'all', the fees will be applied for all channels. "
|
||||
};
|
||||
AUTODATA(json_command, &setchannel_command);
|
||||
|
||||
#if DEVELOPER
|
||||
static struct command_result *json_sign_last_tx(struct command *cmd,
|
||||
const char *buffer,
|
||||
|
Loading…
Reference in New Issue
Block a user