mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +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:
committed by
Rusty Russell
parent
6b7db1ea7c
commit
89ceb273f5
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user