BOLT: update to include 2016 for max_htlc_cltv.

And deprecate the --max-locktime-blocks which allows them to set it.

Hilariously, the spec misspells CLTV as CTLV at one point, so we work around it for now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-03-18 14:37:02 +10:30 committed by Alex Myers
parent bbb6fd4413
commit cca784c9d0
14 changed files with 80 additions and 29 deletions

View file

@ -26,7 +26,7 @@ CCANDIR := ccan
# Where we keep the BOLT RFCs
BOLTDIR := ../bolts/
DEFAULT_BOLTVERSION := 4dcc377209509b13cf89a4b91fde7d478f5b46d8
DEFAULT_BOLTVERSION := 8a64c6a1cef979b3f0cecb00ba7a48c2d28b3588
# Can be overridden on cmdline.
BOLTVERSION := $(DEFAULT_BOLTVERSION)

View file

@ -14695,6 +14695,10 @@
},
"max-locktime-blocks": {
"type": "object",
"deprecated": [
"v24.05",
"v24.11"
],
"additionalProperties": false,
"required": [
"value_int",
@ -16404,7 +16408,6 @@
"pid-file": "/media/vincent/Maxtor/sanboxTestWrapperRPC/lightning_dir_dev/lightningd-testne...",
"ignore-fee-limits": true,
"watchtime-blocks": 6,
"max-locktime-blocks": 2016,
"funding-confirms": 1,
"commit-fee-min": 0,
"commit-fee-max": 0,

View file

@ -34,6 +34,7 @@ hidden: false
| estimatefees.min_acceptable | Field | v23.05 | v24.05 | `min_acceptable` feerate (implementation-specific, use modern feerates) |
| estimatefees.max_acceptable | Field | v23.05 | v24.05 | `max_acceptable` feerate (implementation-specific, use modern feerates) |
| offer.recurrence_base.at_prefix | Parameter | v24.02 | v24.05 | `recurrence_base` with `@` prefix (use `recurrence_start_any_period`) |
| max-locktime-blocks | Config | v24.05 | v24.11 | --max-locktime-blocks is now set to 2016 in the BOLT 4 spec |
Inevitably there are features which need to change: either to be generalized, or removed when they can no longer be supported.

View file

@ -292,7 +292,7 @@ The [`lightning-listconfigs`](ref:lightning-listconfigs) command will output a v
How long we need to spot an outdated close attempt: on opening a channel we tell our peer that this is how long they'll have to wait if they perform a unilateral close.
- **max-locktime-blocks**=_BLOCKS_
- **max-locktime-blocks**=_BLOCKS_ (*deprecated* in 24.05, *removed* in 24.11)
The longest our funds can be delayed (ie. the longest **watchtime-blocks** our peer can ask for, and also the longest HTLC timeout we will accept). If our peer asks for longer, we'll refuse to create a channel, and if an HTLC asks for longer, we'll refuse it.

View file

@ -408,7 +408,7 @@ use the RPC call lightning-setchannel(7).
we tell our peer that this is how long they'll have to wait if they
perform a unilateral close.
* **max-locktime-blocks**=*BLOCKS*
* (deprecated in v23.05) **max-locktime-blocks**=*BLOCKS*
The longest our funds can be delayed (ie. the longest
**watchtime-blocks** our peer can ask for, and also the longest HTLC

View file

@ -795,6 +795,10 @@
},
"max-locktime-blocks": {
"type": "object",
"deprecated": [
"v24.05",
"v24.11"
],
"additionalProperties": false,
"required": [
"value_int",
@ -2504,7 +2508,6 @@
"pid-file": "/media/vincent/Maxtor/sanboxTestWrapperRPC/lightning_dir_dev/lightningd-testne...",
"ignore-fee-limits": true,
"watchtime-blocks": 6,
"max-locktime-blocks": 2016,
"funding-confirms": 1,
"commit-fee-min": 0,
"commit-fee-max": 0,

View file

@ -18,8 +18,8 @@ struct config {
/* How long do we want them to lock up their funds? (blocks) */
u32 locktime_blocks;
/* How long do we let them lock up our funds? (blocks) */
u32 locktime_max;
/* How long do we let them lock up our funds? (blocks: 2016 by spec) */
u32 max_htlc_cltv;
/* How many confirms until we consider an anchor "settled". */
u32 anchor_confirms;

View file

@ -139,7 +139,7 @@ void channel_config(struct lightningd *ld,
struct amount_msat *min_effective_htlc_capacity)
{
/* FIXME: depend on feerate. */
*max_to_self_delay = ld->config.locktime_max;
*max_to_self_delay = ld->config.max_htlc_cltv;
/* Take minimal effective capacity from config min_capacity_sat */
if (!amount_sat_to_msat(min_effective_htlc_capacity,

View file

@ -685,6 +685,15 @@ static char *opt_set_hsm_password(struct lightningd *ld)
return NULL;
}
static char *opt_set_max_htlc_cltv(const char *arg, struct lightningd *ld)
{
if (!opt_deprecated_ok(ld, "max-locktime-blocks", NULL,
"v24.05", "v24.11"))
return "--max-locktime-blocks has been deprecated (BOLT #4 says 2016)";
return opt_set_u32(arg, &ld->config.max_htlc_cltv);
}
static char *opt_force_privkey(const char *optarg, struct lightningd *ld)
{
tal_free(ld->dev_force_privkey);
@ -954,9 +963,14 @@ static const struct config testnet_config = {
/* 6 blocks to catch cheating attempts. */
.locktime_blocks = 6,
/* They can have up to 14 days, maximumu value that lnd will ask for by default. */
/* FIXME Convince lnd to use more reasonable defaults... */
.locktime_max = 14 * 24 * 6,
/* BOLT #4:
* ## `max_htlc_cltv` Selection
*
* This ... value is defined as 2016 blocks, based on historical value
* deployed by Lightning implementations.
*/
/* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */
.max_htlc_cltv = 2016,
/* We're fairly trusting, under normal circumstances. */
.anchor_confirms = 1,
@ -1019,9 +1033,14 @@ static const struct config mainnet_config = {
/* ~one day to catch cheating attempts. */
.locktime_blocks = 6 * 24,
/* They can have up to 14 days, maximumu value that lnd will ask for by default. */
/* FIXME Convince lnd to use more reasonable defaults... */
.locktime_max = 14 * 24 * 6,
/* BOLT #4:
* ## `max_htlc_cltv` Selection
*
* This ... value is defined as 2016 blocks, based on historical value
* deployed by Lightning implementations.
*/
/* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */
.max_htlc_cltv = 2016,
/* We're fairly trusting, under normal circumstances. */
.anchor_confirms = 3,
@ -1512,9 +1531,8 @@ static void register_opts(struct lightningd *ld)
clnopt_witharg("--watchtime-blocks", OPT_SHOWINT, opt_set_u32, opt_show_u32,
&ld->config.locktime_blocks,
"Blocks before peer can unilaterally spend funds");
clnopt_witharg("--max-locktime-blocks", OPT_SHOWINT, opt_set_u32, opt_show_u32,
&ld->config.locktime_max,
"Maximum blocks funds may be locked for");
opt_register_arg("--max-locktime-blocks", opt_set_max_htlc_cltv, NULL,
ld, opt_hidden);
clnopt_witharg("--funding-confirms", OPT_SHOWINT, opt_set_u32, opt_show_u32,
&ld->config.anchor_confirms,
"Confirmations required for funding transaction");

View file

@ -805,16 +805,16 @@ static void forward_htlc(struct htlc_in *hin,
/* BOLT #4:
*
* - if the `cltv_expiry` is unreasonably far in the future:
* - if the `cltv_expiry` is more than `max_htlc_cltv` in the future:
* - return an `expiry_too_far` error.
*/
if (get_block_height(ld->topology)
+ ld->config.locktime_max < outgoing_cltv_value) {
+ ld->config.max_htlc_cltv < outgoing_cltv_value) {
log_debug(hin->key.channel->log,
"Expiry cltv %u too far from current %u + max %u",
outgoing_cltv_value,
get_block_height(ld->topology),
ld->config.locktime_max);
ld->config.max_htlc_cltv);
failmsg = towire_expiry_too_far(tmpctx);
goto fail;
}

View file

@ -159,10 +159,19 @@ static const char *init(struct plugin *p, const char *buf UNUSED,
JSON_SCAN(json_to_node_id, &my_id));
accepted_extra_tlvs = notleak(tal_arr(NULL, u64, 0));
/* BOLT #4:
* ## `max_htlc_cltv` Selection
*
* This ... value is defined as 2016 blocks, based on historical value
* deployed by Lightning implementations.
*/
/* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */
maxdelay_default = 2016;
/* accept-htlc-tlv-types deprecated in v23.08, but still grab it! */
/* max-locktime-blocks deprecated in v24.05, but still grab it! */
rpc_scan(p, "listconfigs", take(json_out_obj(NULL, NULL, NULL)),
"{configs:{"
"max-locktime-blocks:{value_int:%},"
"max-locktime-blocks?:{value_int:%},"
"accept-htlc-tlv-types?:{value_str:%},"
"accept-htlc-tlv-type:{values_int:%}}}",
JSON_SCAN(json_to_u32, &maxdelay_default),

View file

@ -575,10 +575,19 @@ static const char *init(struct plugin *p,
rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)),
"{id:%}", JSON_SCAN(json_to_node_id, &my_id));
/* BOLT #4:
* ## `max_htlc_cltv` Selection
*
* This ... value is defined as 2016 blocks, based on historical value
* deployed by Lightning implementations.
*/
/* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */
maxdelay_default = 2016;
/* max-locktime-blocks deprecated in v24.05, but still grab it! */
rpc_scan(p, "listconfigs",
take(json_out_obj(NULL, NULL, NULL)),
"{configs:"
"{max-locktime-blocks:{value_int:%},"
"{max-locktime-blocks?:{value_int:%},"
"experimental-offers:{set:%}}}",
JSON_SCAN(json_to_number, &maxdelay_default),
JSON_SCAN(json_to_bool, &exp_offers));

View file

@ -47,10 +47,19 @@ static const char *init(struct plugin *p,
rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)),
"{id:%}", JSON_SCAN(json_to_node_id, &pay_plugin->my_id));
/* BOLT #4:
* ## `max_htlc_cltv` Selection
*
* This ... value is defined as 2016 blocks, based on historical value
* deployed by Lightning implementations.
*/
/* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */
pay_plugin->maxdelay_default = 2016;
/* max-locktime-blocks deprecated in v24.05, but still grab it! */
rpc_scan(p, "listconfigs",
take(json_out_obj(NULL, NULL, NULL)),
"{configs:"
"{max-locktime-blocks:{value_int:%},"
"{max-locktime-blocks?:{value_int:%},"
"experimental-offers:{set:%}}}",
JSON_SCAN(json_to_number, &pay_plugin->maxdelay_default),
JSON_SCAN(json_to_bool, &pay_plugin->exp_offers)

View file

@ -331,8 +331,8 @@ def test_balance(node_factory):
@pytest.mark.openchannel('v2')
def test_bad_opening(node_factory):
# l1 asks for a too-long locktime
l1 = node_factory.get_node(options={'watchtime-blocks': 100})
l2 = node_factory.get_node(options={'max-locktime-blocks': 99})
l1 = node_factory.get_node(options={'watchtime-blocks': 2017})
l2 = node_factory.get_node()
ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
assert ret['id'] == l2.info['id']
@ -344,7 +344,7 @@ def test_bad_opening(node_factory):
with pytest.raises(RpcError):
l1.rpc.fundchannel(l2.info['id'], 10**6)
l2.daemon.wait_for_log('to_self_delay 100 larger than 99')
l2.daemon.wait_for_log('to_self_delay 2017 larger than 2016')
@unittest.skipIf(TEST_NETWORK != 'regtest', "Fee computation and limits are network specific")
@ -1117,9 +1117,8 @@ def test_funding_all_too_much(node_factory):
@pytest.mark.openchannel('v2')
def test_funding_fail(node_factory, bitcoind):
"""Add some funds, fund a channel without enough funds"""
# Previous runs with same bitcoind can leave funds!
max_locktime = 5 * 6 * 24
l1 = node_factory.get_node(random_hsm=True, options={'max-locktime-blocks': max_locktime})
max_locktime = 2016
l1 = node_factory.get_node()
l2 = node_factory.get_node(options={'watchtime-blocks': max_locktime + 1})
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)