mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
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:
4
doc/lightning-listconfigs.7
generated
4
doc/lightning-listconfigs.7
generated
@@ -148,6 +148,8 @@ On success, an object is returned, containing:
|
|||||||
.IP \[bu]
|
.IP \[bu]
|
||||||
\fBlog-timestamps\fR (boolean, optional): \fBlog-timestamps\fR field from config or cmdline, or default
|
\fBlog-timestamps\fR (boolean, optional): \fBlog-timestamps\fR field from config or cmdline, or default
|
||||||
.IP \[bu]
|
.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)
|
\fBsubdaemon\fR (string, optional): \fBsubdaemon\fR fields from config or cmdline if any (can be more than one)
|
||||||
.IP \[bu]
|
.IP \[bu]
|
||||||
\fBtor-service-password\fR (string, optional): \fBtor-service-password\fR field from config or cmdline, if any
|
\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
|
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
|
||||||
|
|
||||||
\" SHA256STAMP:f813a777c6e074907980797dafd798a48633469a59e1ac526e2581e2b1a14c83
|
\" SHA256STAMP:4591f6c754162b2dcdf82a36d584a48795752d39a986bc1d39c49e0cdbea440f
|
||||||
|
|||||||
@@ -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-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-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
|
- **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)
|
- **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
|
- **tor-service-password** (string, optional): `tor-service-password` field from config or cmdline, if any
|
||||||
[comment]: # (GENERATE-FROM-SCHEMA-END)
|
[comment]: # (GENERATE-FROM-SCHEMA-END)
|
||||||
@@ -203,4 +204,4 @@ RESOURCES
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
Main web site: <https://github.com/ElementsProject/lightning>
|
Main web site: <https://github.com/ElementsProject/lightning>
|
||||||
[comment]: # ( SHA256STAMP:3c3f2cd354ef5b33ad34febd29b04b1861c62d545c6a5b9181eb2b2b3880258f)
|
[comment]: # ( SHA256STAMP:ad98179a7b6254a936d4fde179918b6a975e186adcbc396917a0c2ed2888519e)
|
||||||
|
|||||||
@@ -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
|
theory increasing this would reduce load, but your node would have to be
|
||||||
extremely busy node for you to even notice\.
|
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
|
.SH Lightning channel and HTLC options
|
||||||
|
|
||||||
\fBlarge-channels\fR
|
\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
|
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\.
|
the rest of the code is covered by the BSD-style MIT license\.
|
||||||
|
|
||||||
\" SHA256STAMP:40c9f5e9e4ee5257e25a1fc196d2c85c3bc5b21d3f390a4e7fafa031c4e7ad5e
|
\" SHA256STAMP:d456e1acd004f9528d8772231afdecff1aaa01d80161c833483f6f078f4c7d70
|
||||||
|
|||||||
@@ -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
|
theory increasing this would reduce load, but your node would have to be
|
||||||
extremely busy node for you to even notice.
|
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
|
### Lightning channel and HTLC options
|
||||||
|
|
||||||
**large-channels**
|
**large-channels**
|
||||||
|
|||||||
@@ -235,6 +235,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "`log-timestamps` field from config or cmdline, or default"
|
"description": "`log-timestamps` field from config or cmdline, or default"
|
||||||
},
|
},
|
||||||
|
"force-feerates": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "force-feerate configuration setting, if any"
|
||||||
|
},
|
||||||
"subdaemon": {
|
"subdaemon": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "`subdaemon` fields from config or cmdline if any (can be more than one)"
|
"description": "`subdaemon` fields from config or cmdline if any (can be more than one)"
|
||||||
|
|||||||
@@ -187,6 +187,12 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
|
|||||||
bitcoin_plugin_error(call->bitcoind, buf, toks,
|
bitcoin_plugin_error(call->bitcoind, buf, toks,
|
||||||
"estimatefees",
|
"estimatefees",
|
||||||
"missing '%s' field", feerate_name(f));
|
"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... */
|
/* FIXME: We could trawl recent blocks for median fee... */
|
||||||
if (!json_to_u32(buf, feeratetok, &feerates[f])) {
|
if (!json_to_u32(buf, feeratetok, &feerates[f])) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ struct txwatch;
|
|||||||
|
|
||||||
/* FIXME: move all feerate stuff out to new lightningd/feerate.[ch] files */
|
/* FIXME: move all feerate stuff out to new lightningd/feerate.[ch] files */
|
||||||
enum feerate {
|
enum feerate {
|
||||||
|
/* DO NOT REORDER: force-feerates uses this order! */
|
||||||
FEERATE_OPENING,
|
FEERATE_OPENING,
|
||||||
FEERATE_MUTUAL_CLOSE,
|
FEERATE_MUTUAL_CLOSE,
|
||||||
FEERATE_UNILATERAL_CLOSE,
|
FEERATE_UNILATERAL_CLOSE,
|
||||||
|
|||||||
@@ -290,6 +290,11 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
|
|||||||
* each invoice we generate has a different set of channels. */
|
* each invoice we generate has a different set of channels. */
|
||||||
ld->rr_counter = 0;
|
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;
|
return ld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,10 @@ struct lightningd {
|
|||||||
/* RPC response to send once we've shut down. */
|
/* RPC response to send once we've shut down. */
|
||||||
const char *stop_response;
|
const char *stop_response;
|
||||||
|
|
||||||
|
/* Used these feerates instead of whatever bcli returns (up to
|
||||||
|
* FEERATE_PENALTY). */
|
||||||
|
u32 *force_feerates;
|
||||||
|
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
/* If we want to debug a subdaemon/plugin. */
|
/* If we want to debug a subdaemon/plugin. */
|
||||||
const char *dev_debug_subprocess;
|
const char *dev_debug_subprocess;
|
||||||
|
|||||||
@@ -131,6 +131,51 @@ static char *opt_set_mode(const char *arg, mode_t *m)
|
|||||||
return NULL;
|
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
|
#if EXPERIMENTAL_FEATURES
|
||||||
static char *opt_set_accept_extra_tlv_types(const char *arg,
|
static char *opt_set_accept_extra_tlv_types(const char *arg,
|
||||||
struct lightningd *ld)
|
struct lightningd *ld)
|
||||||
@@ -1003,6 +1048,10 @@ static void register_opts(struct lightningd *ld)
|
|||||||
"Set the file mode (permissions) for the "
|
"Set the file mode (permissions) for the "
|
||||||
"JSON-RPC socket");
|
"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,
|
opt_register_arg("--subdaemon", opt_subdaemon, NULL,
|
||||||
ld, "Arg specified as SUBDAEMON:PATH. "
|
ld, "Arg specified as SUBDAEMON:PATH. "
|
||||||
"Specifies an alternate subdaemon binary. "
|
"Specifies an alternate subdaemon binary. "
|
||||||
@@ -1423,6 +1472,8 @@ static void add_config(struct lightningd *ld,
|
|||||||
json_add_opt_log_levels(response, ld->log);
|
json_add_opt_log_levels(response, ld->log);
|
||||||
} else if (opt->cb_arg == (void *)opt_disable_plugin) {
|
} else if (opt->cb_arg == (void *)opt_disable_plugin) {
|
||||||
json_add_opt_disable_plugins(response, ld->plugins);
|
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) {
|
} else if (opt->cb_arg == (void *)opt_important_plugin) {
|
||||||
/* Do nothing, this is already handled by
|
/* Do nothing, this is already handled by
|
||||||
* opt_add_plugin. */
|
* opt_add_plugin. */
|
||||||
|
|||||||
@@ -2561,3 +2561,48 @@ def test_getlog(node_factory):
|
|||||||
# This should not
|
# This should not
|
||||||
logs = l1.rpc.getlog(level='io')['log']
|
logs = l1.rpc.getlog(level='io')['log']
|
||||||
assert [l for l in logs if l['type'] == 'SKIPPED'] == []
|
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}
|
||||||
|
|||||||
Reference in New Issue
Block a user