diff --git a/contrib/pyln-spec/Makefile b/contrib/pyln-spec/Makefile index 5ed10647ca2e..2fc7ced39655 100755 --- a/contrib/pyln-spec/Makefile +++ b/contrib/pyln-spec/Makefile @@ -9,6 +9,7 @@ BASEVERSION := $(shell echo $(GITDESCRIBE) | sed 's/^v//' | sed 's/-.*//') POSTVERSION := $(shell echo $(GITDESCRIBE) | sed 's/[^-]*-\([^-]*\)-.*/\1/') # This maintains -dirty, if present. GITVERSION := $(shell echo $(GITDESCRIBE) | sed 's/.*-g//') +IGNORE := text.py,.venv BOLTS := 1 2 4 7 @@ -24,14 +25,14 @@ check-source-flake8: $(DIRS:%=check-source-flake8-%) check-source-mypy: $(DIRS:%=check-source-mypy-%) check-source-flake8-%: - cd $* && flake8 --ignore=E501,E731,W503,E741 --exclude=text.py + cd $* && flake8 --ignore=E501,E731,W503,E741 --exclude=${IGNORE} # mypy . does not recurse. I have no idea why... check-source-mypy-%: - cd $* && mypy --ignore-missing-imports `find * -name '*.py'` + cd $* && poetry run mypy --ignore-missing-imports `find * -name '*.py'` # Given a bolt number and a variable, get the value from inside the package. -extract = $(shell python3 -c 'from pyln.spec import bolt$1 as bolt;print(bolt.$2)') +extract = $(shell PYTHONPATH=bolt$1 python3 -c 'from pyln.spec import bolt$1 as bolt;print(bolt.$2)') # Get the version for this bolt version = $(call extract,$1,__version__) diff --git a/contrib/pyln-spec/bolt1/pyproject.toml b/contrib/pyln-spec/bolt1/pyproject.toml index c6ee8219eb12..5b85b7c5014e 100644 --- a/contrib/pyln-spec/bolt1/pyproject.toml +++ b/contrib/pyln-spec/bolt1/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pyln-bolt1" -version = "1.0.1.187.post0" +version = "1.0.222" description = "" authors = ["Rusty Russell "] license = "MIT" @@ -14,6 +14,9 @@ python = "^3.7" [tool.poetry.dev-dependencies] pyln-proto = "^0.10.2" +pytest = "^7.1.2" +mypy = "^0.971" +typing-extensions = "^4.3.0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/csv.py b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/csv.py index b24b32454e4e..78233b9641bb 100644 --- a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/csv.py +++ b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/csv.py @@ -51,9 +51,12 @@ "msgtype,funding_signed,35", "msgdata,funding_signed,channel_id,channel_id,", "msgdata,funding_signed,signature,signature,", - "msgtype,funding_locked,36", - "msgdata,funding_locked,channel_id,channel_id,", - "msgdata,funding_locked,next_per_commitment_point,point,", + "msgtype,channel_ready,36", + "msgdata,channel_ready,channel_id,channel_id,", + "msgdata,channel_ready,second_per_commitment_point,point,", + "msgdata,channel_ready,tlvs,channel_ready_tlvs,", + "tlvtype,channel_ready_tlvs,short_channel_id,1", + "tlvdata,channel_ready_tlvs,short_channel_id,alias,short_channel_id,", "msgtype,shutdown,38", "msgdata,shutdown,channel_id,channel_id,", "msgdata,shutdown,len,u16,", diff --git a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_csv_version.py b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_csv_version.py index 2140fc8212ff..0741f08250cc 100644 --- a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_csv_version.py +++ b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_csv_version.py @@ -1 +1 @@ -__csv_version__ = "2" +__csv_version__ = "1" diff --git a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_version.py b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_version.py index 3377756caf44..fe86b5a5abaf 100644 --- a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_version.py +++ b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/gen_version.py @@ -1,3 +1,3 @@ __base_version__ = "1.0" -__post_version__ = "222" -__gitversion__ = "f1c797df2966237244527c1c6343dbe9bc765342" +__post_version__ = "246" +__gitversion__ = "f32c6ddb5f11b431c9bb4f501cdec604172a90de" diff --git a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/text.py b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/text.py index 66ba1fbb4e22..3c63f4c4f9d4 100644 --- a/contrib/pyln-spec/bolt2/pyln/spec/bolt2/text.py +++ b/contrib/pyln-spec/bolt2/pyln/spec/bolt2/text.py @@ -13,7 +13,7 @@ * [The `accept_channel` Message](#the-accept_channel-message) * [The `funding_created` Message](#the-funding_created-message) * [The `funding_signed` Message](#the-funding_signed-message) - * [The `funding_locked` Message](#the-funding_locked-message) + * [The `channel_ready` Message](#the-channel_ready-message) * [Channel Close](#channel-close) * [Closing Initiation: `shutdown`](#closing-initiation-shutdown) * [Closing Negotiation: `closing_signed`](#closing-negotiation-closing_signed) @@ -71,8 +71,8 @@ the `funding_signed` message is sent/received, both sides should wait for the funding transaction to enter the blockchain and reach the specified depth (number of confirmations). After both sides have sent -the `funding_locked` message, the channel is established and can begin -normal operation. The `funding_locked` message includes information +the `channel_ready` message, the channel is established and can begin +normal operation. The `channel_ready` message includes information that will be used to construct channel authentication proofs. @@ -83,8 +83,8 @@ | A |--(3)-- funding_created --->| B | | |<-(4)-- funding_signed -----| | | | | | - | |--(5)--- funding_locked ---->| | - | |<-(6)--- funding_locked -----| | + | |--(5)--- channel_ready ---->| | + | |<-(6)--- channel_ready -----| | +-------+ +-------+ - where node A is 'funder' and node B is 'fundee' @@ -208,12 +208,16 @@ arbitrary combination (they represent the persistent features which affect the channel operation). -The currently defined types are: +The currently defined basic types are: - no features (no bits set) - `option_static_remotekey` (bit 12) - `option_anchor_outputs` and `option_static_remotekey` (bits 20 and 12) - `option_anchors_zero_fee_htlc_tx` and `option_static_remotekey` (bits 22 and 12) +Each basic type has the following variations allowed: + - `option_scid_alias` (bit 46) + - `option_zeroconf` (bit 50) + #### Requirements The sending node: @@ -240,6 +244,8 @@ - MUST set it to a defined type representing the type it wants. - MUST use the smallest bitmap possible to represent the channel type. - SHOULD NOT set it to a type containing a feature which was not negotiated. + - if `announce_channel` is `true` (not `0`): + - MUST NOT send `channel_type` with the `option_scid_alias` bit set. The sending node SHOULD: - set `to_self_delay` sufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehavior by the receiver. @@ -277,7 +283,9 @@ - the funder's amount for the initial commitment transaction is not sufficient for full [fee payment](03-transactions.md#fee-payment). - both `to_local` and `to_remote` amounts for the initial commitment transaction are less than or equal to `channel_reserve_satoshis` (see [BOLT 3](03-transactions.md#commitment-transaction-outputs)). - `funding_satoshis` is greater than or equal to 2^24 and the receiver does not support `option_support_large_channel`. - - It supports `channel_type`, `channel_type` was set, and the `type` is not suitable. + - It supports `channel_type` and `channel_type` was set: + - if `type` is not suitable. + - if `type` includes `option_zeroconf` and it does not trust the sender to open an unconfirmed channel. The receiving node MUST NOT: - consider funds received, using `push_msat`, to be received until the funding transaction has reached sufficient depth. @@ -345,8 +353,10 @@ the `open_channel` message. The sender: - - SHOULD set `minimum_depth` to a number of blocks it considers reasonable to -avoid double-spending of the funding transaction. + - if `channel_type` includes `option_zeroconf`: + - MUST set `minimum_depth` to zero. + - otherwise: + - SHOULD set `minimum_depth` to a number of blocks it considers reasonable to avoid double-spending of the funding transaction. - MUST set `channel_reserve_satoshis` greater than or equal to `dust_limit_satoshis` from the `open_channel` message. - MUST set `dust_limit_satoshis` less than or equal to `channel_reserve_satoshis` from the `open_channel` message. - if `option_channel_type` was negotiated: @@ -464,31 +474,67 @@ `option_static_remotekey`, and the superior one is favored if more than one is negotiated. -### The `funding_locked` Message +### The `channel_ready` Message + +This message (which used to be called `funding_locked`) indicates that the funding transaction has sufficient confirms for channel use. Once both nodes have sent this, the channel enters normal operating mode. -This message indicates that the funding transaction has reached the `minimum_depth` asked for in `accept_channel`. Once both nodes have sent this, the channel enters normal operating mode. +Note that the opener is free to send this message at any time (since it presumably trusts itself), but the +accepter would usually wait until the funding has reached the `minimum_depth` asked for in `accept_channel`. -1. type: 36 (`funding_locked`) +1. type: 36 (`channel_ready`) 2. data: * [`channel_id`:`channel_id`] - * [`point`:`next_per_commitment_point`] + * [`point`:`second_per_commitment_point`] + * [`channel_ready_tlvs`:`tlvs`] + +1. `tlv_stream`: `channel_ready_tlvs` +2. types: + 1. type: 1 (`short_channel_id`) + 2. data: + * [`short_channel_id`:`alias`] #### Requirements -The sender MUST: - - NOT send `funding_locked` unless outpoint of given by `funding_txid` and +The sender: + - MUST NOT send `channel_ready` unless outpoint of given by `funding_txid` and `funding_output_index` in the `funding_created` message pays exactly `funding_satoshis` to the scriptpubkey specified in [BOLT #3](03-transactions.md#funding-transaction-output). - - wait until the funding transaction has reached `minimum_depth` before - sending this message. - - set `next_per_commitment_point` to the per-commitment point to be used - for the following commitment transaction, derived as specified in + - if it is not the node opening the channel: + - SHOULD wait until the funding transaction has reached `minimum_depth` before + sending this message. + - MUST set `second_per_commitment_point` to the per-commitment point to be used + for commitment transaction #1, derived as specified in [BOLT #3](03-transactions.md#per-commitment-secret-requirements). + - if `option_scid_alias` was negotiated: + - MUST set `short_channel_id` `alias`. + - otherwise: + - MAY set `short_channel_id` `alias`. + - if it sets `alias`: + - if the `announce_channel` bit was set in `open_channel`: + - SHOULD initially set `alias` to value not related to the real `short_channel_id`. + - otherwise: + - MUST set `alias` to a value not related to the real `short_channel_id`. + - MUST NOT send the same `alias` for multiple peers or use an alias which + collides with a `short_channel_id` of a channel on the same node. + - MUST always recognize the `alias` as a `short_channel_id` for incoming HTLCs to this channel. + - if `channel_type` has `option_scid_alias` set: + - MUST NOT allow incoming HTLCs to this channel using the real `short_channel_id` + - MAY send multiple `channel_ready` messages to the same peer with different `alias` values. + - otherwise: + - MUST wait until the funding transaction has reached `minimum_depth` before sending this message. + + +The sender: A non-funding node (fundee): - SHOULD forget the channel if it does not see the correct funding - transaction after a timeout of 2016 blocks. + transaction after a timeout of 2016 blocks. -From the point of waiting for `funding_locked` onward, either node MAY +The receiver: + - MAY use any of the `alias` it received, in BOLT 11 `r` fields. + - if `channel_type` has `option_scid_alias` set: + - MUST NOT use the real `short_channel_id` in BOLT 11 `r` fields. + +From the point of waiting for `channel_ready` onward, either node MAY send an `error` and fail the channel if it does not receive a required response from the other node after a reasonable timeout. @@ -504,6 +550,17 @@ channel. To avoid this, the funder should ensure the funding transaction confirms in the next 2016 blocks. +The `alias` here is required for two distinct use cases. The first one is +for routing payments through channels that are not confirmed yet (since +the real `short_channel_id` is unknown until confirmation). The second one +is to provide one or more aliases to use for private channels (even once +a real `short_channel_id` is available). + +While a node can send multiple `alias`, it must remember all of the +ones it has sent so it can use them should they be requested by +incoming HTLCs. The recipient only need remember one, for use in +`r` route hints in BOLT 11 invoices. + ## Channel Close Nodes can negotiate a mutual close of the connection, which unlike a @@ -544,12 +601,14 @@ A sending node: - if it hasn't sent a `funding_created` (if it is a funder) or a `funding_signed` (if it is a fundee): - MUST NOT send a `shutdown` - - MAY send a `shutdown` before a `funding_locked`, i.e. before the funding transaction has reached `minimum_depth`. + - MAY send a `shutdown` before a `channel_ready`, i.e. before the funding transaction has reached `minimum_depth`. - if there are updates pending on the receiving node's commitment transaction: - MUST NOT send a `shutdown`. + - MUST NOT send multiple `shutdown` messages. - MUST NOT send an `update_add_htlc` after a `shutdown`. - - if no HTLCs remain in either commitment transaction: - - MUST NOT send any `update` message after a `shutdown`. + - if no HTLCs remain in either commitment transaction (including dust HTLCs) + and neither side has a pending `revoke_and_ack` to send: + - MUST NOT send any `update` message after that point. - SHOULD fail to route any HTLC added after it has sent `shutdown`. - if it sent a non-zero-length `shutdown_scriptpubkey` in `open_channel` or `accept_channel`: - MUST send the same value in `scriptpubkey`. @@ -566,7 +625,7 @@ - SHOULD send an `error` and fail the channel. - if the `scriptpubkey` is not in one of the above forms: - SHOULD send a `warning`. - - if it hasn't sent a `funding_locked` yet: + - if it hasn't sent a `channel_ready` yet: - MAY reply to a `shutdown` message with a `shutdown` - once there are no outstanding updates on the peer, UNLESS it has already sent a `shutdown`: - MUST reply to a `shutdown` message with a `shutdown` @@ -581,10 +640,13 @@ the sender always sends a `commitment_signed` first. As shutdown implies a desire to terminate, it implies that no new -HTLCs will be added or accepted. Once any HTLCs are cleared, the peer -may immediately begin closing negotiation, so we ban further updates -to the commitment transaction (in particular, `update_fee` would be -possible otherwise). +HTLCs will be added or accepted. Once any HTLCs are cleared, there are no commitments +for which a revocation is owed, and all updates are included on both commitment +transactions, the peer may immediately begin closing negotiation, so we ban further +updates to the commitment transaction (in particular, `update_fee` would be +possible otherwise). However, while there are HTLCs on the commitment transaction, +the initiator may find it desirable to increase the feerate as there may be pending +HTLCs on the commitment which could timeout. The `scriptpubkey` forms include only standard segwit forms accepted by the Bitcoin network, which ensures the resulting transaction will @@ -603,8 +665,9 @@ ### Closing Negotiation: `closing_signed` -Once shutdown is complete and the channel is empty of HTLCs, the final -current commitment transactions will have no HTLCs, and closing fee +Once shutdown is complete, the channel is empty of HTLCs, there are no commitments +for which a revocation is owed, and all updates are included on both commitments, +the final current commitment transactions will have no HTLCs, and closing fee negotiation begins. The funder chooses a fee it thinks is fair, and signs the closing transaction with the `scriptpubkey` fields from the `shutdown` messages (along with its chosen fee) and sends the signature; @@ -716,7 +779,7 @@ ## Normal Operation -Once both nodes have exchanged `funding_locked` (and optionally [`announcement_signatures`](07-routing-gossip.md#the-announcement_signatures-message)), the channel can be used to make payments via Hashed Time Locked Contracts. +Once both nodes have exchanged `channel_ready` (and optionally [`announcement_signatures`](07-routing-gossip.md#the-announcement_signatures-message)), the channel can be used to make payments via Hashed Time Locked Contracts. Changes are sent in batches: one or more `update_` messages are sent before a `commitment_signed` message, as in the following diagram: @@ -1370,11 +1433,12 @@ A node: - if `next_commitment_number` is 1 in both the `channel_reestablish` it sent and received: - - MUST retransmit `funding_locked`. + - MUST retransmit `channel_ready`. - otherwise: - - MUST NOT retransmit `funding_locked`. + - MUST NOT retransmit `channel_ready`, but MAY send `channel_ready` with + a different `short_channel_id` `alias` field. - upon reconnection: - - MUST ignore any redundant `funding_locked` it receives. + - MUST ignore any redundant `channel_ready` it receives. - if `next_commitment_number` is equal to the commitment number of the last `commitment_signed` message the receiving node has sent: - MUST reuse the same commitment number for its next `commitment_signed`. @@ -1442,7 +1506,7 @@ is if the `funding_signed` message is sent but not received. In this case, the funder will forget the channel, and presumably open a new one upon reconnection; meanwhile, the other node will eventually forget -the original channel, due to never receiving `funding_locked` or seeing +the original channel, due to never receiving `channel_ready` or seeing the funding transaction on-chain. There's no acknowledgment for `error`, so if a reconnect occurs it's @@ -1478,7 +1542,7 @@ `commitment_signed` for commitment number 1 is send and then the revocation for commitment number 0 is received. -`funding_locked` is implicitly acknowledged by the start of normal +`channel_ready` is implicitly acknowledged by the start of normal operation, which is known to have begun after a `commitment_signed` has been received — hence, the test for a `next_commitment_number` greater than 1. diff --git a/contrib/pyln-spec/bolt2/pyproject.toml b/contrib/pyln-spec/bolt2/pyproject.toml index 10367daa99b8..9052b90886ae 100644 --- a/contrib/pyln-spec/bolt2/pyproject.toml +++ b/contrib/pyln-spec/bolt2/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pyln-bolt2" -version = "1.0.2.187.post0" +version = "1.0.246" description = "A pure python implementation of BOLT2" authors = ["Rusty Russell "] license = "MIT" @@ -14,6 +14,9 @@ python = "^3.7" [tool.poetry.dev-dependencies] pyln-proto = "^0.10.2" +pytest = "^7.1.2" +mypy = "^0.971" +typing-extensions = "^4.3.0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/contrib/pyln-spec/bolt4/pyproject.toml b/contrib/pyln-spec/bolt4/pyproject.toml index 1d3361de1b91..39c3884fa419 100644 --- a/contrib/pyln-spec/bolt4/pyproject.toml +++ b/contrib/pyln-spec/bolt4/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pyln-bolt4" -version = "1.0.2.187.post0" +version = "1.0.222" description = "A pure python implementation of BOLT4" authors = ["Rusty Russell "] license = "MIT" @@ -14,6 +14,9 @@ python = "^3.7" [tool.poetry.dev-dependencies] pyln-proto = "^0.10.2" +pytest = "^7.1.2" +mypy = "^0.971" +typing-extensions = "^4.3.0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/contrib/pyln-spec/bolt7/pyln/spec/bolt7/csv.py b/contrib/pyln-spec/bolt7/pyln/spec/bolt7/csv.py index d94248c545a7..80d60c1a286b 100644 --- a/contrib/pyln-spec/bolt7/pyln/spec/bolt7/csv.py +++ b/contrib/pyln-spec/bolt7/pyln/spec/bolt7/csv.py @@ -38,7 +38,7 @@ "msgdata,channel_update,htlc_minimum_msat,u64,", "msgdata,channel_update,fee_base_msat,u32,", "msgdata,channel_update,fee_proportional_millionths,u32,", - "msgdata,channel_update,htlc_maximum_msat,u64,,option_channel_htlc_max", + "msgdata,channel_update,htlc_maximum_msat,u64,", "msgtype,query_short_channel_ids,261,gossip_queries", "msgdata,query_short_channel_ids,chain_hash,chain_hash,", "msgdata,query_short_channel_ids,len,u16,", diff --git a/contrib/pyln-spec/bolt7/pyln/spec/bolt7/gen_version.py b/contrib/pyln-spec/bolt7/pyln/spec/bolt7/gen_version.py index 3377756caf44..fe86b5a5abaf 100644 --- a/contrib/pyln-spec/bolt7/pyln/spec/bolt7/gen_version.py +++ b/contrib/pyln-spec/bolt7/pyln/spec/bolt7/gen_version.py @@ -1,3 +1,3 @@ __base_version__ = "1.0" -__post_version__ = "222" -__gitversion__ = "f1c797df2966237244527c1c6343dbe9bc765342" +__post_version__ = "246" +__gitversion__ = "f32c6ddb5f11b431c9bb4f501cdec604172a90de" diff --git a/contrib/pyln-spec/bolt7/pyln/spec/bolt7/text.py b/contrib/pyln-spec/bolt7/pyln/spec/bolt7/text.py index 84c430ec8a2b..404303a26ddd 100644 --- a/contrib/pyln-spec/bolt7/pyln/spec/bolt7/text.py +++ b/contrib/pyln-spec/bolt7/pyln/spec/bolt7/text.py @@ -86,7 +86,7 @@ A node: - if the `open_channel` message has the `announce_channel` bit set AND a `shutdown` message has not been sent: - MUST send the `announcement_signatures` message. - - MUST NOT send `announcement_signatures` messages until `funding_locked` + - MUST NOT send `announcement_signatures` messages until `channel_ready` has been sent and received AND the funding transaction has at least six confirmations. - otherwise: - MUST NOT send the `announcement_signatures` message. @@ -105,8 +105,8 @@ `error` and fail the channel. - if it has sent AND received a valid `announcement_signatures` message: - SHOULD queue the `channel_announcement` message for its peers. - - if it has not sent funding_locked: - - MAY defer handling the announcement_signatures until after it has sent funding_locked + - if it has not sent `channel_ready`: + - MAY defer handling the announcement_signatures until after it has sent `channel_ready` - otherwise: - MUST ignore it. @@ -168,7 +168,7 @@ - for the _Bitcoin blockchain_: - MUST set `chain_hash` value (encoded in hex) equal to `6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000`. - MUST set `short_channel_id` to refer to the confirmed funding transaction, - as specified in [BOLT #2](02-peer-protocol.md#the-funding_locked-message). + as specified in [BOLT #2](02-peer-protocol.md#the-channel_ready-message). - Note: the corresponding output MUST be a P2WSH, as described in [BOLT #3](03-transactions.md#funding-transaction-output). - MUST set `node_id_1` and `node_id_2` to the public keys of the two nodes operating the channel, such that `node_id_1` is the lexicographically-lesser of the @@ -225,7 +225,7 @@ - otherwise: - SHOULD store this `channel_announcement`. - once its funding output has been spent OR reorganized out: - - SHOULD forget a channel. + - SHOULD forget a channel after a 12-block delay. ### Rationale @@ -250,6 +250,10 @@ will have _even_ feature bits (["It's OK to be odd!"](00-introduction.md#glossary-and-terminology-guide)). +A delay of 12-blocks is used when forgetting a channel on funding output spend +as to permit a new `channel_announcement` to propagate which indicates this +channel was spliced. + ## The `node_announcement` Message This gossip message allows a node to indicate extra data associated with it, in @@ -287,6 +291,10 @@ onion service addresses; Encodes: `[32:32_byte_ed25519_pubkey] || [2:checksum] || [1:version]`, where `checksum = sha3(".onion checksum" | pubkey || version)[:2]`. + * `5`: DNS hostname; data = `[1:hostname_len][hostname_len:hostname][2:port]` (length up to 258) + * `hostname` bytes MUST be ASCII characters. + * Non-ASCII characters MUST be encoded using Punycode: + https://en.wikipedia.org/wiki/Punycode ### Requirements @@ -308,13 +316,14 @@ - MUST place address descriptors in ascending order. - SHOULD NOT place any zero-typed address descriptors anywhere. - SHOULD use placement only for aligning fields that follow `addresses`. - - MUST NOT create a `type 1` OR `type 2` address descriptor with `port` equal - to 0. + - MUST NOT create a `type 1`, `type 2` or `type 5` address descriptor with + `port` equal to 0. - SHOULD ensure `ipv4_addr` AND `ipv6_addr` are routable addresses. - MUST set `features` according to [BOLT #9](09-features.md#assigned-features-flags) - SHOULD set `flen` to the minimum length required to hold the `features` bits it sets. - SHOULD not announce a Tor v2 onion service. + - MUST NOT announce more than one `type 5` DNS hostname. The receiving node: - if `node_id` is NOT a valid compressed public key: @@ -339,7 +348,7 @@ - SHOULD send a `warning`. - MAY close the connection. - if `port` is equal to 0: - - SHOULD ignore `ipv6_addr` OR `ipv4_addr`. + - SHOULD ignore `ipv6_addr` OR `ipv4_addr` OR `hostname`. - if `node_id` is NOT previously known from a `channel_announcement` message, OR if `timestamp` is NOT greater than the last-received `node_announcement` from this `node_id`: @@ -352,6 +361,9 @@ - MAY use `rgb_color` AND `alias` to reference nodes in interfaces. - SHOULD insinuate their self-signed origins. - SHOULD ignore Tor v2 onion services. + - if more than one `type 5` address is announced: + - SHOULD ignore the additional data. + - MUST not forward the `node_announcement`. ### Rationale @@ -414,7 +426,7 @@ * [`u64`:`htlc_minimum_msat`] * [`u32`:`fee_base_msat`] * [`u32`:`fee_proportional_millionths`] - * [`u64`:`htlc_maximum_msat`] (option_channel_htlc_max) + * [`u64`:`htlc_maximum_msat`] The `channel_flags` bitfield is used to indicate the direction of the channel: it identifies the node that this update originated from and signals various options @@ -426,18 +438,12 @@ | 0 | `direction` | Direction this update refers to. | | 1 | `disable` | Disable the channel. | -The `message_flags` bitfield is used to indicate the presence of optional -fields in the `channel_update` message: - -| Bit Position | Name | Field | -| ------------- | ------------------------- | -------------------------------- | -| 0 | `option_channel_htlc_max` | `htlc_maximum_msat` | +The `message_flags` bitfield is used to provide additional details about the message: -Note that the `htlc_maximum_msat` field is static in the current -protocol over the life of the channel: it is *not* designed to be -indicative of real-time channel capacity in each direction, which -would be both a massive data leak and uselessly spam the network (it -takes an average of 30 seconds for gossip to propagate each hop). +| Bit Position | Name | +| ------------- | ---------------| +| 0 | `must_be_one` | +| 1 | `dont_forward` | The `node_id` for the signature verification is taken from the corresponding `channel_announcement`: `node_id_1` if the least-significant bit of flags is 0 @@ -446,10 +452,13 @@ ### Requirements The origin node: - - MUST NOT send a created `channel_update` before `funding_locked` has been received. + - MUST NOT send a created `channel_update` before `channel_ready` has been received. - MAY create a `channel_update` to communicate the channel parameters to the channel peer, even though the channel has not yet been announced (i.e. the `announce_channel` bit was not set). + - MUST set the `short_channel_id` to either an `alias` it has + received from the peer, or the real channel `short_channel_id`. + - MUST set `dont_forward` to 1 in `message_flags` - MUST NOT forward such a `channel_update` to other peers, for privacy reasons. - Note: such a `channel_update`, one not preceded by a @@ -463,15 +472,8 @@ - MUST set the `direction` bit of `channel_flags` to 0. - otherwise: - MUST set the `direction` bit of `channel_flags` to 1. - - if the `htlc_maximum_msat` field is present: - - MUST set the `option_channel_htlc_max` bit of `message_flags` to 1. - - MUST set `htlc_maximum_msat` to the maximum value it will send through this channel for a single HTLC. - - MUST set this to less than or equal to the channel capacity. - - MUST set this to less than or equal to `max_htlc_value_in_flight_msat` - it received from the peer. - - otherwise: - - MUST set the `option_channel_htlc_max` bit of `message_flags` to 0. - - MUST set bits in `channel_flags` and `message_flags `that are not assigned a meaning to 0. + - MUST set `must_be_one` in `message_flags` to 1. + - MUST set bits in `channel_flags` and `message_flags` that are not assigned a meaning to 0. - MAY create and send a `channel_update` with the `disable` bit set to 1, to signal a channel's temporary unavailability (e.g. due to a loss of connectivity) OR permanent unavailability (e.g. prior to an on-chain @@ -490,6 +492,8 @@ - MUST set `fee_proportional_millionths` to the amount (in millionths of a satoshi) it will charge per transferred satoshi. - SHOULD NOT create redundant `channel_update`s + - If it creates a new `channel_update` with updated channel parameters: + - SHOULD keep accepting the previous channel parameters for 10 minutes The receiving node: - if the `short_channel_id` does NOT match a previous `channel_announcement`, @@ -522,14 +526,11 @@ - otherwise: - SHOULD queue the message for rebroadcasting. - MAY choose NOT to for messages longer than the minimum expected length. - - if the `option_channel_htlc_max` bit of `message_flags` is 0: - - MUST consider `htlc_maximum_msat` not to be present. + - if `htlc_maximum_msat` is greater than channel capacity: + - MAY blacklist this `node_id` + - SHOULD ignore this channel during route considerations. - otherwise: - - if `htlc_maximum_msat` is not present or greater than channel capacity: - - MAY blacklist this `node_id` - - SHOULD ignore this channel during route considerations. - - otherwise: - - SHOULD consider the `htlc_maximum_msat` when routing. + - SHOULD consider the `htlc_maximum_msat` when routing. ### Rationale @@ -539,23 +540,17 @@ 1970-01-01). This cannot be a hard requirement, however, given the possible case of two `channel_update`s within a single second. -It is assumed that more than one `channel_update` message changing the channel -parameters in the same second may be a DoS attempt, and therefore, the node responsible -for signing such messages may be blacklisted. However, a node may send a same -`channel_update` message with a different signature (changing the nonce in signature -signing), and hence fields apart from signature are checked to see if the channel -parameters have changed for the same timestamp. It is also important to note that -ECDSA signatures are malleable. So, an intermediate node who received the `channel_update` -message can rebroadcast it just by changing the `s` component of signature with `-s`. +It is assumed that more than one `channel_update` message changing the channel +parameters in the same second may be a DoS attempt, and therefore, the node responsible +for signing such messages may be blacklisted. However, a node may send a same +`channel_update` message with a different signature (changing the nonce in signature +signing), and hence fields apart from signature are checked to see if the channel +parameters have changed for the same timestamp. It is also important to note that +ECDSA signatures are malleable. So, an intermediate node who received the `channel_update` +message can rebroadcast it just by changing the `s` component of signature with `-s`. This should however not result in the blacklist of the `node_id` from where the message originated. -The explicit `option_channel_htlc_max` flag to indicate the presence -of `htlc_maximum_msat` (rather than having `htlc_maximum_msat` implied -by the message length) allows us to extend the `channel_update` -with different fields in future. Since channels are limited to 2^32-1 -millisatoshis in Bitcoin, the `htlc_maximum_msat` has the same restriction. - The recommendation against redundant `channel_update`s minimizes spamming the network, however it is sometimes inevitable. For example, a channel with a peer which is unreachable will eventually cause a `channel_update` to @@ -564,6 +559,15 @@ messages are batched and replace previous ones, the result may be a single seemingly-redundant update. +When a node creates a new `channel_update` to change its channel parameters, +it will take some time to propagate through the network and payers may use +older parameters. It is recommended to keep accepting older parameters for +at least 10 minutes to improve payment latency and reliability. + +The `must_be_one` field in `message_flags` was previously used to indicate +the presence of the `htlc_maximum_msat` field. This field must now always +be present, so `must_be_one` is a constant value, and ignored by receivers. + ## Query Messages Negotiating the `gossip_queries` option via `init` enables a number @@ -986,8 +990,8 @@ #### Requirements A node: - - if a channel's oldest `channel_update`s `timestamp` is older than two weeks - (1209600 seconds): + - if the `timestamp` of the latest `channel_update` in either direction is + older than two weeks (1209600 seconds): - MAY prune the channel. - MAY ignore the channel. - Note: this is an individual node policy and MUST NOT be enforced by diff --git a/contrib/pyln-spec/bolt7/pyproject.toml b/contrib/pyln-spec/bolt7/pyproject.toml index bc6b128ea567..58403b50a897 100644 --- a/contrib/pyln-spec/bolt7/pyproject.toml +++ b/contrib/pyln-spec/bolt7/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pyln-bolt7" -version = "1.0.2.186.post0" +version = "1.0.246" description = "BOLT7" authors = ["Rusty Russell"] license = "BSD-MIT" @@ -14,6 +14,9 @@ python = "^3.7" [tool.poetry.dev-dependencies] pyln-proto = "^0.10.2" +pytest = "^7.1.2" +mypy = "^0.971" +typing-extensions = "^4.3.0" [build-system] requires = ["poetry-core>=1.0.0"]