diff --git a/lightningd/bitcoind.c b/lightningd/bitcoind.c index 6595dcdf1..744b579d9 100644 --- a/lightningd/bitcoind.c +++ b/lightningd/bitcoind.c @@ -332,7 +332,8 @@ static bool process_estimatefee(struct bitcoin_cli *bcli) efee->satoshi_per_kw[efee->i] = 0; } else /* Rate in satoshi per kw. */ - efee->satoshi_per_kw[efee->i] = feerate / 4; + efee->satoshi_per_kw[efee->i] + = feerate_from_style(feerate, FEERATE_PER_KBYTE); efee->i++; if (efee->i == tal_count(efee->satoshi_per_kw)) { diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index d91b33d9b..60f83e8bc 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -422,6 +421,32 @@ u32 unilateral_feerate(struct chain_topology *topo) return try_get_feerate(topo, FEERATE_URGENT); } +u32 feerate_from_style(u32 feerate, enum feerate_style style) +{ + switch (style) { + case FEERATE_PER_KSIPA: + return feerate; + case FEERATE_PER_KBYTE: + /* Everyone uses satoshi per kbyte, but we use satoshi per ksipa + * (don't round down to zero though)! */ + return (feerate + 3) / 4; + } + abort(); +} + +u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style) +{ + switch (style) { + case FEERATE_PER_KSIPA: + return feerate_perkw; + case FEERATE_PER_KBYTE: + if ((u64)feerate_perkw * 4 > UINT_MAX) + return UINT_MAX; + return feerate_perkw * 4; + } + abort(); +} + static void json_feerates(struct command *cmd, const char *buffer, const jsmntok_t *params) { @@ -429,12 +454,10 @@ static void json_feerates(struct command *cmd, struct json_result *response; u32 *urgent, *normal, *slow, feerates[NUM_FEERATES]; bool missing; - const jsmntok_t *style; - bool bitcoind_style; - u64 mulfactor; + enum feerate_style *style; if (!param(cmd, buffer, params, - p_req("style", json_tok_tok, &style), + p_req("style", json_tok_feerate_style, &style), p_opt("urgent", json_tok_number, &urgent), p_opt("normal", json_tok_number, &normal), p_opt("slow", json_tok_number, &slow), @@ -446,20 +469,8 @@ static void json_feerates(struct command *cmd, feerates[FEERATE_NORMAL] = normal ? *normal : 0; feerates[FEERATE_SLOW] = slow ? *slow : 0; - if (json_tok_streq(buffer, style, "perkw")) { - bitcoind_style = false; - mulfactor = 1; - } else if (json_tok_streq(buffer, style, "perkb")) { - /* Everyone uses satoshi per kbyte, but we use satoshi per ksipa - * (don't round down to zero though)! */ - for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) - feerates[i] = (feerates[i] + 3) / 4; - bitcoind_style = true; - mulfactor = 4; - } else { - command_fail(cmd, JSONRPC2_INVALID_PARAMS, "invalid style"); - return; - } + for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) + feerates[i] = feerate_from_style(feerates[i], *style); log_info(topo->log, "feerates: inserting feerates in sipa/kb %u/%u/%u", @@ -478,16 +489,17 @@ static void json_feerates(struct command *cmd, response = new_json_result(cmd); json_object_start(response, NULL); - json_object_start(response, bitcoind_style ? "perkb" : "perkw"); + json_object_start(response, json_feerate_style_name(*style)); for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) { if (!feerates[i]) continue; - json_add_num(response, feerate_name(i), feerates[i] * mulfactor); + json_add_num(response, feerate_name(i), + feerate_to_style(feerates[i], *style)); } json_add_u64(response, "min_acceptable", - feerate_min(cmd->ld, NULL) * mulfactor); + feerate_to_style(feerate_min(cmd->ld, NULL), *style)); json_add_u64(response, "max_acceptable", - feerate_max(cmd->ld, NULL) * mulfactor); + feerate_to_style(feerate_max(cmd->ld, NULL), *style)); json_object_end(response); if (missing) diff --git a/lightningd/chaintopology.h b/lightningd/chaintopology.h index dcf889e40..ced494752 100644 --- a/lightningd/chaintopology.h +++ b/lightningd/chaintopology.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ struct lightningd; struct peer; struct txwatch; +/* FIXME: move all feerate stuff out to new lightningd/feerate.[ch] files */ enum feerate { FEERATE_URGENT, /* Aka: aim for next block. */ FEERATE_NORMAL, /* Aka: next 4 blocks or so. */ @@ -144,6 +146,10 @@ u32 mutual_close_feerate(struct chain_topology *topo); u32 opening_feerate(struct chain_topology *topo); u32 unilateral_feerate(struct chain_topology *topo); +/* We always use feerate-per-ksipa, ie. perkw */ +u32 feerate_from_style(u32 feerate, enum feerate_style style); +u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style); + /* Broadcast a single tx, and rebroadcast as reqd (copies tx). * If failed is non-NULL, call that and don't rebroadcast. */ void broadcast_tx(struct chain_topology *topo, diff --git a/lightningd/json.c b/lightningd/json.c index baac19d0b..f4b3b6a3b 100644 --- a/lightningd/json.c +++ b/lightningd/json.c @@ -223,6 +223,41 @@ bool json_tok_short_channel_id(struct command *cmd, const char *name, return false; } +const char *json_feerate_style_name(enum feerate_style style) +{ + switch (style) { + case FEERATE_PER_KBYTE: + return "perkb"; + case FEERATE_PER_KSIPA: + return "perkw"; + } + abort(); +} + +bool json_tok_feerate_style(struct command *cmd, const char *name, + const char *buffer, const jsmntok_t *tok, + enum feerate_style **style) +{ + *style = tal(cmd, enum feerate_style); + if (json_tok_streq(buffer, tok, + json_feerate_style_name(FEERATE_PER_KSIPA))) { + **style = FEERATE_PER_KSIPA; + return true; + } else if (json_tok_streq(buffer, tok, + json_feerate_style_name(FEERATE_PER_KBYTE))) { + **style = FEERATE_PER_KBYTE; + return true; + } + + command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "'%s' should be '%s' or '%s', not '%.*s'", + name, + json_feerate_style_name(FEERATE_PER_KSIPA), + json_feerate_style_name(FEERATE_PER_KBYTE), + tok->end - tok->start, buffer + tok->start); + return false; +} + bool json_tok_channel_id(const char *buffer, const jsmntok_t *tok, struct channel_id *cid) diff --git a/lightningd/json.h b/lightningd/json.h index cf664ce10..3b694a5e3 100644 --- a/lightningd/json.h +++ b/lightningd/json.h @@ -83,6 +83,18 @@ bool json_tok_u64(struct command *cmd, const char *name, const char *buffer, const jsmntok_t *tok, uint64_t **num); +enum feerate_style { + FEERATE_PER_KSIPA, + FEERATE_PER_KBYTE +}; + +/* Extract a feerate style. */ +bool json_tok_feerate_style(struct command *cmd, const char *name, + const char *buffer, const jsmntok_t *tok, + enum feerate_style **style); + +const char *json_feerate_style_name(enum feerate_style style); + /* '"fieldname" : "1234:5:6"' */ void json_add_short_channel_id(struct json_result *response, const char *fieldname, diff --git a/tests/test_misc.py b/tests/test_misc.py index ad9def5fc..a61ac864d 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -876,7 +876,7 @@ def test_feerates(node_factory): assert len(feerates['perkb']) == 2 assert feerates['warning'] == 'Some fee estimates unavailable: bitcoind startup?' assert 'perkw' not in feerates - assert feerates['perkb']['max_acceptable'] == (2**32 - 1) * 4 + assert feerates['perkb']['max_acceptable'] == (2**32 - 1) assert feerates['perkb']['min_acceptable'] == 253 * 4 # Now try setting them, one at a time.