diff --git a/Makefile b/Makefile index 5014b024d..2bedf13e4 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json index 30fa4209c..123ccba89 100644 --- a/contrib/msggen/msggen/schema.json +++ b/contrib/msggen/msggen/schema.json @@ -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, diff --git a/doc/developers-guide/deprecations.md b/doc/developers-guide/deprecations.md index fa2880177..df4da8826 100644 --- a/doc/developers-guide/deprecations.md +++ b/doc/developers-guide/deprecations.md @@ -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. diff --git a/doc/getting-started/getting-started/configuration.md b/doc/getting-started/getting-started/configuration.md index 3afc7d013..e75338cf0 100644 --- a/doc/getting-started/getting-started/configuration.md +++ b/doc/getting-started/getting-started/configuration.md @@ -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. diff --git a/doc/lightningd-config.5.md b/doc/lightningd-config.5.md index 71bcb3340..1f9eb3723 100644 --- a/doc/lightningd-config.5.md +++ b/doc/lightningd-config.5.md @@ -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 diff --git a/doc/schemas/lightning-listconfigs.json b/doc/schemas/lightning-listconfigs.json index 2015f53f7..071c17d5b 100644 --- a/doc/schemas/lightning-listconfigs.json +++ b/doc/schemas/lightning-listconfigs.json @@ -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, diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 075bfd88c..8b1d973b7 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -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; diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index b9019659d..7576d6149 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -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, diff --git a/lightningd/options.c b/lightningd/options.c index 040dec479..8c794f271 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -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"); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 02423d4b1..c0fcfe28c 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -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; } diff --git a/plugins/keysend.c b/plugins/keysend.c index e240184a0..4bc48e4da 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -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), diff --git a/plugins/pay.c b/plugins/pay.c index 40031ea04..be01b4403 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -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)); diff --git a/plugins/renepay/main.c b/plugins/renepay/main.c index b7e83cdf3..4ca6707f1 100644 --- a/plugins/renepay/main.c +++ b/plugins/renepay/main.c @@ -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) diff --git a/tests/test_connection.py b/tests/test_connection.py index 2feeeb570..7df2b3881 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -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)