mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
wire: remove towire_double()
Before this patch we used to send `double`s over the wire by just copying them. This is not portable because the internal represenation of a `double` is implementation specific. Instead of this, multiply any floating-point numbers that come from the outside (e.g. JSONs) by 1 million and round them to integers when handling them. * Introduce a new param_millionths() that expects a floating-point number and returns it multipled by 1000000 as an integer. * Replace param_double() and param_percent() with param_millionths() * Previously the riskfactor would be allowed to be negative, which must have been unintentional. This patch changes that to require a non-negative number. Changelog-None
This commit is contained in:
parent
6b7db1ea7c
commit
89ceb273f5
@ -35,17 +35,21 @@ struct command_result *param_bool(struct command *cmd, const char *name,
|
||||
name, tok->end - tok->start, buffer + tok->start);
|
||||
}
|
||||
|
||||
struct command_result *param_double(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
double **num)
|
||||
struct command_result *param_millionths(struct command *cmd, const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok, uint64_t **num)
|
||||
{
|
||||
*num = tal(cmd, double);
|
||||
if (json_to_double(buffer, tok, *num))
|
||||
double d;
|
||||
if (json_to_double(buffer, tok, &d) && d >= 0.0) {
|
||||
*num = tal(cmd, uint64_t);
|
||||
**num = (uint64_t)(d * 1000000);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"'%s' should be a double, not '%.*s'",
|
||||
name, tok->end - tok->start, buffer + tok->start);
|
||||
return command_fail(
|
||||
cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"'%s' should be a non-negative floating-point number, not '%.*s'",
|
||||
name, tok->end - tok->start, buffer + tok->start);
|
||||
}
|
||||
|
||||
struct command_result *param_escaped_string(struct command *cmd,
|
||||
@ -128,19 +132,6 @@ struct command_result *param_sha256(struct command *cmd, const char *name,
|
||||
name, tok->end - tok->start, buffer + tok->start);
|
||||
}
|
||||
|
||||
struct command_result *param_percent(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
double **num)
|
||||
{
|
||||
*num = tal(cmd, double);
|
||||
if (json_to_double(buffer, tok, *num) && **num >= 0.0)
|
||||
return NULL;
|
||||
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"'%s' should be a positive double, not '%.*s'",
|
||||
name, tok->end - tok->start, buffer + tok->start);
|
||||
}
|
||||
|
||||
struct command_result *param_u64(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
uint64_t **num)
|
||||
|
@ -25,10 +25,14 @@ struct command_result *param_bool(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
bool **b);
|
||||
|
||||
/* Extract double from this (must be a number literal) */
|
||||
struct command_result *param_double(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
double **num);
|
||||
/*
|
||||
* Extract a non-negative (either 0 or positive) floating-point number from this
|
||||
* (must be a number literal), multiply it by 1 million and return it as an
|
||||
* integer.
|
||||
*/
|
||||
struct command_result *param_millionths(struct command *cmd, const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok, uint64_t **num);
|
||||
|
||||
/* Extract an escaped string (and unescape it) */
|
||||
struct command_result *param_escaped_string(struct command *cmd,
|
||||
@ -57,11 +61,6 @@ struct command_result *param_sha256(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
struct sha256 **hash);
|
||||
|
||||
/* Extract double in range [0.0, 100.0] */
|
||||
struct command_result *param_percent(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
double **num);
|
||||
|
||||
/* Extract number from this (may be a string, or a number literal) */
|
||||
struct command_result *param_u64(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
|
@ -131,17 +131,17 @@ struct sanity {
|
||||
char *str;
|
||||
bool failed;
|
||||
int ival;
|
||||
double dval;
|
||||
u64 fpval; /* floating-point, multiplied by 1000000 */
|
||||
char *fail_str;
|
||||
};
|
||||
|
||||
struct sanity buffers[] = {
|
||||
// pass
|
||||
{"['42', '3.15']", false, 42, 3.15, NULL},
|
||||
{"{ 'u64' : '42', 'double' : '3.15' }", false, 42, 3.15, NULL},
|
||||
{"['42', '3.15']", false, 42, 3150000, NULL},
|
||||
{"{ 'u64' : '42', 'fp' : '3.15' }", false, 42, 3150000, NULL},
|
||||
|
||||
// fail
|
||||
{"{'u64':'42', 'double':'3.15', 'extra':'stuff'}", true, 0, 0,
|
||||
{"{'u64':'42', 'fp':'3.15', 'extra':'stuff'}", true, 0, 0,
|
||||
"unknown parameter"},
|
||||
{"['42', '3.15', 'stuff']", true, 0, 0, "too many"},
|
||||
{"['42', '3.15', 'null']", true, 0, 0, "too many"},
|
||||
@ -151,17 +151,17 @@ struct sanity buffers[] = {
|
||||
{"['42']", true, 0, 0, "missing required"},
|
||||
|
||||
// fail wrong type
|
||||
{"{'u64':'hello', 'double':'3.15'}", true, 0, 0, "be an unsigned 64"},
|
||||
{"{'u64':'hello', 'fp':'3.15'}", true, 0, 0, "be an unsigned 64"},
|
||||
{"['3.15', '3.15', 'stuff']", true, 0, 0, "integer"},
|
||||
};
|
||||
|
||||
static void stest(const struct json *j, struct sanity *b)
|
||||
{
|
||||
u64 *ival;
|
||||
double *dval;
|
||||
u64 *fpval;
|
||||
if (!param(cmd, j->buffer, j->toks,
|
||||
p_req("u64", param_u64, &ival),
|
||||
p_req("double", param_double, &dval), NULL)) {
|
||||
p_req("fp", param_millionths, &fpval), NULL)) {
|
||||
assert(check_fail());
|
||||
assert(b->failed == true);
|
||||
if (!strstr(fail_msg, b->fail_str)) {
|
||||
@ -172,7 +172,7 @@ static void stest(const struct json *j, struct sanity *b)
|
||||
assert(!check_fail());
|
||||
assert(b->failed == false);
|
||||
assert(*ival == 42);
|
||||
assert(*dval > 3.1499 && b->dval < 3.1501);
|
||||
assert(*fpval > 3149900 && b->fpval < 3150100);
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,13 +222,13 @@ static void dup_names(void)
|
||||
{
|
||||
struct json *j =
|
||||
json_parse(cmd,
|
||||
"{ 'u64' : '42', 'u64' : '43', 'double' : '3.15' }");
|
||||
"{ 'u64' : '42', 'u64' : '43', 'fp' : '3.15' }");
|
||||
|
||||
u64 *i;
|
||||
double *d;
|
||||
u64 *fp;
|
||||
assert(!param(cmd, j->buffer, j->toks,
|
||||
p_req("u64", param_u64, &i),
|
||||
p_req("double", param_double, &d), NULL));
|
||||
p_req("fp", param_millionths, &fp), NULL));
|
||||
}
|
||||
|
||||
static void null_params(void)
|
||||
@ -290,28 +290,28 @@ static void bad_programmer(void)
|
||||
{
|
||||
u64 *ival;
|
||||
u64 *ival2;
|
||||
double *dval;
|
||||
u64 *fpval;
|
||||
struct json *j = json_parse(cmd, "[ '25', '546', '26' ]");
|
||||
|
||||
/* check for repeated names */
|
||||
assert(!param(cmd, j->buffer, j->toks,
|
||||
p_req("repeat", param_u64, &ival),
|
||||
p_req("double", param_double, &dval),
|
||||
p_req("fp", param_millionths, &fpval),
|
||||
p_req("repeat", param_u64, &ival2), NULL));
|
||||
assert(check_fail());
|
||||
assert(strstr(fail_msg, "developer error"));
|
||||
|
||||
assert(!param(cmd, j->buffer, j->toks,
|
||||
p_req("repeat", param_u64, &ival),
|
||||
p_req("double", param_double, &dval),
|
||||
p_req("fp", param_millionths, &fpval),
|
||||
p_req("repeat", param_u64, &ival), NULL));
|
||||
assert(check_fail());
|
||||
assert(strstr(fail_msg, "developer error"));
|
||||
|
||||
assert(!param(cmd, j->buffer, j->toks,
|
||||
p_req("u64", param_u64, &ival),
|
||||
p_req("repeat", param_double, &dval),
|
||||
p_req("repeat", param_double, &dval), NULL));
|
||||
p_req("repeat", param_millionths, &fpval),
|
||||
p_req("repeat", param_millionths, &fpval), NULL));
|
||||
assert(check_fail());
|
||||
assert(strstr(fail_msg, "developer error"));
|
||||
|
||||
@ -330,12 +330,13 @@ static void bad_programmer(void)
|
||||
/* Add required param after optional */
|
||||
j = json_parse(cmd, "[ '25', '546', '26', '1.1' ]");
|
||||
unsigned int *msatoshi;
|
||||
double *riskfactor;
|
||||
assert(!param(cmd, j->buffer, j->toks,
|
||||
p_req("u64", param_u64, &ival),
|
||||
p_req("double", param_double, &dval),
|
||||
p_opt_def("msatoshi", param_number, &msatoshi, 100),
|
||||
p_req("riskfactor", param_double, &riskfactor), NULL));
|
||||
u64 *riskfactor_millionths;
|
||||
assert(!param(
|
||||
cmd, j->buffer, j->toks, p_req("u64", param_u64, &ival),
|
||||
p_req("fp", param_millionths, &fpval),
|
||||
p_opt_def("msatoshi", param_number, &msatoshi, 100),
|
||||
p_req("riskfactor", param_millionths, &riskfactor_millionths),
|
||||
NULL));
|
||||
assert(*msatoshi);
|
||||
assert(*msatoshi == 100);
|
||||
assert(check_fail());
|
||||
@ -525,16 +526,16 @@ static void param_tests(void)
|
||||
test_cb(param_bool, bool, "[ tru ]", false, false);
|
||||
test_cb(param_bool, bool, "[ 1 ]", false, false);
|
||||
|
||||
test_cb(param_percent, double, "[ -0.01 ]", 0, false);
|
||||
test_cb(param_percent, double, "[ 0.00 ]", 0, true);
|
||||
test_cb(param_percent, double, "[ 1 ]", 1, true);
|
||||
test_cb(param_percent, double, "[ 1.1 ]", 1.1, true);
|
||||
test_cb(param_percent, double, "[ 1.01 ]", 1.01, true);
|
||||
test_cb(param_percent, double, "[ 99.99 ]", 99.99, true);
|
||||
test_cb(param_percent, double, "[ 100.0 ]", 100, true);
|
||||
test_cb(param_percent, double, "[ 100.001 ]", 100.001, true);
|
||||
test_cb(param_percent, double, "[ 1000 ]", 1000, true);
|
||||
test_cb(param_percent, double, "[ 'wow' ]", 0, false);
|
||||
test_cb(param_millionths, u64, "[ -0.01 ]", 0, false);
|
||||
test_cb(param_millionths, u64, "[ 0.00 ]", 0, true);
|
||||
test_cb(param_millionths, u64, "[ 1 ]", 1000000, true);
|
||||
test_cb(param_millionths, u64, "[ 1.1 ]", 1100000, true);
|
||||
test_cb(param_millionths, u64, "[ 1.01 ]", 1010000, true);
|
||||
test_cb(param_millionths, u64, "[ 99.99 ]", 99990000, true);
|
||||
test_cb(param_millionths, u64, "[ 100.0 ]", 100000000, true);
|
||||
test_cb(param_millionths, u64, "[ 100.001 ]", 100001000, true);
|
||||
test_cb(param_millionths, u64, "[ 1000 ]", 1000000000, true);
|
||||
test_cb(param_millionths, u64, "[ 'wow' ]", 0, false);
|
||||
}
|
||||
|
||||
static void test_invoice(struct command *cmd,
|
||||
|
8
doc/lightning-getroute.7
generated
8
doc/lightning-getroute.7
generated
@ -21,9 +21,9 @@ in \fIbtc\fR\.
|
||||
|
||||
There are two considerations for how good a route is: how low the fees
|
||||
are, and how long your payment will get stuck in a delayed output if a
|
||||
node goes down during the process\. The \fIriskfactor\fR floating-point field
|
||||
controls this tradeoff; it is the annual cost of your funds being stuck
|
||||
(as a percentage)\.
|
||||
node goes down during the process\. The \fIriskfactor\fR non-negative
|
||||
floating-point field controls this tradeoff; it is the annual cost of
|
||||
your funds being stuck (as a percentage)\.
|
||||
|
||||
|
||||
For example, if you thought the convenience of keeping your funds liquid
|
||||
@ -36,7 +36,7 @@ If you didn’t care about risk, \fIriskfactor\fR would be zero\.
|
||||
\fIfromid\fR is the node to start the route from: default is this node\.
|
||||
|
||||
|
||||
The \fIfuzzpercent\fR is a positive floating-point number, representing a
|
||||
The \fIfuzzpercent\fR is a non-negative floating-point number, representing a
|
||||
percentage of the actual fee\. The \fIfuzzpercent\fR is used to distort
|
||||
computed fees along each channel, to provide some randomization to the
|
||||
route generated\. 0\.0 means the exact fee of that channel is used, while
|
||||
|
@ -21,9 +21,9 @@ in *btc*.
|
||||
|
||||
There are two considerations for how good a route is: how low the fees
|
||||
are, and how long your payment will get stuck in a delayed output if a
|
||||
node goes down during the process. The *riskfactor* floating-point field
|
||||
controls this tradeoff; it is the annual cost of your funds being stuck
|
||||
(as a percentage).
|
||||
node goes down during the process. The *riskfactor* non-negative
|
||||
floating-point field controls this tradeoff; it is the annual cost of
|
||||
your funds being stuck (as a percentage).
|
||||
|
||||
For example, if you thought the convenience of keeping your funds liquid
|
||||
(not stuck) was worth 20% per annum interest, *riskfactor* would be 20.
|
||||
@ -32,7 +32,7 @@ If you didn’t care about risk, *riskfactor* would be zero.
|
||||
|
||||
*fromid* is the node to start the route from: default is this node.
|
||||
|
||||
The *fuzzpercent* is a positive floating-point number, representing a
|
||||
The *fuzzpercent* is a non-negative floating-point number, representing a
|
||||
percentage of the actual fee. The *fuzzpercent* is used to distort
|
||||
computed fees along each channel, to provide some randomization to the
|
||||
route generated. 0.0 means the exact fee of that channel is used, while
|
||||
|
@ -35,10 +35,9 @@ msgtype,gossip_getroute_request,3006
|
||||
msgdata,gossip_getroute_request,source,?node_id,
|
||||
msgdata,gossip_getroute_request,destination,node_id,
|
||||
msgdata,gossip_getroute_request,msatoshi,amount_msat,
|
||||
# We don't pass doubles, so pass riskfactor 1000000.
|
||||
msgdata,gossip_getroute_request,riskfactor_by_million,u64,
|
||||
msgdata,gossip_getroute_request,riskfactor_millionths,u64,
|
||||
msgdata,gossip_getroute_request,final_cltv,u32,
|
||||
msgdata,gossip_getroute_request,fuzz,double,
|
||||
msgdata,gossip_getroute_request,fuzz_millionths,u64,
|
||||
msgdata,gossip_getroute_request,num_excluded,u16,
|
||||
msgdata,gossip_getroute_request,excluded,exclude_entry,num_excluded
|
||||
msgdata,gossip_getroute_request,max_hops,u32,
|
||||
|
Can't render this file because it has a wrong number of fields in line 6.
|
@ -883,11 +883,13 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
|
||||
struct node_id *source, destination;
|
||||
struct amount_msat msat;
|
||||
u32 final_cltv;
|
||||
u64 riskfactor_by_million;
|
||||
/* risk factor 12.345% -> riskfactor_millionths = 12345000 */
|
||||
u64 riskfactor_millionths;
|
||||
u32 max_hops;
|
||||
u8 *out;
|
||||
struct route_hop *hops;
|
||||
double fuzz;
|
||||
/* fuzz 12.345% -> fuzz_millionths = 12345000 */
|
||||
u64 fuzz_millionths;
|
||||
struct exclude_entry **excluded;
|
||||
|
||||
/* To choose between variations, we need to know how much we're
|
||||
@ -901,12 +903,9 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
|
||||
* for a route from ourselves (the usual case): in that case,
|
||||
* we don't have to consider fees on our own outgoing channels.
|
||||
*/
|
||||
if (!fromwire_gossip_getroute_request(msg, msg,
|
||||
&source, &destination,
|
||||
&msat, &riskfactor_by_million,
|
||||
&final_cltv, &fuzz,
|
||||
&excluded,
|
||||
&max_hops))
|
||||
if (!fromwire_gossip_getroute_request(
|
||||
msg, msg, &source, &destination, &msat, &riskfactor_millionths,
|
||||
&final_cltv, &fuzz_millionths, &excluded, &max_hops))
|
||||
master_badmsg(WIRE_GOSSIP_GETROUTE_REQUEST, msg);
|
||||
|
||||
status_debug("Trying to find a route from %s to %s for %s",
|
||||
@ -916,9 +915,10 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
|
||||
type_to_string(tmpctx, struct amount_msat, &msat));
|
||||
|
||||
/* routing.c does all the hard work; can return NULL. */
|
||||
hops = get_route(tmpctx, daemon->rstate, source, &destination,
|
||||
msat, riskfactor_by_million / 1000000.0, final_cltv,
|
||||
fuzz, pseudorand_u64(), excluded, max_hops);
|
||||
hops = get_route(tmpctx, daemon->rstate, source, &destination, msat,
|
||||
riskfactor_millionths / 1000000.0, final_cltv,
|
||||
fuzz_millionths / 1000000.0, pseudorand_u64(),
|
||||
excluded, max_hops);
|
||||
|
||||
out = towire_gossip_getroute_reply(NULL, hops);
|
||||
daemon_conn_send(daemon->master, take(out));
|
||||
|
@ -381,7 +381,8 @@ static struct command_result *json_getroute(struct command *cmd,
|
||||
const jsmntok_t *excludetok;
|
||||
struct amount_msat *msat;
|
||||
u32 *cltv;
|
||||
double *riskfactor;
|
||||
/* risk factor 12.345% -> riskfactor_millionths = 12345000 */
|
||||
u64 *riskfactor_millionths;
|
||||
const struct exclude_entry **excluded;
|
||||
u32 *max_hops;
|
||||
|
||||
@ -390,23 +391,23 @@ static struct command_result *json_getroute(struct command *cmd,
|
||||
* randomization (the higher-fee paths become more likely to
|
||||
* be selected) at the cost of increasing the probability of
|
||||
* selecting the higher-fee paths. */
|
||||
double *fuzz;
|
||||
u64 *fuzz_millionths; /* fuzz 12.345% -> fuzz_millionths = 12345000 */
|
||||
|
||||
if (!param(cmd, buffer, params,
|
||||
p_req("id", param_node_id, &destination),
|
||||
p_req("msatoshi", param_msat, &msat),
|
||||
p_req("riskfactor", param_double, &riskfactor),
|
||||
p_opt_def("cltv", param_number, &cltv, 9),
|
||||
p_opt("fromid", param_node_id, &source),
|
||||
p_opt_def("fuzzpercent", param_percent, &fuzz, 5.0),
|
||||
p_opt("exclude", param_array, &excludetok),
|
||||
p_opt_def("maxhops", param_number, &max_hops,
|
||||
ROUTING_MAX_HOPS),
|
||||
NULL))
|
||||
if (!param(
|
||||
cmd, buffer, params, p_req("id", param_node_id, &destination),
|
||||
p_req("msatoshi", param_msat, &msat),
|
||||
p_req("riskfactor", param_millionths, &riskfactor_millionths),
|
||||
p_opt_def("cltv", param_number, &cltv, 9),
|
||||
p_opt("fromid", param_node_id, &source),
|
||||
p_opt_def("fuzzpercent", param_millionths, &fuzz_millionths,
|
||||
5000000),
|
||||
p_opt("exclude", param_array, &excludetok),
|
||||
p_opt_def("maxhops", param_number, &max_hops, ROUTING_MAX_HOPS),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
/* Convert from percentage */
|
||||
*fuzz = *fuzz / 100.0;
|
||||
*fuzz_millionths /= 100;
|
||||
|
||||
if (excludetok) {
|
||||
const jsmntok_t *t;
|
||||
@ -442,12 +443,9 @@ static struct command_result *json_getroute(struct command *cmd,
|
||||
excluded = NULL;
|
||||
}
|
||||
|
||||
u8 *req = towire_gossip_getroute_request(cmd, source, destination,
|
||||
*msat,
|
||||
*riskfactor * 1000000.0,
|
||||
*cltv, fuzz,
|
||||
excluded,
|
||||
*max_hops);
|
||||
u8 *req = towire_gossip_getroute_request(
|
||||
cmd, source, destination, *msat, *riskfactor_millionths, *cltv,
|
||||
*fuzz_millionths, excluded, *max_hops);
|
||||
subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd);
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
@ -13,7 +13,9 @@
|
||||
#include <common/json_stream.h>
|
||||
#include <common/pseudorand.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <inttypes.h>
|
||||
#include <plugins/libplugin.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <wire/onion_defs.h>
|
||||
#include <wire/wire.h>
|
||||
@ -83,11 +85,13 @@ struct pay_command {
|
||||
|
||||
/* How much we're paying, and what riskfactor for routing. */
|
||||
struct amount_msat msat;
|
||||
double riskfactor;
|
||||
/* riskfactor 12.345% -> riskfactor_millionths = 12345000 */
|
||||
u64 riskfactor_millionths;
|
||||
unsigned int final_cltv;
|
||||
|
||||
/* Limits on what routes we'll accept. */
|
||||
double maxfeepercent;
|
||||
/* 12.345% -> maxfee_pct_millionths = 12345000 */
|
||||
u64 maxfee_pct_millionths;
|
||||
unsigned int maxdelay;
|
||||
struct amount_msat exemptfee;
|
||||
|
||||
@ -719,8 +723,8 @@ static struct command_result *getroute_done(struct command *cmd,
|
||||
struct pay_attempt *attempt = current_attempt(pc);
|
||||
const jsmntok_t *t = json_get_member(buf, result, "route");
|
||||
struct amount_msat fee;
|
||||
struct amount_msat max_fee;
|
||||
u32 delay;
|
||||
double feepercent;
|
||||
struct out_req *req;
|
||||
|
||||
if (!t)
|
||||
@ -752,14 +756,19 @@ static struct command_result *getroute_done(struct command *cmd,
|
||||
plugin_err(cmd->plugin, "getroute with invalid delay? %.*s",
|
||||
result->end - result->start, buf);
|
||||
|
||||
/* Casting u64 to double will lose some precision. The loss of precision
|
||||
* in feepercent will be like 3.0000..(some dots)..1 % - 3.0 %.
|
||||
* That loss will not be representable in double. So, it's Okay to
|
||||
* cast u64 to double for feepercent calculation. */
|
||||
feepercent = ((double)fee.millisatoshis) * 100.0 / ((double) pc->msat.millisatoshis); /* Raw: fee double manipulation */
|
||||
if (pc->maxfee_pct_millionths / 100 > UINT32_MAX)
|
||||
plugin_err(cmd->plugin, "max fee percent too large: %lf",
|
||||
pc->maxfee_pct_millionths / 1000000.0);
|
||||
|
||||
if (amount_msat_greater(fee, pc->exemptfee)
|
||||
&& feepercent > pc->maxfeepercent) {
|
||||
if (!amount_msat_fee(&max_fee, pc->msat, 0,
|
||||
(u32)(pc->maxfee_pct_millionths / 100)))
|
||||
plugin_err(
|
||||
cmd->plugin, "max fee too large: %s * %lf%%",
|
||||
type_to_string(tmpctx, struct amount_msat, &pc->msat),
|
||||
pc->maxfee_pct_millionths / 1000000.0);
|
||||
|
||||
if (amount_msat_greater(fee, pc->exemptfee) &&
|
||||
amount_msat_greater(fee, max_fee)) {
|
||||
const jsmntok_t *charger;
|
||||
struct json_out *failed;
|
||||
char *feemsg;
|
||||
@ -916,7 +925,8 @@ static struct command_result *execute_getroute(struct command *cmd,
|
||||
type_to_string(tmpctx, struct amount_msat, &msat));
|
||||
json_add_u32(req->js, "cltv", cltv);
|
||||
json_add_u32(req->js, "maxhops", max_hops);
|
||||
json_add_member(req->js, "riskfactor", false, "%f", pc->riskfactor);
|
||||
json_add_member(req->js, "riskfactor", false, "%lf",
|
||||
pc->riskfactor_millionths / 1000000.0);
|
||||
if (tal_count(pc->excludes) != 0) {
|
||||
json_array_start(req->js, "exclude");
|
||||
for (size_t i = 0; i < tal_count(pc->excludes); i++)
|
||||
@ -1245,10 +1255,10 @@ static struct command_result *json_pay(struct command *cmd,
|
||||
struct bolt11 *b11;
|
||||
const char *b11str;
|
||||
char *fail;
|
||||
double *riskfactor;
|
||||
u64 *riskfactor_millionths;
|
||||
unsigned int *retryfor;
|
||||
struct pay_command *pc = tal(cmd, struct pay_command);
|
||||
double *maxfeepercent;
|
||||
u64 *maxfee_pct_millionths;
|
||||
unsigned int *maxdelay;
|
||||
struct amount_msat *exemptfee;
|
||||
struct out_req *req;
|
||||
@ -1256,16 +1266,18 @@ static struct command_result *json_pay(struct command *cmd,
|
||||
bool *use_shadow;
|
||||
#endif
|
||||
|
||||
if (!param(cmd, buf, params,
|
||||
p_req("bolt11", param_string, &b11str),
|
||||
if (!param(cmd, buf, params, p_req("bolt11", param_string, &b11str),
|
||||
p_opt("msatoshi", param_msat, &msat),
|
||||
p_opt("label", param_string, &pc->label),
|
||||
p_opt_def("riskfactor", param_double, &riskfactor, 10),
|
||||
p_opt_def("maxfeepercent", param_percent, &maxfeepercent, 0.5),
|
||||
p_opt_def("riskfactor", param_millionths,
|
||||
&riskfactor_millionths, 10000000),
|
||||
p_opt_def("maxfeepercent", param_millionths,
|
||||
&maxfee_pct_millionths, 500000),
|
||||
p_opt_def("retry_for", param_number, &retryfor, 60),
|
||||
p_opt_def("maxdelay", param_number, &maxdelay,
|
||||
maxdelay_default),
|
||||
p_opt_def("exemptfee", param_msat, &exemptfee, AMOUNT_MSAT(5000)),
|
||||
p_opt_def("exemptfee", param_msat, &exemptfee,
|
||||
AMOUNT_MSAT(5000)),
|
||||
#if DEVELOPER
|
||||
p_opt_def("use_shadow", param_bool, &use_shadow, true),
|
||||
#endif
|
||||
@ -1312,10 +1324,10 @@ static struct command_result *json_pay(struct command *cmd,
|
||||
" sets feature var_onion with no secret");
|
||||
}
|
||||
|
||||
pc->maxfeepercent = *maxfeepercent;
|
||||
pc->maxfee_pct_millionths = *maxfee_pct_millionths;
|
||||
pc->maxdelay = *maxdelay;
|
||||
pc->exemptfee = *exemptfee;
|
||||
pc->riskfactor = *riskfactor;
|
||||
pc->riskfactor_millionths = *riskfactor_millionths;
|
||||
pc->final_cltv = b11->min_final_cltv_expiry;
|
||||
pc->dest = type_to_string(cmd, struct node_id, &b11->receiver_id);
|
||||
pc->shadow_dest = tal_strdup(pc, pc->dest);
|
||||
|
@ -199,7 +199,6 @@ class Type(FieldSet):
|
||||
'secp256k1_ecdsa_signature',
|
||||
'secp256k1_ecdsa_recoverable_signature',
|
||||
'wirestring',
|
||||
'double',
|
||||
'errcode_t',
|
||||
'bigsize',
|
||||
'varint',
|
||||
|
@ -151,11 +151,6 @@ u64 fromwire_tu64(const u8 **cursor, size_t *max)
|
||||
return fromwire_tlv_uint(cursor, max, 8);
|
||||
}
|
||||
|
||||
void fromwire_double(const u8 **cursor, size_t *max, double *ret)
|
||||
{
|
||||
fromwire(cursor, max, ret, sizeof(*ret));
|
||||
}
|
||||
|
||||
bool fromwire_bool(const u8 **cursor, size_t *max)
|
||||
{
|
||||
u8 ret;
|
||||
|
@ -77,11 +77,6 @@ void towire_tu64(u8 **pptr, u64 v)
|
||||
return towire_tlv_uint(pptr, v);
|
||||
}
|
||||
|
||||
void towire_double(u8 **pptr, const double *v)
|
||||
{
|
||||
towire(pptr, v, sizeof(*v));
|
||||
}
|
||||
|
||||
void towire_bool(u8 **pptr, bool v)
|
||||
{
|
||||
u8 val = v;
|
||||
|
@ -78,7 +78,6 @@ void towire_u64(u8 **pptr, u64 v);
|
||||
void towire_tu16(u8 **pptr, u16 v);
|
||||
void towire_tu32(u8 **pptr, u32 v);
|
||||
void towire_tu64(u8 **pptr, u64 v);
|
||||
void towire_double(u8 **pptr, const double *v);
|
||||
void towire_pad(u8 **pptr, size_t num);
|
||||
void towire_bool(u8 **pptr, bool v);
|
||||
void towire_errcode_t(u8 **pptr, errcode_t v);
|
||||
@ -103,7 +102,6 @@ u64 fromwire_u64(const u8 **cursor, size_t *max);
|
||||
u16 fromwire_tu16(const u8 **cursor, size_t *max);
|
||||
u32 fromwire_tu32(const u8 **cursor, size_t *max);
|
||||
u64 fromwire_tu64(const u8 **cursor, size_t *max);
|
||||
void fromwire_double(const u8 **cursor, size_t *max, double *v);
|
||||
bool fromwire_bool(const u8 **cursor, size_t *max);
|
||||
errcode_t fromwire_errcode_t(const u8 **cursor, size_t *max);
|
||||
bigsize_t fromwire_bigsize(const u8 **cursor, size_t *max);
|
||||
|
Loading…
Reference in New Issue
Block a user