mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
json: add cmd setchannelfee and wire to channeld
* adds the channeld_specific_feerates wire message 1029 * adds a json command handler * adds u32 access methods for amount_msat
This commit is contained in:
parent
ac0f925dee
commit
5d0390f637
@ -178,3 +178,7 @@ channel_dev_memleak_reply,,leak,bool
|
||||
channel_fail_fallen_behind,1028
|
||||
channel_fail_fallen_behind,,remote_per_commitment_point,struct pubkey
|
||||
|
||||
# Handle a channel specific feerate base ppm configuration
|
||||
channel_specific_feerates,1029
|
||||
channel_specific_feerates,,feerate_base,u32
|
||||
channel_specific_feerates,,feerate_ppm,u32
|
||||
|
|
@ -2528,6 +2528,22 @@ static void handle_feerates(struct peer *peer, const u8 *inmsg)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_specific_feerates(struct peer *peer, const u8 *inmsg)
|
||||
{
|
||||
u32 base_old = peer->fee_base;
|
||||
u32 per_satoshi_old = peer->fee_per_satoshi;
|
||||
|
||||
if (!fromwire_channel_specific_feerates(inmsg,
|
||||
&peer->fee_base,
|
||||
&peer->fee_per_satoshi))
|
||||
master_badmsg(WIRE_CHANNEL_SPECIFIC_FEERATES, inmsg);
|
||||
|
||||
/* only send channel updates if values actually changed */
|
||||
if (peer->fee_base != base_old || peer->fee_per_satoshi != per_satoshi_old)
|
||||
send_channel_update(peer, 0);
|
||||
}
|
||||
|
||||
|
||||
static void handle_preimage(struct peer *peer, const u8 *inmsg)
|
||||
{
|
||||
struct fulfilled_htlc fulfilled_htlc;
|
||||
@ -2648,6 +2664,9 @@ static void req_in(struct peer *peer, const u8 *msg)
|
||||
case WIRE_CHANNEL_FAIL_HTLC:
|
||||
handle_fail(peer, msg);
|
||||
return;
|
||||
case WIRE_CHANNEL_SPECIFIC_FEERATES:
|
||||
handle_specific_feerates(peer, msg);
|
||||
return;
|
||||
case WIRE_CHANNEL_SEND_SHUTDOWN:
|
||||
handle_shutdown_cmd(peer, msg);
|
||||
return;
|
||||
|
@ -362,6 +362,21 @@ bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat)
|
||||
return msat.millisatoshis <= msat_from_sat.millisatoshis;
|
||||
}
|
||||
|
||||
bool amount_msat_overflow_u32(struct amount_msat msat)
|
||||
{
|
||||
return amount_msat_greater_eq(msat, AMOUNT_MSAT(0x100000000));
|
||||
}
|
||||
|
||||
u32 amount_msat_to_u32(struct amount_msat msat)
|
||||
{
|
||||
return (u32)msat.millisatoshis;
|
||||
}
|
||||
|
||||
void amount_msat_from_u32(struct amount_msat *msat, u32 value)
|
||||
{
|
||||
msat->millisatoshis = (u64)value;
|
||||
}
|
||||
|
||||
bool amount_msat_fee(struct amount_msat *fee,
|
||||
struct amount_msat amt,
|
||||
u32 fee_base_msat,
|
||||
|
@ -98,6 +98,15 @@ bool amount_msat_less_sat(struct amount_msat msat, struct amount_sat sat);
|
||||
/* Is msat <= sat? */
|
||||
bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat);
|
||||
|
||||
/* Does value overflow u32 bit */
|
||||
bool amount_msat_overflow_u32(struct amount_msat msat);
|
||||
|
||||
/* Return unchecked u32 value */
|
||||
u32 amount_msat_to_u32(struct amount_msat msat);
|
||||
|
||||
/* Set by u32 value */
|
||||
void amount_msat_from_u32(struct amount_msat *msat, u32 value);
|
||||
|
||||
/* Common operation: what is the HTLC fee for given feerate? Can overflow! */
|
||||
WARN_UNUSED_RESULT bool amount_msat_fee(struct amount_msat *fee,
|
||||
struct amount_msat amt,
|
||||
|
@ -232,6 +232,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
|
||||
case WIRE_CHANNEL_SEND_SHUTDOWN:
|
||||
case WIRE_CHANNEL_DEV_REENABLE_COMMIT:
|
||||
case WIRE_CHANNEL_FEERATES:
|
||||
case WIRE_CHANNEL_SPECIFIC_FEERATES:
|
||||
case WIRE_CHANNEL_DEV_MEMLEAK:
|
||||
/* Replies go to requests. */
|
||||
case WIRE_CHANNEL_OFFER_HTLC_REPLY:
|
||||
|
@ -1034,7 +1034,7 @@ AUTODATA(json_command, &listpeers_command);
|
||||
static struct command_result *
|
||||
command_find_channel(struct command *cmd,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
struct channel **channel, struct peer **peer_out)
|
||||
struct channel **channel)
|
||||
{
|
||||
struct lightningd *ld = cmd->ld;
|
||||
struct channel_id cid;
|
||||
@ -1050,10 +1050,8 @@ command_find_channel(struct command *cmd,
|
||||
derive_channel_id(&channel_cid,
|
||||
&(*channel)->funding_txid,
|
||||
(*channel)->funding_outnum);
|
||||
if (channel_id_eq(&channel_cid, &cid)) {
|
||||
if (peer_out) *peer_out = peer;
|
||||
if (channel_id_eq(&channel_cid, &cid))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Channel ID not found: '%.*s'",
|
||||
@ -1066,10 +1064,8 @@ command_find_channel(struct command *cmd,
|
||||
if (!*channel)
|
||||
continue;
|
||||
if ((*channel)->scid
|
||||
&& (*channel)->scid->u64 == scid.u64) {
|
||||
if (peer_out) *peer_out = peer;
|
||||
&& (*channel)->scid->u64 == scid.u64)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Short channel ID not found: '%.*s'",
|
||||
@ -1108,7 +1104,7 @@ static struct command_result *json_close(struct command *cmd,
|
||||
channel = peer_active_channel(peer);
|
||||
else {
|
||||
struct command_result *res;
|
||||
res = command_find_channel(cmd, buffer, idtok, &channel, NULL);
|
||||
res = command_find_channel(cmd, buffer, idtok, &channel);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
@ -1343,6 +1339,104 @@ static const struct json_command getinfo_command = {
|
||||
};
|
||||
AUTODATA(json_command, &getinfo_command);
|
||||
|
||||
|
||||
static struct command_result *json_setchannelfee(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct json_stream *response;
|
||||
const jsmntok_t *idtok;
|
||||
struct peer *peer;
|
||||
struct channel *channel;
|
||||
struct channel_id cid;
|
||||
struct command_result *res;
|
||||
struct amount_msat *base, base_default;
|
||||
u32 *ppm, ppm_default;
|
||||
|
||||
/* Use daemon config values base/ppm as default */
|
||||
amount_msat_from_u32(&base_default, cmd->ld->config.fee_base);
|
||||
ppm_default = cmd->ld->config.fee_per_satoshi;
|
||||
|
||||
/* Parse the JSON command */
|
||||
if (!param(cmd, buffer, params,
|
||||
p_req("id", param_tok, &idtok),
|
||||
p_opt_def("base", param_msat, &base, base_default),
|
||||
p_opt_def("ppm", param_number, &ppm, ppm_default),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
/* Check base for u32 overflow */
|
||||
if (amount_msat_overflow_u32(*base))
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Value 'base' exceeds u32 max");
|
||||
|
||||
/* Find the channel */
|
||||
peer = peer_from_json(cmd->ld, buffer, idtok);
|
||||
if (peer) {
|
||||
channel = peer_active_channel(peer);
|
||||
if (!channel)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Could not find active channel of peer with that id");
|
||||
} else {
|
||||
res = command_find_channel(cmd, buffer, idtok, &channel);
|
||||
if (res)
|
||||
return res;
|
||||
/* check channel is found and in valid state */
|
||||
if (!channel)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Could not find channel with that id");
|
||||
peer = channel->peer;
|
||||
}
|
||||
|
||||
if (channel->state != CHANNELD_NORMAL &&
|
||||
channel->state != CHANNELD_AWAITING_LOCKIN)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Channel is in state %s", channel_state_name(channel));
|
||||
|
||||
/* set, notify and save new values */
|
||||
channel->feerate_base = amount_msat_to_u32(*base);
|
||||
channel->feerate_ppm = *ppm;
|
||||
|
||||
/* tell channeld to make a send_channel_update */
|
||||
if (channel->owner && streq(channel->owner->name, "lightning_channeld"))
|
||||
subd_send_msg(channel->owner,
|
||||
take(towire_channel_specific_feerates(channel,
|
||||
amount_msat_to_u32(*base), *ppm)));
|
||||
|
||||
/* save values to database */
|
||||
wallet_channel_save(cmd->ld->wallet, channel);
|
||||
|
||||
/* get channel id */
|
||||
derive_channel_id(&cid, &channel->funding_txid, channel->funding_outnum);
|
||||
|
||||
/* write response */
|
||||
response = json_stream_success(cmd);
|
||||
json_object_start(response, NULL);
|
||||
json_add_num(response, "base", amount_msat_to_u32(*base));
|
||||
json_add_num(response, "ppm", *ppm);
|
||||
json_add_pubkey(response, "peer_id", &peer->id);
|
||||
json_add_string(response, "channel_id",
|
||||
type_to_string(tmpctx, struct channel_id, &cid));
|
||||
if (channel->scid)
|
||||
json_add_short_channel_id(response, "short_channel_id", channel->scid);
|
||||
json_object_end(response);
|
||||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
static const struct json_command setchannelfee_command = {
|
||||
"setchannelfee",
|
||||
json_setchannelfee,
|
||||
"Sets specific routing fees for channel with {id} "
|
||||
"(either peer ID, channel ID or short channel ID). "
|
||||
"The routing fees are defined by a fixed {base} (msat) "
|
||||
"and a {ppm} value (proportional per millionth)."
|
||||
"To disable channel specific fees and restore global values, "
|
||||
"just leave out the optional {base} and {ppm} values. "
|
||||
"{base} can also be supplied in other units, i.e. '1sat'."
|
||||
};
|
||||
AUTODATA(json_command, &setchannelfee_command);
|
||||
|
||||
#if DEVELOPER
|
||||
static struct command_result *json_sign_last_tx(struct command *cmd,
|
||||
const char *buffer,
|
||||
|
@ -131,7 +131,7 @@ void json_add_amount_msat(struct json_stream *result UNNEEDED,
|
||||
void json_add_amount_sat(struct json_stream *result UNNEEDED,
|
||||
struct amount_sat sat UNNEEDED,
|
||||
const char *rawfieldname UNNEEDED,
|
||||
const char *satfieldname)
|
||||
const char *msatfieldname)
|
||||
|
||||
{ fprintf(stderr, "json_add_amount_sat called!\n"); abort(); }
|
||||
/* Generated stub for json_add_bool */
|
||||
@ -311,6 +311,11 @@ struct command_result *param_loglevel(struct command *cmd UNNEEDED,
|
||||
const jsmntok_t *tok UNNEEDED,
|
||||
enum log_level **level UNNEEDED)
|
||||
{ fprintf(stderr, "param_loglevel called!\n"); abort(); }
|
||||
/* Generated stub for param_msat */
|
||||
struct command_result *param_msat(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
struct amount_msat **msat UNNEEDED)
|
||||
{ fprintf(stderr, "param_msat called!\n"); abort(); }
|
||||
/* Generated stub for param_number */
|
||||
struct command_result *param_number(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
@ -404,6 +409,9 @@ u8 *towire_channel_dev_reenable_commit(const tal_t *ctx UNNEEDED)
|
||||
/* Generated stub for towire_channel_send_shutdown */
|
||||
u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED)
|
||||
{ fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); }
|
||||
/* Generated stub for towire_channel_specific_feerates */
|
||||
u8 *towire_channel_specific_feerates(const tal_t *ctx UNNEEDED, u32 feerate_base UNNEEDED, u32 feerate_ppm UNNEEDED)
|
||||
{ fprintf(stderr, "towire_channel_specific_feerates called!\n"); abort(); }
|
||||
/* Generated stub for towire_connectctl_connect_to_peer */
|
||||
u8 *towire_connectctl_connect_to_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, u32 seconds_waited UNNEEDED, const struct wireaddr_internal *addrhint UNNEEDED)
|
||||
{ fprintf(stderr, "towire_connectctl_connect_to_peer called!\n"); abort(); }
|
||||
|
@ -210,7 +210,7 @@ void json_add_amount_msat(struct json_stream *result UNNEEDED,
|
||||
void json_add_amount_sat(struct json_stream *result UNNEEDED,
|
||||
struct amount_sat sat UNNEEDED,
|
||||
const char *rawfieldname UNNEEDED,
|
||||
const char *satfieldname)
|
||||
const char *msatfieldname)
|
||||
|
||||
{ fprintf(stderr, "json_add_amount_sat called!\n"); abort(); }
|
||||
/* Generated stub for json_add_bool */
|
||||
@ -371,6 +371,11 @@ struct command_result *param_loglevel(struct command *cmd UNNEEDED,
|
||||
const jsmntok_t *tok UNNEEDED,
|
||||
enum log_level **level UNNEEDED)
|
||||
{ fprintf(stderr, "param_loglevel called!\n"); abort(); }
|
||||
/* Generated stub for param_msat */
|
||||
struct command_result *param_msat(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
struct amount_msat **msat UNNEEDED)
|
||||
{ fprintf(stderr, "param_msat called!\n"); abort(); }
|
||||
/* Generated stub for param_number */
|
||||
struct command_result *param_number(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
@ -492,6 +497,9 @@ u8 *towire_channel_sending_commitsig_reply(const tal_t *ctx UNNEEDED)
|
||||
/* Generated stub for towire_channel_send_shutdown */
|
||||
u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED)
|
||||
{ fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); }
|
||||
/* Generated stub for towire_channel_specific_feerates */
|
||||
u8 *towire_channel_specific_feerates(const tal_t *ctx UNNEEDED, u32 feerate_base UNNEEDED, u32 feerate_ppm UNNEEDED)
|
||||
{ fprintf(stderr, "towire_channel_specific_feerates called!\n"); abort(); }
|
||||
/* Generated stub for towire_connectctl_connect_to_peer */
|
||||
u8 *towire_connectctl_connect_to_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, u32 seconds_waited UNNEEDED, const struct wireaddr_internal *addrhint UNNEEDED)
|
||||
{ fprintf(stderr, "towire_connectctl_connect_to_peer called!\n"); abort(); }
|
||||
|
Loading…
Reference in New Issue
Block a user