lightningd: add force-feerates option.

Useful for regtest and testnet.  Sure, you shouldn't use this on mainnet,
but I haven't restricted it because our users are usually pretty clever.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: #1806
Changelog-Added: config: `force_feerates` option to allow overriding feerate estimates (mainly for regtest).
This commit is contained in:
Rusty Russell 2021-07-08 12:17:03 +09:30
parent 131e79ab91
commit adab9eb301
11 changed files with 150 additions and 3 deletions

View File

@ -148,6 +148,8 @@ On success, an object is returned, containing:
.IP \[bu]
\fBlog-timestamps\fR (boolean, optional): \fBlog-timestamps\fR field from config or cmdline, or default
.IP \[bu]
\fBforce-feerates\fR (string, optional): \fBforce-feerates\fR field from config or cmdline, if any
.IP \[bu]
\fBsubdaemon\fR (string, optional): \fBsubdaemon\fR fields from config or cmdline if any (can be more than one)
.IP \[bu]
\fBtor-service-password\fR (string, optional): \fBtor-service-password\fR field from config or cmdline, if any
@ -268,4 +270,4 @@ Vincenzo Palazzo \fI<vincenzo.palazzo@protonmail.com\fR> wrote the initial versi
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
\" SHA256STAMP:f813a777c6e074907980797dafd798a48633469a59e1ac526e2581e2b1a14c83
\" SHA256STAMP:4591f6c754162b2dcdf82a36d584a48795752d39a986bc1d39c49e0cdbea440f

View File

@ -84,6 +84,7 @@ On success, an object is returned, containing:
- **log-prefix** (string, optional): `log-prefix` field from config or cmdline, or default
- **log-file** (string, optional): `log-file` field from config or cmdline, or default
- **log-timestamps** (boolean, optional): `log-timestamps` field from config or cmdline, or default
- **force-feerates** (string, optional): `force-feerates` field from config or cmdline, if any
- **subdaemon** (string, optional): `subdaemon` fields from config or cmdline if any (can be more than one)
- **tor-service-password** (string, optional): `tor-service-password` field from config or cmdline, if any
[comment]: # (GENERATE-FROM-SCHEMA-END)
@ -203,4 +204,4 @@ RESOURCES
---------
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:3c3f2cd354ef5b33ad34febd29b04b1861c62d545c6a5b9181eb2b2b3880258f)
[comment]: # ( SHA256STAMP:ad98179a7b6254a936d4fde179918b6a975e186adcbc396917a0c2ed2888519e)

View File

@ -316,6 +316,21 @@ How long to wait before sending commitment messages to the peer: in
theory increasing this would reduce load, but your node would have to be
extremely busy node for you to even notice\.
\fBforce-feerates\fR==\fIVALUES\fR
Networks like regtest and testnet have unreliable fee estimates: we
usually treat them as the minumum (253 sats/kw) if we can't get them\.
This allows override of one or more of our standard feerates (see
\fBlightning-feerates\fR(7))\. Up to 5 values, separated by '/' can be
provided: if fewer are provided, then the final value is used for the
remainder\. The values are in per-kw (roughly 1/4 of bitcoind's per-kb
values), an in order are "opening", "mutual_close",
"unilateral_close", "delayed_to_us", "htlc_resolution", and "penalty"\.
You would usually put this option in the per-chain config file, to avoid
setting it on Bitcoin mainnet! e\.g\. \fB~rusty/.lightning/regtest/config\fR\.
.SH Lightning channel and HTLC options
\fBlarge-channels\fR
@ -635,4 +650,4 @@ Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
Note: the modules in the ccan/ directory have their own licenses, but
the rest of the code is covered by the BSD-style MIT license\.
\" SHA256STAMP:40c9f5e9e4ee5257e25a1fc196d2c85c3bc5b21d3f390a4e7fafa031c4e7ad5e
\" SHA256STAMP:d456e1acd004f9528d8772231afdecff1aaa01d80161c833483f6f078f4c7d70

View File

@ -257,6 +257,19 @@ How long to wait before sending commitment messages to the peer: in
theory increasing this would reduce load, but your node would have to be
extremely busy node for you to even notice.
**force-feerates**==*VALUES*
Networks like regtest and testnet have unreliable fee estimates: we
usually treat them as the minumum (253 sats/kw) if we can't get them.
This allows override of one or more of our standard feerates (see
lightning-feerates(7)). Up to 5 values, separated by '/' can be
provided: if fewer are provided, then the final value is used for the
remainder. The values are in per-kw (roughly 1/4 of bitcoind's per-kb
values), an in order are "opening", "mutual_close",
"unilateral_close", "delayed_to_us", "htlc_resolution", and "penalty".
You would usually put this option in the per-chain config file, to avoid
setting it on Bitcoin mainnet! e.g. `~rusty/.lightning/regtest/config`.
### Lightning channel and HTLC options
**large-channels**

View File

@ -235,6 +235,10 @@
"type": "boolean",
"description": "`log-timestamps` field from config or cmdline, or default"
},
"force-feerates": {
"type": "string",
"description": "force-feerate configuration setting, if any"
},
"subdaemon": {
"type": "string",
"description": "`subdaemon` fields from config or cmdline if any (can be more than one)"

View File

@ -187,6 +187,12 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
bitcoin_plugin_error(call->bitcoind, buf, toks,
"estimatefees",
"missing '%s' field", feerate_name(f));
/* We still use the bcli plugin for min and max, even with
* force_feerates */
if (f < tal_count(call->bitcoind->ld->force_feerates)) {
feerates[f] = call->bitcoind->ld->force_feerates[f];
continue;
}
/* FIXME: We could trawl recent blocks for median fee... */
if (!json_to_u32(buf, feeratetok, &feerates[f])) {

View File

@ -22,6 +22,7 @@ struct txwatch;
/* FIXME: move all feerate stuff out to new lightningd/feerate.[ch] files */
enum feerate {
/* DO NOT REORDER: force-feerates uses this order! */
FEERATE_OPENING,
FEERATE_MUTUAL_CLOSE,
FEERATE_UNILATERAL_CLOSE,

View File

@ -290,6 +290,11 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
* each invoice we generate has a different set of channels. */
ld->rr_counter = 0;
/*~ Because fee estimates on testnet and regtest are unreliable,
* we allow overriding them with --force-feerates, in which
* case this is a pointer to an enum feerate-indexed array of values */
ld->force_feerates = NULL;
return ld;
}

View File

@ -199,6 +199,10 @@ struct lightningd {
/* RPC response to send once we've shut down. */
const char *stop_response;
/* Used these feerates instead of whatever bcli returns (up to
* FEERATE_PENALTY). */
u32 *force_feerates;
#if DEVELOPER
/* If we want to debug a subdaemon/plugin. */
const char *dev_debug_subprocess;

View File

@ -131,6 +131,51 @@ static char *opt_set_mode(const char *arg, mode_t *m)
return NULL;
}
static char *opt_force_feerates(const char *arg, struct lightningd *ld)
{
char **vals = tal_strsplit(tmpctx, arg, "/", STR_EMPTY_OK);
size_t n;
/* vals has NULL at end, enum feerate is 0 based */
if (tal_count(vals) - 1 > FEERATE_PENALTY + 1)
return "Too many values";
if (!ld->force_feerates)
ld->force_feerates = tal_arr(ld, u32, FEERATE_PENALTY + 1);
n = 0;
for (size_t i = 0; i < tal_count(ld->force_feerates); i++) {
char *err = opt_set_u32(vals[n], &ld->force_feerates[i]);
if (err)
return err;
fprintf(stderr, "Set feerate %zu based on val %zu\n", i, n);
if (vals[n+1])
n++;
}
return NULL;
}
static char *fmt_force_feerates(const tal_t *ctx, const u32 *force_feerates)
{
char *ret;
size_t last;
if (!force_feerates)
return NULL;
ret = tal_fmt(ctx, "%i", force_feerates[0]);
last = 0;
for (size_t i = 1; i < tal_count(force_feerates); i++) {
if (force_feerates[i] == force_feerates[i-1])
continue;
/* Different? Catchup! */
for (size_t j = last + 1; j <= i; j++)
tal_append_fmt(&ret, "/%i", force_feerates[j]);
last = i;
}
return ret;
}
#if EXPERIMENTAL_FEATURES
static char *opt_set_accept_extra_tlv_types(const char *arg,
struct lightningd *ld)
@ -1003,6 +1048,10 @@ static void register_opts(struct lightningd *ld)
"Set the file mode (permissions) for the "
"JSON-RPC socket");
opt_register_arg("--force-feerates",
opt_force_feerates, NULL, ld,
"Set testnet/regtest feerates in sats perkw, opening/mutual_close/unlateral_close/delayed_to_us/htlc_resolution/penalty: if fewer specified, last number applies to remainder");
opt_register_arg("--subdaemon", opt_subdaemon, NULL,
ld, "Arg specified as SUBDAEMON:PATH. "
"Specifies an alternate subdaemon binary. "
@ -1423,6 +1472,8 @@ static void add_config(struct lightningd *ld,
json_add_opt_log_levels(response, ld->log);
} else if (opt->cb_arg == (void *)opt_disable_plugin) {
json_add_opt_disable_plugins(response, ld->plugins);
} else if (opt->cb_arg == (void *)opt_force_feerates) {
answer = fmt_force_feerates(name0, ld->force_feerates);
} else if (opt->cb_arg == (void *)opt_important_plugin) {
/* Do nothing, this is already handled by
* opt_add_plugin. */

View File

@ -2561,3 +2561,48 @@ def test_getlog(node_factory):
# This should not
logs = l1.rpc.getlog(level='io')['log']
assert [l for l in logs if l['type'] == 'SKIPPED'] == []
def test_force_feerates(node_factory):
l1 = node_factory.get_node(options={'force-feerates': 1111})
assert l1.rpc.listconfigs()['force-feerates'] == '1111'
assert l1.rpc.feerates('perkw')['perkw'] == {
"opening": 1111,
"mutual_close": 1111,
"unilateral_close": 1111,
"delayed_to_us": 1111,
"htlc_resolution": 1111,
"penalty": 1111,
"min_acceptable": 1875,
"max_acceptable": 150000}
l1.stop()
l1.daemon.opts['force-feerates'] = '1111/2222'
l1.start()
assert l1.rpc.listconfigs()['force-feerates'] == '1111/2222'
assert l1.rpc.feerates('perkw')['perkw'] == {
"opening": 1111,
"mutual_close": 2222,
"unilateral_close": 2222,
"delayed_to_us": 2222,
"htlc_resolution": 2222,
"penalty": 2222,
"min_acceptable": 1875,
"max_acceptable": 150000}
l1.stop()
l1.daemon.opts['force-feerates'] = '1111/2222/3333/4444/5555/6666'
l1.start()
assert l1.rpc.listconfigs()['force-feerates'] == '1111/2222/3333/4444/5555/6666'
assert l1.rpc.feerates('perkw')['perkw'] == {
"opening": 1111,
"mutual_close": 2222,
"unilateral_close": 3333,
"delayed_to_us": 4444,
"htlc_resolution": 5555,
"penalty": 6666,
"min_acceptable": 1875,
"max_acceptable": 150000}