From 51eb32670f40b6495c3213fc7f3ed1e775a0cb01 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Thu, 16 Mar 2023 16:29:45 +0200 Subject: [PATCH 1/6] bolt-taproot-gossip --- bolt-taproot-gossip.md | 1083 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1083 insertions(+) create mode 100644 bolt-taproot-gossip.md diff --git a/bolt-taproot-gossip.md b/bolt-taproot-gossip.md new file mode 100644 index 000000000..f9985ca04 --- /dev/null +++ b/bolt-taproot-gossip.md @@ -0,0 +1,1083 @@ +# Extension BOLT XX: Taproot Gossip + +# Table of Contents + + * [Aim](#aim) + * [Overview](#overview) + * [Terminology](#terminology) + * [Type Definitions](#type-definitions) + * [TLV Based Messages](#tlv-based-messages) + * [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification) + * [Timestamp fields](#timestamp-fields) + * [Bootstrapping Taproot Gossip](#bootstrapping-taproot-gossip) + * [Specification](#specification) + * [Feature Bits](#feature-bits) + * [The `announcement_signatures_2` message](#the-announcement_signatures_2-message) + * [The `channel_announcement_2` message](#the-channel_announcement_2-message) + * [The `node_announcement_2` message](#the-node_announcement_2-message) + * [The `channel_update_2` message](#the-channel_update_2-message) + * [Appendix A: Algorithms](#appendix-a-algorithms) + * [Partial Signature Calculation](#partial-signature-calculation) + * [Partial Signature Verification](#partial-signature-verification) + * [Appendix B: Test Vectors](#appendix-b-test-vectors) + * [Acknowledgements](#acknowledgements) + +## Aim + +This document aims to update the gossip protocol defined in [BOLT 7][bolt-7] to +allow for advertisement and verification of taproot channels. An entirely new +set of gossip messages are defined that use [BIP-340][bip-340] signatures and +that use a purely TLV based schema. + +## Overview + +The initial version of the Lightning Network gossip protocol as defined in +[BOLT 7][bolt-7] was designed around P2WSH funding transactions. For these +channels, the `channel_announcement` message is used to advertise the channel to +the rest of the network. Nodes in the network use the content of this message to +prove that the channel is sufficiently bound to the Lightning Network context +and that it is owned by the nodes advertising the channel. This proof and +verification protocol is, however, not compatible with SegWit V1 (P2TR) outputs +and so cannot be used to advertise the channels defined in the +[Simple Taproot Channel][simple-taproot-chans] proposal. This document thus aims +to define an updated gossip protocol that will allow nodes to both advertise and +verify taproot channels. This part of the update affects the +`announcement_signatures` and `channel_announcement` messages. + +The opportunity is also taken to rework the `node_announcement` and +`channel_update` messages to take advantage of [BIP-340][bip-340] signatures and +TLV fields. Timestamp fields are also updated to be block heights instead of +Unix timestamps. + +## Terminology + +- Collectively, the set of new gossip messages will be referred to as + `taproot gossip`. +- `node_1` and `node_2` refer to the two parties involved in opening a channel. +- `node_ID_1` and `node_ID_2` respectively refer to the public keys that + `node_1` and `node_2` use to identify their nodes in the network. +- `bitcoin_key_1` and `bitcoin_key_2` respectively refer to the public keys + that `node_1` and `node_2` will use for the specific channel being opened. + The funding transaction's output will be derived from these two keys. + +## Type Definitions + +The following convenient types are defined: + +* `bip340_sig`: a 64-byte bitcoin Elliptic Curve Schnorr signature as + per [BIP-340][bip-340]. +* `partial_signature`: a 32-byte partial MuSig2 signature as defined + in [BIP-MuSig2][bip-musig2]. +* `public_nonce`: a 66-byte public nonce as defined in [BIP-MuSig2][bip-musig2]. +* `utf8`: a byte as part of a UTF-8 string. A writer MUST ensure an array of + these is a valid UTF-8 string, a reader MAY reject any messages containing an + array of these which is not a valid UTF-8 string. + +## TLV Based Messages + +The initial set of Lightning Network messages consisted of fields that had to +be present. Later on, TLV encoding was introduced which provided a backward +compatible way to extend messages. To ensure that the new messages defined in +this document remain as future-proof as possible, the messages will be pure TLV +streams. By making all fields in the messages TLV records, fields that we +consider mandatory today can easily be dropped in future (when coupled with a +new feature bit) without needing to completely redefine the gossip message in +order to make the field optional. + +## Taproot Channel Proof and Verification + +Taproot channel funding transaction outputs will be SegWit V1 (P2TR) outputs of +the following form: + +``` +OP_1 +``` + +where +``` +taproot_internal_key = MuSig2.KeyAgg(MuSig2.KeySort(bitcoin_key_1, bitcoin_key_2)) + +taproot_output_key = taproot_internal_key + tagged_hash("TapTweak", taproot_internal_key) * G +``` + +`taproot_interal_key` is the aggregate key of `bitcoin_key_1` and +`bitcoin_key_2` after first sorting the keys using the +[MuSig2 KeySort][musig-keysort] algorithm and then running the +[MuSig2 KeyAgg][musig-keyagg] algorithm. + +Then, to commit to spending the taproot output via the keyspend path, a +[BIP86][bip86-tweak] tweak is added to the internal key to calculate the +`taproot_output_key`. + +As with legacy channels, nodes will want to perform some checks before adding +an announced taproot channel to their routing graph: + +1. The funding output of the channel being advertised exists on-chain, is an + unspent UTXO and has a sufficient number of confirmations. To allow this + check, the SCID of the channel will continue to be included in the channel + announcement. +2. The funding transaction is sufficiently bound to the Lightning context. + Nodes will do this by checking that they are able to derive the output key + found on-chain by using the advertised `bitcoin_key_1` and `bitcoin_key_2` + along with a [BIP86 tweak][bip86-tweak]. This provides a slightly weaker + binding to the LN context than legacy channels do but at least somewhat + limits how the output can be spent due to the script-path being disabled. + The context binding with legacy channels is greater because an attacker + trying to create gossip spam would need to create 2-of-2 multisig P2WSH + outputs on-chain that would require them to then pay for the bytes of two + signatures at the time of spending the output. This extra cost provided some + extra deterrence for attackers. This deterrence is not present with P2TR + transactions. +3. The owners of `bitcoin_key_1` and `bitcoin_key_2` agree to be associated with + a channel owned by `node_1` and `node_2`. +4. The owners of `node_ID_1` and `node_ID_2` agree to being associated with the + output paying to `bitcoin_key_1` and `bitcoin_key_2`. + +For legacy channels, these last two proofs are made possible by including four +separate signatures in the `channel_announcement`. However, [BIP-340][bip-340] +signatures and the MuSig2 protocol allow us to now aggregate these four +signatures into a single one. Verifiers will then be able to aggregate the four +keys (`bitcoin_key_1`, `bitcoin_key_2`, `node_ID_1` and `node_ID_2`) using +MuSig2 key aggregation and then they can do a single signature verification +check instead of four individual checks. + +## Timestamp fields + +In this document, the `timestamp` fields in messages are block heights instead +of the UNIX timestamps used in the legacy gossip messages. + +### Rate Limiting + +A block height based timestamp results in more natural rate limiting for gossip +messages: nodes are allowed to send at most one announcement and update per +block. To allow for bursts, nodes are encouraged not to use the latest block +height for their latest announcements/updates but rather to backdate and use +older block heights that they have not used in an announcement/update. There of +course needs to be a limit on the start block height that the node can use: +for `channel_update_2` messages, the first timestamp must be the block height in +which the channel funding transaction was mined and all updates after the +initial one must have increasing timestamps. Nodes are then responsible for +building up their own timestamp buffer: if they want to be able to send +multiple `channel_update_2` messages per block, then they will need to ensure +that there are blocks during which they do not broadcast any updates. This +provides an incentive for nodes not to spam the network with too many updates. + +To also prevent nodes from building up too large of a burst-buffer with which +they can spam the network and to give a limit to how low the block height on a +`node_announcement_2` can be: nodes should not be allowed to use a block height +smaller 1440 (~ a day worth of blocks) below the current block height. + +### Simplifies Channel Announcement Queries + +In the legacy gossip protocol, the timestamp of the `channel_announcement` is +hard to define since the message itself does not have a `timestamp` field. This +makes timestamp based gossip queries tricky. By using block heights as +timestamps instead, there is an implicit timestamp associated with the +`channel_announcement_2`: the block in which the funding transaction is mined. + +## Bootstrapping Taproot Gossip + +While the network upgrades from the legacy gossip protocol to the taproot gossip +protocol, the following scenarios may exist for any node on the network: + +| scenario | has legacy channels | has taproot channels | should send `node_announcement` | should send `node_announcement_2` | +|----------|---------------------|-----------------------|---------------------------------|-----------------------------------| +| 1 | no | no | no | no | +| 2 | yes | no | yes | no | +| 3 | yes | yes | yes | no | +| 4 | no | yes | no | yes | + +### Scenario 1 + +These nodes have no announced channels and so should not be broadcasting legacy +or new node announcement messages. + +### Scenario 2 + +If a node has legacy channels but no taproot channels, they should broadcast +only a legacy `node_announcement` message. Both taproot-gossip aware and unaware +nodes will be able to verify the node announcement since both groups are able to +process the `channel_announcement` for the legacy channel(s). The reason why +upgraded nodes should continue to broadcast the legacy announcement is because +this is the most effective way of spreading the `option_taproot_gossip` feature +bit since un-upgraded nodes can assist in spreading the message. + +### Scenario 3 + +If a node has both legacy channels and taproot channels, then like Scenario 2 +nodes, they should continue broadcasting the legacy `node_announcement` +message. + +### Scenario 4 + +In this scenario, a node has only taproot channels and no legacy channels. This +means that they cannot broadcast a legacy `node_announcement` message since +un-upgraded nodes will drop this message due to the fact that no legacy +`channel_announcement` message would have been received for that node. These +nodes will also not be able to use a legacy `node_announcement` to propagate +their new `node_announcement_2` message. + +### Consideration & Suggestions + +While the network is in the upgrade phase, the following suggestions apply: + +- Keeping at least a single, announced, legacy channel open during the initial + phase of the transition to the new gossip protocol could be very beneficial + since nodes can continue to broadcast their legacy `node_announcement` and + thus more effectively advertise their support for `option_taproot_gossip`. +- Nodes are encouraged to actively connect to other nodes that advertise the + `option_taproot_gossip` feature bit as this is the only way in which they + will learn about taproot channel announcements and updates. +- Nodes should not use the new `node_announcement_2` message until they have + no more announced legacy channels. + +### Alternative Approaches + +An alternative approach would be to add an optional TLV to the legacy +`node_annoucement` that includes the serialised `node_announcement_2`. The nice +thing about this is that it allows the new `node_announcement_2` message to +propagate quickly through the network before the upgrade is complete. The +downside of this approach is that it would more than double the size of the +legacy `node_announcement` and most of the information would be duplicated. It +also makes gossip queries tricky since `node_announcement_2` uses a block-height +based timestamp instead of the unix timestamp used by the legacy message. +There also does not seem to be a big benefit in spreading the +`node_announcement_2` message quickly since the speed of propagation of the +`channel_announcement_2` and `channel_update_2` messages will still depend on a +network wide upgrade. + +## Specification + +### Feature Bits + +Unlike the original set of gossip messages, it needs to be explicitly advertised +that nodes are aware of the new gossip messages defined in this document at +least until the whole network has upgraded to only using taproot gossip. We thus +define a new feature bit, `option_taproot_gossip` to be included in the `init` +message as well as the _old_ `node_announcement` message. Note that for all +other feature bits with the `N` and `C` contexts, it can be assumed that those +contexts will switch to the new `node_announcement_2` and +`channel_announcement_2` messages for all feature bits _except_ for +`option_taproot_gossip` which only makes sense in the context of the old +`node_announcement` message and not the new `node_announcement_v2` message. +The `option_taproot` feature bit can also be implied when using the new taproot +gossip messages. + +| Bits | Name | Description | Context | Dependencies | +|-------|-------------------------|---------------------------------------------------|---------|------------------| +| 32/33 | `option_taproot_gossip` | Nodes that understand the taproot gossip messages | IN | `option_taproot` | + +A node can be assumed to understand the new gossip v2 messages if: + +- They advertise `option_taproot_gossip` in a legacy `node_announcement` message + OR +- They have broadcast one of the new gossip messages defined in this document. + +Advertisement of the `option_taproot_gossip` feature bit should be taken to +mean: + +- The node understands and is able to forward all the taproot gossip messages. +- The node may be willing to open an announced taproot channel. + +### `open_channel` Extra Requirements + +These extra requirements only apply if the `option_taproot` channel type is set +in the `open_channel` message. + +The sender: + +- if `option_taproot_gossip` was negotiated: + - MAY set the `announce_channel` bit in `channel_flags` +- otherwise: + - MUST NOT set the `announce_channel` bit. + +The receiving node MUST fail the channel if: + +- if `option_taproot_gossip` was not negotiated and the `announce_channel` + bit in the `channel_flags` was set. + +### `channel_ready` Extensions + +These extensions only apply if the `option_taproot` channel type was set in the +`open_channel` message along with the `announce_channel` channel flag. + +1. `tlv_stream`: `channel_ready_tlvs` +2. types: + 1. type: 0 (`announcement_node_pubnonce`) + 2. data: + * [`66*byte`: `public_nonce`] + 3. type: 1 (`announcement_bitcoin_pubnonce`) + 4. data: + * [`66*byte`: `public_nonce`] + +### Requirements + +The sender: + + - MUST set the `announcement_node_pubnonce` and + `announcement_bitcoin_pubnonce` tlv fields in `channel_ready`. + - SHOULD use the MuSig2 `NonceGen` algorithm to generate two unique secret + nonces and use these to determine the corresponding public nonces: + `announcement_node_pubnonce` and `announcement_bitcoin_pubnonce`. + +The recipient: + + - MUST fail the channel if: + - if the `announcement_node_pubnonce` or `announcement_bitcoin_pubnonce` tlv + fields are missing. + - if the `announcement_node_pubnonce` and `announcement_bitcoin_pubnonce` + are equal. + +### Rationale + +The final signature included in the `channel_announcement_v2` message will be a +single [BIP-340][bip-340] signature that needs to be valid for a public key +derived by aggregating all the `node_ID` and `bitcoin_key` public keys. The +signature for this key will thus be created by aggregating (via MuSig2) four +partial signatures. One for each of the keys: `node_ID_1`, `node_ID_2`, +`bitcoin_key_1` and `bitcoin_key_2`. A nonce will need to be generated and +exchanged for each of the keys and so each node will need to send the other node +two nonces. The `announcement_node_nonce` is for `node_ID_x` and the +`announcement_bitcoin_nonce` is for `bitcoin_key_x`. + +Since the channel can only be announced once the `channel_ready` messages have +been exchanged and since it is generally preferred to keep nonce exchanges as +Just In Time as possible, the nonces are exchanged via the `channel_ready` +message. + +## The `announcement_signatures_2` Message + +Like the legacy `announcement_signatures` message, this is a direct message +between the two endpoints of a channel and serves as an opt-in mechanism to +allow the announcement of the channel to the rest of the network. + +1. type: xxx (`announcement_signatures_2`) +2. data (tlv_stream): + 1. type: 0 (`channel_id`) + 2. data: + * [`channel_id`:`channel_id`] + 3. type: 1 (`short_channel_id`) + 4. data: + * [`short_channel_id`:`short_channel_id`] + 5. type: 2 (`partial_signature`) + 6. data: + * [`partial_signature`:`partial_signature`] + +### Requirements + +The requirements are similar to the ones defined for the legacy +`announcement_signatures`. The below requirements assume that the +`option_taproot` channel type was set in `open_channel`. + +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_2` message. + - MUST NOT send `announcement_signatures_2` messages until `channel_ready` + has been sent and received AND the funding transaction has at least six + confirmations. + - MUST set the `partial_signature` field to the 32-byte `s` value of the + partial signature calculated as described + in [Partial Signature Calculation](#partial-signature-calculation). The + message to be signed is + `MsgHash("channel_announcement", "announcement_sig", m)` where `m` is the + serialisation of the `channel_announcement_2` message excluding the + `announcement_sig` field (see the + [`MsgHash`](#signature-message-construction) definition). +- otherwise: + - MUST NOT send the `announcement_signatures_2` message. +- upon reconnection (once the above timing requirements have been met): + - MUST respond to the first `announcement_signatures_2` message with its own + `announcement_signatures_2` message. + - if it has NOT received an `announcement_signatures_2` message: + - SHOULD retransmit the `announcement_signatures_2` message. + +A recipient node: +- if the `short_channel_id` is NOT correct: + - SHOULD send a `warning` and close the connection, or send an + `error` and fail the channel. +- if the `partial_signature` is NOT valid as + per [Partial Signature Verification](#partial-signature-verification): + - MAY send a `warning` and close the connection, or send an + `error` and fail the channel. +- if it has sent AND received a valid `announcement_signatures_2` message: + - SHOULD queue the `channel_announcement_2` message for its peers. +- if it has not sent `channel_ready`: + - MAY send a `warning` and close the connection, or send an `error` and fail + the channel. + +### Rationale + +The message contains the necessary partial signature, by the sender, that the +recipient will be able to combine with their own partial signature to construct +the signature to put in the `channel_announcement_v2` message. Unlike the legacy +`announcement_signatures` message, `announcement_signatures_v2` only has one +signature field. This field is a MuSig2 partial signature which is the +aggregation of the two signatures that the sender would have created (one for +`bitcoin_key_x` and another for `node_ID_x`). + +## The `channel_announcement_2` Message + +This gossip message contains ownership information regarding a taproot channel. +It ties each on-chain Bitcoin key that makes up the taproot output key to the +associated Lightning node key, and vice-versa. The channel is not practically +usable until at least one side has announced its fee levels and expiry, using +`channel_update_2`. + +See [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification) +for more information regarding the requirements for proving the existence of a +channel. + +1. type: xxx (`channel_announcement_2`) +2. data: (tlv_stream): + 1. type: 0 (`announcement_sig`) + 2. data: + * [`bip340_sig`:`bip340_sig`] + 3. type: 1 (`features`) + 4. data: + * [`...*byte`: `features`] + 5. type: 2 (`chain_hash`) + 6. data: + * [`chain_hash`:`chain_hash`] + 7. type: 3 (`short_channel_id`) + 8. data: + * [`short_channel_id`:`short_channel_id`] + 9. type: 4 (`node_id_1`) + 10. data: + * [`point`:`point`] + 11. type: 5 (`node_id_2`) + 12. data: + * [`point`:`point`] + 13. type: 6 (`bitcoin_key_1`) + 14. data: + * [`point`:`point`] + 15. type: 7 (`bitcoin_key_2`) + 16. data: + * [`point`:`point`] + +### Requirements + +The origin node: + +- MUST include types 0-7. +- MUST set `chain_hash` to the 32-byte hash that uniquely identifies the chain + that the channel was opened within: + - 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-channel_ready-message). + - Note: the corresponding output MUST be a P2TR, as described + in [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification). +- 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 two compressed keys sorted in ascending lexicographic order. +- MUST set `bitcoin_key_1` and `bitcoin_key_2` to `node_id_1` and `node_id_2`'s + respective `funding_pubkey`s. +- MUST set `features` based on what features were negotiated for this channel, + according to [BOLT #9](09-features.md#assigned-features-flags) +- MUST set `announcement_sig` signature to the [BIP-340][bip-340] signature + calculated by passing the partial signatures sent and received during the + `announcement_signatures_2` exchange to the + [MuSig2 PartialSigAgg][musig-partial-sig-agg] function. + +The receiving node: + +- If types 0-7 are not present: + - SHOULD send a `warning`. + - MAY close the connection. + - MUST ignore the message. +- MUST verify the integrity AND authenticity of the message by verifying the + `announcement_sig` as per [BIP 340][bip-340-verify]. +- if there is an unknown even bit in the `features` field: + - MUST NOT attempt to route messages through the channel. +- if the `short_channel_id`'s output does NOT correspond to a P2WSH (using + `bitcoin_key_1` and `bitcoin_key_2`, as specified in + [BOLT #3](03-transactions.md#funding-transaction-output)) OR the output is + spent: + - MUST ignore the message. +- if the specified `chain_hash` is unknown to the receiver: + - MUST ignore the message. +- otherwise: + - if `announcement_sig` is invalid OR NOT correct: + - SHOULD send a `warning`. + - MAY close the connection. + - MUST ignore the message. + - otherwise: + - if `node_id_1` OR `node_id_2` are blacklisted: + - SHOULD ignore the message. + - otherwise: + - if the transaction referred to was NOT previously announced as a + channel: + - SHOULD queue the message for rebroadcasting. + - MAY choose NOT to for messages longer than the minimum + expected length. + - if it has previously received a valid `channel_announcement_2`, for + the same transaction, in the same block, but for a + different `node_id_1` or `node_id_2`: + - SHOULD blacklist the previous message's `node_id_1` + and `node_id_2`, as well as this `node_id_1` and `node_id_2` AND + forget any channels connected to them. + - otherwise: + - SHOULD store this `channel_announcement_2`. +- once its funding output has been spent OR reorganized out: + - SHOULD forget a channel after a 12-block delay. + +### Rationale + +Both nodes are required to sign to indicate they are willing to route other +payments via this channel (i.e. be part of the public network); requiring their +aggregated MuSig2 Schnorr signature proves that they control the channel. + +The blacklisting of conflicting nodes disallows multiple different +announcements. Such conflicting announcements should never be broadcast by any +node, as this implies that keys have leaked. + +While channels should not be advertised before they are sufficiently deep, the +requirement against rebroadcasting only applies if the transaction has not moved +to a different block. + +In order to avoid storing excessively large messages, yet still allow for +reasonable future expansion, nodes are permitted to restrict rebroadcasting +(perhaps statistically). + +New channel features are possible in the future: backwards compatible (or +optional) features will have _odd_ feature bits, while incompatible features +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_2` to propagate which indicates this +channel was spliced. + +## The `node_announcement_2` Message + +This gossip message, like the legacy `node_announcement` message, allows a node +to indicate extra data associated with it, in addition to its public key. +To avoid trivial denial of service attacks, nodes not associated with an already +known channel (legacy or taproot) are ignored. + +Unlike the legacy `node_announcement` message, this message makes use of a +Schnorr signature instead of an ECDSA one. This will allow nodes to be backed +by multiple keys since MuSig2 can be used to construct the single signature. + +The other two main differences from the legacy message are that the timestamp +is now a block height and that the message is purely TLV based. + +1. type: xxx (`node_announcement_2`) +2. data: (tlv_stream): + 1. type: 0 (`announcement_sig`) + 2. data: + * [`bip340_sig`:`bip340_sig`] + 3. type: 1 (`features`) + 4. data: + * [`...*byte`: `features`] + 5. type: 2 (`timestamp`) + 6. data: + * [`u32`: `block_height`] + 7. type: 3 (`node_ID`) + 8. data: + * [`point`:`node_id`] + 9. type: 4 (`color`) + 10. data: + * [`rgb_color`:`rgb_color`] + 11. type: 5 (`alias`) + 12. data: + * [`...*utf8`:`alias`] + 13. type: 6 (`ipv4_addrs`) + 14. data: + * [`...*ipv4_addr`: `ipv4_addresses`] + 15. type: 7 (`ipv6_addrs`) + 16. data: + * [`...*ipv6_addr`: `ipv6_addresses`] + 17. type: 8 (`tor_v3_addrs`) + 18. data: + * [`...*tor_v3_addr`: `tor_v3_addresses`] + 19. type: 9 (`dns_hostname`) + 20. data: + * [`dns_hostname`: `dns_hostname`] + +The following subtypes are defined: + +1. subtype: `rgb_color` +2. data: + * [`byte`:`red`] + * [`byte`:`green`] + * [`byte`:`blue`] + +3. subtype: `ipv4_addr` +4. data: + * [`u32`:`addr`] + * [`tu16`:`port`] + +5. subtype: `ipv6_addr` +6. data: + * [`16*byte`:`addr`] + * [`tu16`:`port`] + +7. subtype: `tor_v3_addr` +8. data: + * [`35*utf8`:`onion_addr`] + * [`tu16`:`port`] + +9. subtype: `dns_hostname` +10. data: + * [`...*utf8`:`hostname`] + * [`tu16`:`port`] + +`tor_v3_address` is a Tor version 3 ([prop224]) onion service address; +Its `onion_addr` encodes: +`[32:32_byte_ed25519_pubkey] || [2:checksum] || [1:version]`, where +`checksum = sha3(".onion checksum" | pubkey || version)[:2]`. + +The `dns_hostname` `hostname` MUST be ASCII characters. Non-ASCII characters +MUST be encoded using [Punycode][punycode]. The length of the `hostname` cannot +exceed 255 bytes. + +### Requirements + +The sender: + +- MUST set types 0-3 (inclusive) +- MUST set `announcement_sig` to a valid [BIP340][bip-340] signature for the + `node_id` key. The message to be signed is + `MsgHash("node_announcement_2", "announcement_sig", m)` where `m` is the + serialisation of the `node_announcement_2` message excluding the + `announcement_sig` field (see the + [`MsgHash`](#signature-message-construction) definition). +- MAY set `color` and `alias` to customise appearance in maps and graphs. +- If the node sets the `alias`: + - MUST use 32 utf8 characters or less. +- MUST set `timestamp` to be greater than that of any previous + `node_announcement_2` it has previously created. + - MUST set it to a block height less than the latest block's height but no + more than 1440 lower. +- If the node wishes to announce its willingness to accept incoming network + connections: + - SHOULD set at least one of types 7-10. +- SHOULD set an address type (`ipv4_address`, `ipv6_address`, `tor_v3_address` + and/or `dns_hostname`) for each public network address that expects incoming + connections. +- SHOULD ensure that any specified `ipv4_addr` AND `ipv6_addr` are routable + addresses. +- MUST not create a `ipv4_addr`, `ipv6_addr` or `dns_hostname` with a `port` + equal to 0. +- MUST set `features` according to [BOLT #9][bolt-9-features]. +- SHOULD only start using this message once they no longer have announced legacy + channels. + +The receiving node: + +- If any type between 0-3 (inclusive) are missing: + - SHOULD send a `warning`. + - MAY close the connection. + - MUST ignore the message. +- if `alias` is set and is larger than 32 utf8 characters: + - SHOULD send a `warning`. + - MAY close the connection. + - MUST ignore the message. +- if `node_id` is NOT a valid compressed public key: + - SHOULD send a `warning`. + - MAY close the connection. + - MUST NOT process the message further. +- if `announcement_sig` is NOT a valid [BIP340][bip-340] signature (using + `node_id` over the message): + - SHOULD send a `warning`. + - MAY close the connection. + - MUST NOT process the message further. +- if `features` field contains _unknown even bits_: + - SHOULD NOT connect to the node. + - Unless paying a [BOLT #11][bolt-11] invoice which does not have the same + bit(s) set, MUST NOT attempt to send payments _to_ the node. + - MUST NOT route a payment _through_ the node. +- if `port` is equal to 0 for any `ipv6_addr` OR `ipv4_addr` OR `hostname`: + - SHOULD ignore that address. +- if `node_id` is NOT previously known from a `channel_announcement` OR + `channel_announcement_2` message, OR if `timestamp` is NOT greater than the + last-received `node_announcement_2` from this `node_id`: + - SHOULD ignore the message. +- otherwise: + - if `timestamp` is greater than the last-received `node_announcement_2` + from this `node_id`: + - SHOULD queue the message for rebroadcasting. +- MAY use `rgb_color` AND `alias` to reference nodes in interfaces. + - SHOULD insinuate their self-signed origins. +- SHOULD ignore any legacy `node_announcement` message for this `node_ID`. + +### Rationale + +New node features are possible in the future: backwards compatible (or +optional) ones will have _odd_ `feature` _bits_, incompatible ones will have +_even_ `feature` _bits_. These will be propagated normally; incompatible feature +bits here refer to the nodes, not the `node_announcement_2` message itself. + +Since the legacy `node_announcement` uses a UNIX based `timestamp` field and +this message uses block heights, deciding which message is the latest one could +be tricky. To simplify the logic, the decision is made that once a +`node_announcement_2` is received, then any legacy `node_announcement` messages +received for the same `node_id` can be ignored. + +### Security Considerations for Node Aliases + +The security considerations for node aliases mentioned in +[BOLT #7][bolt-7-alias-security] apply here too. + +## The `channel_update_2` Message + +After a channel has been initially announced via `channel_announcement_2`, each +side independently announces the fees and minimum expiry delta it requires to +relay HTLCs through this channel. Each uses the 8-byte short channel id that +matches the `channel_announcement_2` and the 1-bit `channel_flags` field to +indicate which end of the channel it's on (origin or final). A node can do this +multiple times, in order to change fees. + +Note that the `channel_update` gossip message is only useful in the context +of *relaying* payments, not *sending* payments. When making a payment +`A` -> `B` -> `C` -> `D`, only the `channel_update`s related to channels +`B` -> `C` (announced by `B`) and `C` -> `D` (announced by `C`) will +come into play. When building the route, amounts and expiries for HTLCs need +to be calculated backward from the destination to the source. The exact initial +value for `amount_msat` and the minimal value for `cltv_expiry`, to be used for +the last HTLC in the route, are provided in the payment request +(see [BOLT #11][[bolt-11-tagged-fields]]). + +1. type: xxx (`channel_update_2`) +2. data: (tlv_stream): + 1. type: 0 (`update_sig`) + 2. data: + * [`bip340_sig`:`bip340_sig`] + 3. type: 2 (`chain_hash`) + 4. data: + * [`chain_hash`:`chain_hash`] + 5. type: 2 (`timestamp`) + 6. data: + * [`u32`: `block_height`] + 7. type: 5 (`channel_flags`) + 8. data: + * [`...*byte`, `channel_flags`] + 9. type: 6 (`cltv_expiry_delta`) + 10. data: + * [`tu32`, `cltv_expiry_delta`] + 11. type: 7 (`htlc_min_msat`) + 12. data: + * [`tu64`, `htlc_min_msat`] + 13. type: 10 (`htlc_max_msat`) + 14. data: + * [`tu64`, `htlc_max_msat`] + 15. type: 8 (`fee_base_msat`) + 16. data: + * [`tu32`, `fee_base_msat`] + 17. type: 9 (`fee_prop_millionths`) + 18. data: + * [`tu32`, `fee_prop_millionths`] + +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 concerning the channel. The following table specifies the meaning of its +individual bits: + +| Bit Position | Name | Meaning | +|--------------|-------------|----------------------------------| +| 0 | `direction` | Direction this update refers to. | +| 1 | `disable` | Disable the channel. | + +The `node_id` for the signature verification is taken from the corresponding +`channel_announcement_2`: `node_id_1` if the least-significant bit of flags is +0 or `node_id_2` otherwise. + +### Requirements + +The origin node: +- MUST NOT send `channel_update_2` before `channel_ready` has been received. +- MUST NOT send `channel_update_2` for legacy (non-taproot) channels. +- MAY create a `channel_update_2` 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 NOT forward such a `channel_update` to other peers, for privacy + reasons. + - Note: such a `channel_update`, one not preceded by a + `channel_announcement`, is invalid to any other peer and would be + discarded. +- MUST set `update_sig` to a valid [BIP340][bip-340] signature for its own + `node_id` key. The message to be signed is + `MsgHash("channel_update_2", "update_sig", m)` where `m` is the serialisation + of the `channel_update` message excluding the `update_sig` field (see the + [`MsgHash`](#signature-message-construction) definition). +- MUST set `chain_hash` AND `short_channel_id` to match the 32-byte hash AND + 8-byte channel ID that uniquely identifies the channel specified in the + `channel_announcement_2` message. +- if the origin node is `node_id_1` in the message: + - MUST set the `direction` bit of `channel_flags` to 0. +- otherwise: + - MUST set the `direction` bit of `channel_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. +- MAY create and send a `channel_update_2` 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 + settlement). + - MAY send a subsequent `channel_update_2` with the `disable` bit set to 0 + to re-enable the channel. +- MUST set `timestamp` greater or equal to the block height that the channel's + funding transaction was mined in AND to greater than any previously-sent + `channel_update_2` for this `short_channel_id` AND no less than 1440 blocks + below the current best block height . +- MUST set `cltv_expiry_delta` to the number of blocks it will subtract from + an incoming HTLC's `cltv_expiry`. +- MUST set `htlc_minimum_msat` to the minimum HTLC value (in millisatoshi) + that the channel peer will accept. +- MUST set `fee_base_msat` to the base fee (in millisatoshi) it will charge + for any HTLC. +- 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_2`s +- If it creates a new `channel_update_2` 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_2`, + OR if the channel has been closed in the meantime: + - MUST ignore `channel_update_2`s that do NOT correspond to one of its own + channels. +- SHOULD accept `channel_update_2`s for its own taproot channels (even if + non-public), in order to learn the associated origin nodes' forwarding + parameters. +- if `update_sig` is NOT a valid [BIP340][bip-340] signature (using `node_id` + over the message): + - SHOULD send a `warning` and close the connection. + - MUST NOT process the message further. +- if the specified `chain_hash` value is unknown (meaning it isn't active on + the specified chain): + - MUST ignore the channel update. +- if the `timestamp` is equal to the last-received `channel_update_2` for this + `short_channel_id` AND `node_id`: + - if the fields below `timestamp` differ: + - MAY blacklist this `node_id`. + - MAY forget all channels associated with it. + - if the fields below `timestamp` are equal: + - SHOULD ignore this message +- if `timestamp` is lower than that of the last-received + `channel_update_2` for this `short_channel_id` AND for `node_id`: + - SHOULD ignore the message. +- otherwise: + - if the `timestamp` is a block height greater than the current best block + height: + - MAY discard the `channel_update_2`. + - if the `timestamp` block height is more than 1440 blocks less than the + current best block height: + - MAY discard the `channel_update_2`. + - otherwise: + - SHOULD queue the message for rebroadcasting. +- if `htlc_maximum_msat` is 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. + +### Rationale + +TODO + +## Query Messages + +TODO: any updates that need to happen to this section? + +# Appendix A: Algorithms + +### Partial Signature Calculation + +When both nodes have exchanged `channel_ready` then they will each have the +following information: + +- `node_1` will know: + - `bitcoin_priv_key_1`, `node_ID_priv_key_1`, + - `bitcoin_key_2`, + - `node_ID_1`, + - `announcement_node_secnonce_1` and `announcement_node_pubnonce_1`, + - `announcement_bitcoin_secnonce_1` and `announcement_bitcoin_pubnonce_1`, + - `announcement_node_pubnonce_2`, + - `announcement_bitcoin_pubnonce_2`, + +- `node_2` will know: + - `bitcoin_priv_key_2`, `node_ID_priv_key_2`, + - `bitcoin_key_1`, + - `node_ID_1`, + - `announcement_node_secnonce_2` and `announcement_node_pubnonce_2`, + - `announcement_bitcoin_secnonce_2` and `announcement_bitcoin_pubnonce_2`, + - `announcement_node_pubnonce_1`, + - `announcement_bitcoin_pubnonce_1`, + +With the above information, both nodes can now start calculating the partial +signatures that will be exchanged in the `announcement_signatures_v2` message. + +Firstly, the aggregate public key, `P_agg`, that the signature will be valid for +can be calculated as follows: + +``` +P_agg = Musig2.KeyAgg(Musig2.KeySort(node_ID_1, node_ID_2, bitcoin_key_1, bitcoin_key_2)) +``` + +Next, the aggregate public nonce, `aggnonce`, can be calculated: + +``` +aggnonce = Musig2.NonceAgg(announcement_node_secnonce_1, announcement_bitcoin_pubnonce_1, announcement_node_secnonce_2, announcement_bitcoin_pubnonce_2) +``` + +The message, `msg` that the peers will sign is the serialisation of +`channel_announcement_2` _without_ the `announcement_sig` field (i.e. without +type 0) + +With all the information mentioned, both peers can now construct the +[`Session Context`][musig-session-ctx] defined by the MuSig2 protocol which is +necessary for as an input to the `Musig2.Sign` algorithm. The following members +of the `Session Context`, which we will call `session_ctx`, can be defined: + +- `aggnonce`: `aggnonce` +- `u`: 2 +- `pk1..u`: [`node_ID_1`, `node_ID_2`, `bitcoin_key_1`, `bitcoin_key_2`] +- `v`: 0 +- `m`: `msg` + +Both peers, `node_1` and `node_2` will need to construct two partial signatures. +One for their `bitcoin_key` and one for their `node_ID` and aggregate those. + +- `node_1`: + - calculates a partial signature for `node_ID_1` as follows: + ``` + partial_sig_node_1 = MuSig2.Sign(announcement_node_secnonce_1, node_ID_priv_key_1, session_ctx) + ``` + - calculates a partial signature for `bitcoin_ID_1` as follows: + ``` + partial_sig_bitcoin_1 = MuSig2.Sign(announcement_bitcoin_secnonce_1, bitcoin_priv_key_1, session_ctx) + ``` + - calculates `partial_sig_1` as follows: + ``` + partial_sig_1 = MuSig2.PartialSigAgg(partial_sig_node_1, partial_sig_bitcoin_1, session_ctx) + ``` + +- `node_2`: + - calculates a partial signature for `node_ID_2` as follows: + ``` + partial_sig_node_2 = MuSig2.Sign(announcement_node_secnonce_2, node_ID_priv_key_2, session_ctx) + ``` + - calculates a partial signature for `bitcoin_ID_2` as follows: + ``` + partial_sig_bitcoin_2 = MuSig2.Sign(announcement_bitcoin_secnonce_2, bitcoin_priv_key_2, session_ctx) + ``` + - calculates `partial_sig_2` as follows: + ``` + partial_sig_2 = MuSig2.PartialSigAgg(partial_sig_node_2, partial_sig_bitcoin_2, session_ctx) + ``` + +Note that since there are no tweaks involved in this MuSig2 signing flow, +signature aggregation is simply the addition of the two signatures: + +``` + partial_sig = (partial_sig_node + partial_sig_bitcoin) % n +``` + +Where `n` is the [secp256k1][secp256k1] curve order. + +### Partial Signature Verification + +Since the partial signature put in `announcement_signatures_2` is the addition +of two of four signatures required to make up the final MuSig2 signature, the +verification of the partial signature is slightly different from what is +specified in the MuSig2 spec. The slightly adjusted algorithm will be defined +here. The notation used is the same as defined in the [MuSig2][musig-notation] +spec. + +The inputs are: + +- `partial_sig` sent by the peer in the `announcement_signatures_2` message. +- The `node_ID` and `bitcoin_key` of the peer. +- The `announcement_node_pubnonce` and `announcement_bitcoin_pubnonce` sent by + the peer in the `channel_ready` message. +- The `session_ctx` as shown + in [Partial Signature Calculation](#partial-signature-calculation). + +Verification steps: + +Note that the `GetSessionValues` and `GetSessionKeyAggCoeff` definitions can be +found in the [MuSig2][musig-session-ctx] spec. + +- Let `(Q, _, _, b, R, e) = GetSessionValues(session_ctx)` +- Let `s = int(psig); fail if s >= n` +- Let `R_n1 = cpoint(announcement_node_pubnonce[0:33])` +- Let `R_n2 = cpoint(announcement_node_pubnonce[33:66])` +- Let `R_b1 = cpoint(announcement_bitcoin_pubnonce[0:33])` +- Let `R_b2 = cpoint(announcement_bitcoin_pubnonce[33:66])` +- Let `R_1 = R_n1 + R_b1` +- Let `R_2 = b*(R_n2 + R_b2)` +- Let `R_e' = R_1 + R_2` +- Let `R_e = R_e'` if `has_even_y(R)`, otherwise let `R_e = -R_e'` +- Let `P_n = node_ID` +- Let `P_b = bitcoin_key` +- Let `a_n = GetSessionKeyAggCoeff(session_ctx, P_n)` +- Let `a_b = GetSessionKeyAggCoeff(session_ctx, P_b)` +- Let `P = a_n*P_n + a_b*P_b` +- Let `g = 1` if `has_even_y(Q)`, otherwise `let g = -1 mod n` +- Fail if `s*G != R_e + e*g*P` + +### Signature Message Construction + +The following `MsgHash` function is defined which can be used to construct a +32-byte message that can be used as a valid input to the [BIP-340][bip-340] +signing and verification algorithms. + +_MsgHash:_ + - _inputs_: + * `message_name`: UTF-8 string + * `field_name`: UTF-8 string + * `message`: byte array + + - Let `tag` = "lightning" || `message_name` || `field_name` + - return SHA256(SHA256(`tag`) || SHA256(`tag`) || SHA256(`message`)) + + +# Appendix B: Test Vectors + +TODO(elle) + +# Acknowledgements + +The ideas in this document are largely a consolidation and filtering of the +ideas mentioned in the following references: + +- [Rusty's initial Gossip v2 proposal][ml-rusty-2019-gossip-v2] where the idea + of replacing all gossip messages with new ones that use Schnorr signatures was + first mentioned (in public writing). This post also included the idea of using + block heights instead of Unix timestamps for timestamp fields as well as the + idea of moving some optional fields to TLVs. +- [Roasbeef's post][ml-roasbeef-2022-tr-chan-announcement] on Taproot-aware + Channel Announcements + Proof Verification which expands on the details of how + taproot channel verification should work. + +[bolt-7]: ./07-routing-gossip.md +[bolt-7-alias-security]: ./07-routing-gossip.md#security-considerations-for-node-aliases +[bolt-9-features]: ./09-features.md#bolt-9-assigned-feature-flags +[bolt-11]: ./11-payment-encoding.md +[bolt-11-tagged-fields]: ./11-payment-encoding.md#tagged-fields +[open-chan-msg]: ./02-peer-protocol.md#the-open_channel-message +[ml-rusty-2019-gossip-v2]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-July/002065.html +[ml-roasbeef-2022-tr-chan-announcement]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2022-March/003526.html +[bip-340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +[bip-340-verify]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#verification +[simple-taproot-chans]: https://github.com/lightning/bolts/pull/995 +[musig-keysort]: https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#key-sorting +[musig-keyagg]: https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#key-aggregation +[musig-signing]: https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#signing +[bip86-tweak]: https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#address-derivation +[bip-musig2]: https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki +[musig-session-ctx]: https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#session-context +[musig-notation]: https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#notation +[musig-partial-sig-agg]: https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#partial-signature-aggregation +[secp256k1]: https://www.secg.org/sec2-v2.pdf +[punycode]: https://en.wikipedia.org/wiki/Punycode +[prop224]: https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt From adf593304940b2f646aa1bf1abd02f1dc796f7a7 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 5 Jun 2023 16:11:58 +0200 Subject: [PATCH 2/6] fixup! bolt-taproot-gossip --- bolt-taproot-gossip.md | 144 +++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/bolt-taproot-gossip.md b/bolt-taproot-gossip.md index f9985ca04..29e8607b4 100644 --- a/bolt-taproot-gossip.md +++ b/bolt-taproot-gossip.md @@ -36,12 +36,15 @@ The initial version of the Lightning Network gossip protocol as defined in channels, the `channel_announcement` message is used to advertise the channel to the rest of the network. Nodes in the network use the content of this message to prove that the channel is sufficiently bound to the Lightning Network context -and that it is owned by the nodes advertising the channel. This proof and -verification protocol is, however, not compatible with SegWit V1 (P2TR) outputs -and so cannot be used to advertise the channels defined in the -[Simple Taproot Channel][simple-taproot-chans] proposal. This document thus aims -to define an updated gossip protocol that will allow nodes to both advertise and -verify taproot channels. This part of the update affects the +by being provided enough information to prove that the script is a 2-of-2 +multi-sig and that it is owned by the nodes advertising the channel. This +ownership proof is done by including signatures in the `channel_announcement` +from both the node ID keys along with the bitcoin keys used in the P2WSH script. +This proof and verification protocol is, however, not compatible with SegWit V1 +(P2TR) outputs and so cannot be used to advertise the channels defined in the +[Simple Taproot Channel][simple-taproot-chans] proposal. This document thus aims +to define an updated gossip protocol that will allow nodes to both advertise and +verify taproot channels. This part of the update affects the `announcement_signatures` and `channel_announcement` messages. The opportunity is also taken to rework the `node_announcement` and @@ -138,13 +141,13 @@ separate signatures in the `channel_announcement`. However, [BIP-340][bip-340] signatures and the MuSig2 protocol allow us to now aggregate these four signatures into a single one. Verifiers will then be able to aggregate the four keys (`bitcoin_key_1`, `bitcoin_key_2`, `node_ID_1` and `node_ID_2`) using -MuSig2 key aggregation and then they can do a single signature verification +MuSig2 key aggregation, and then they can do a single signature verification check instead of four individual checks. -## Timestamp fields +## Block-height fields -In this document, the `timestamp` fields in messages are block heights instead -of the UNIX timestamps used in the legacy gossip messages. +In the messages defined in this document, block heights are used as timestamps +instead of the UNIX timestamps used in the legacy set of gossip messages. ### Rate Limiting @@ -165,7 +168,7 @@ provides an incentive for nodes not to spam the network with too many updates. To also prevent nodes from building up too large of a burst-buffer with which they can spam the network and to give a limit to how low the block height on a `node_announcement_2` can be: nodes should not be allowed to use a block height -smaller 1440 (~ a day worth of blocks) below the current block height. +smaller 2016 (~ one week worth of blocks) below the current block height. ### Simplifies Channel Announcement Queries @@ -217,7 +220,7 @@ un-upgraded nodes will drop this message due to the fact that no legacy nodes will also not be able to use a legacy `node_announcement` to propagate their new `node_announcement_2` message. -### Consideration & Suggestions +### Considerations & Suggestions While the network is in the upgrade phase, the following suggestions apply: @@ -269,7 +272,8 @@ gossip messages. A node can be assumed to understand the new gossip v2 messages if: -- They advertise `option_taproot_gossip` in a legacy `node_announcement` message +- They advertise `option_taproot_gossip` in the `init` or + legacy `node_announcement` messages OR - They have broadcast one of the new gossip messages defined in this document. @@ -306,7 +310,7 @@ These extensions only apply if the `option_taproot` channel type was set in the 1. type: 0 (`announcement_node_pubnonce`) 2. data: * [`66*byte`: `public_nonce`] - 3. type: 1 (`announcement_bitcoin_pubnonce`) + 3. type: 2 (`announcement_bitcoin_pubnonce`) 4. data: * [`66*byte`: `public_nonce`] @@ -356,10 +360,10 @@ allow the announcement of the channel to the rest of the network. 1. type: 0 (`channel_id`) 2. data: * [`channel_id`:`channel_id`] - 3. type: 1 (`short_channel_id`) + 3. type: 2 (`short_channel_id`) 4. data: * [`short_channel_id`:`short_channel_id`] - 5. type: 2 (`partial_signature`) + 5. type: 4 (`partial_signature`) 6. data: * [`partial_signature`:`partial_signature`] @@ -372,14 +376,12 @@ The requirements are similar to the ones defined for the legacy 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_2` message. - - MUST NOT send `announcement_signatures_2` messages until `channel_ready` + - MUST send the `announcement_signatures_2` message once `channel_ready` has been sent and received AND the funding transaction has at least six confirmations. - - MUST set the `partial_signature` field to the 32-byte `s` value of the - partial signature calculated as described - in [Partial Signature Calculation](#partial-signature-calculation). The - message to be signed is + - MUST set the `partial_signature` field to the 32-byte `partial_sig` value of + the partial signature calculated as described in [Partial Signature + Calculation](#partial-signature-calculation). The message to be signed is `MsgHash("channel_announcement", "announcement_sig", m)` where `m` is the serialisation of the `channel_announcement_2` message excluding the `announcement_sig` field (see the @@ -433,38 +435,39 @@ channel. 1. type: 0 (`announcement_sig`) 2. data: * [`bip340_sig`:`bip340_sig`] - 3. type: 1 (`features`) + 3. type: 1 (`chain_hash`) 4. data: - * [`...*byte`: `features`] - 5. type: 2 (`chain_hash`) + * [`chain_hash`:`chain_hash`] + 5. type: 2 (`features`) 6. data: - * [`chain_hash`:`chain_hash`] - 7. type: 3 (`short_channel_id`) + * [`...*byte`: `features`] + 7. type: 4 (`short_channel_id`) 8. data: * [`short_channel_id`:`short_channel_id`] - 9. type: 4 (`node_id_1`) + 9. type: 6 (`node_id_1`) 10. data: * [`point`:`point`] - 11. type: 5 (`node_id_2`) + 11. type: 8 (`node_id_2`) 12. data: * [`point`:`point`] - 13. type: 6 (`bitcoin_key_1`) + 13. type: 3 (`bitcoin_key_1`) 14. data: * [`point`:`point`] - 15. type: 7 (`bitcoin_key_2`) + 15. type: 5 (`bitcoin_key_2`) 16. data: * [`point`:`point`] + 17. type: 7 (`tap_tweak`) + 18. data: + * [`point`:`point`] ### Requirements The origin node: -- MUST include types 0-7. -- MUST set `chain_hash` to the 32-byte hash that uniquely identifies the chain - that the channel was opened within: - - for the _Bitcoin blockchain_: - - MUST set `chain_hash` value (encoded in hex) equal - to `6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000`. +- If the chain being referred to is not the Bitcoin blockchain: + - MUST set `chain_hash` to the 32-byte hash that uniquely identifies the chain + that the channel was opened within: +- otherwise, MUST not set `chain_has` as the _Bitcoin blockchain_ is assumed. - MUST set `short_channel_id` to refer to the confirmed funding transaction, as specified in [BOLT #2](02-peer-protocol.md#the-channel_ready-message). - Note: the corresponding output MUST be a P2TR, as described @@ -483,7 +486,7 @@ The origin node: The receiving node: -- If types 0-7 are not present: +- If any even typed messages are not present: - SHOULD send a `warning`. - MAY close the connection. - MUST ignore the message. @@ -491,7 +494,7 @@ The receiving node: `announcement_sig` as per [BIP 340][bip-340-verify]. - if there is an unknown even bit in the `features` field: - MUST NOT attempt to route messages through the channel. -- if the `short_channel_id`'s output does NOT correspond to a P2WSH (using +- if the `short_channel_id`'s output does NOT correspond to a P2TR (using `bitcoin_key_1` and `bitcoin_key_2`, as specified in [BOLT #3](03-transactions.md#funding-transaction-output)) OR the output is spent: @@ -569,31 +572,31 @@ is now a block height and that the message is purely TLV based. 1. type: 0 (`announcement_sig`) 2. data: * [`bip340_sig`:`bip340_sig`] - 3. type: 1 (`features`) + 3. type: 2 (`features`) 4. data: * [`...*byte`: `features`] - 5. type: 2 (`timestamp`) + 5. type: 4 (`block_height`) 6. data: * [`u32`: `block_height`] - 7. type: 3 (`node_ID`) + 7. type: 6 (`node_ID`) 8. data: * [`point`:`node_id`] - 9. type: 4 (`color`) + 9. type: 1 (`color`) 10. data: * [`rgb_color`:`rgb_color`] - 11. type: 5 (`alias`) + 11. type: 3 (`alias`) 12. data: * [`...*utf8`:`alias`] - 13. type: 6 (`ipv4_addrs`) + 13. type: 5 (`ipv4_addrs`) 14. data: * [`...*ipv4_addr`: `ipv4_addresses`] 15. type: 7 (`ipv6_addrs`) 16. data: * [`...*ipv6_addr`: `ipv6_addresses`] - 17. type: 8 (`tor_v3_addrs`) + 17. type: 9 (`tor_v3_addrs`) 18. data: * [`...*tor_v3_addr`: `tor_v3_addresses`] - 19. type: 9 (`dns_hostname`) + 19. type: 11 (`dns_hostname`) 20. data: * [`dns_hostname`: `dns_hostname`] @@ -638,7 +641,6 @@ exceed 255 bytes. The sender: -- MUST set types 0-3 (inclusive) - MUST set `announcement_sig` to a valid [BIP340][bip-340] signature for the `node_id` key. The message to be signed is `MsgHash("node_announcement_2", "announcement_sig", m)` where `m` is the @@ -648,7 +650,7 @@ The sender: - MAY set `color` and `alias` to customise appearance in maps and graphs. - If the node sets the `alias`: - MUST use 32 utf8 characters or less. -- MUST set `timestamp` to be greater than that of any previous +- MUST set `block_height` to be greater than that of any previous `node_announcement_2` it has previously created. - MUST set it to a block height less than the latest block's height but no more than 1440 lower. @@ -668,7 +670,7 @@ The sender: The receiving node: -- If any type between 0-3 (inclusive) are missing: +- If any type between even-typed values are missing: - SHOULD send a `warning`. - MAY close the connection. - MUST ignore the message. @@ -693,11 +695,11 @@ The receiving node: - if `port` is equal to 0 for any `ipv6_addr` OR `ipv4_addr` OR `hostname`: - SHOULD ignore that address. - if `node_id` is NOT previously known from a `channel_announcement` OR - `channel_announcement_2` message, OR if `timestamp` is NOT greater than the + `channel_announcement_2` message, OR if `blockheight` is NOT greater than the last-received `node_announcement_2` from this `node_id`: - SHOULD ignore the message. - otherwise: - - if `timestamp` is greater than the last-received `node_announcement_2` + - if `block_height` is greater than the last-received `node_announcement_2` from this `node_id`: - SHOULD queue the message for rebroadcasting. - MAY use `rgb_color` AND `alias` to reference nodes in interfaces. @@ -746,28 +748,28 @@ the last HTLC in the route, are provided in the payment request 1. type: 0 (`update_sig`) 2. data: * [`bip340_sig`:`bip340_sig`] - 3. type: 2 (`chain_hash`) + 3. type: 1 (`chain_hash`) 4. data: * [`chain_hash`:`chain_hash`] - 5. type: 2 (`timestamp`) + 5. type: 2 (`block_height`) 6. data: * [`u32`: `block_height`] - 7. type: 5 (`channel_flags`) + 7. type: 4 (`channel_flags`) 8. data: * [`...*byte`, `channel_flags`] 9. type: 6 (`cltv_expiry_delta`) 10. data: * [`tu32`, `cltv_expiry_delta`] - 11. type: 7 (`htlc_min_msat`) + 11. type: 8 (`htlc_min_msat`) 12. data: * [`tu64`, `htlc_min_msat`] 13. type: 10 (`htlc_max_msat`) 14. data: * [`tu64`, `htlc_max_msat`] - 15. type: 8 (`fee_base_msat`) + 15. type: 12 (`fee_base_msat`) 16. data: * [`tu32`, `fee_base_msat`] - 17. type: 9 (`fee_prop_millionths`) + 17. type: 14 (`fee_prop_millionths`) 18. data: * [`tu32`, `fee_prop_millionths`] @@ -788,6 +790,10 @@ The `node_id` for the signature verification is taken from the corresponding ### Requirements The origin node: +- If the chain being referred to is not the Bitcoin blockchain: + - MUST set `chain_hash` to the 32-byte hash that uniquely identifies the + chain that the channel was opened within: +- otherwise, MUST not set `chain_hash` as the _Bitcoin blockchain_ is assumed. - MUST NOT send `channel_update_2` before `channel_ready` has been received. - MUST NOT send `channel_update_2` for legacy (non-taproot) channels. - MAY create a `channel_update_2` to communicate the channel parameters to the @@ -823,10 +829,10 @@ The origin node: settlement). - MAY send a subsequent `channel_update_2` with the `disable` bit set to 0 to re-enable the channel. -- MUST set `timestamp` greater or equal to the block height that the channel's - funding transaction was mined in AND to greater than any previously-sent - `channel_update_2` for this `short_channel_id` AND no less than 1440 blocks - below the current best block height . +- MUST set `block_height` greater or equal to the block height that the + channel's funding transaction was mined in AND to greater than any + previously-sent `channel_update_2` for this `short_channel_id` AND no less + than 1440 blocks below the current best block height . - MUST set `cltv_expiry_delta` to the number of blocks it will subtract from an incoming HTLC's `cltv_expiry`. - MUST set `htlc_minimum_msat` to the minimum HTLC value (in millisatoshi) @@ -855,21 +861,21 @@ The receiving node: - if the specified `chain_hash` value is unknown (meaning it isn't active on the specified chain): - MUST ignore the channel update. -- if the `timestamp` is equal to the last-received `channel_update_2` for this - `short_channel_id` AND `node_id`: - - if the fields below `timestamp` differ: +- if the `block_height` is equal to the last-received `channel_update_2` for + this `short_channel_id` AND `node_id`: + - if the fields below `block_height` differ: - MAY blacklist this `node_id`. - MAY forget all channels associated with it. - - if the fields below `timestamp` are equal: + - if the fields below `block_height` are equal: - SHOULD ignore this message -- if `timestamp` is lower than that of the last-received +- if `block_height` is lower than that of the last-received `channel_update_2` for this `short_channel_id` AND for `node_id`: - SHOULD ignore the message. - otherwise: - - if the `timestamp` is a block height greater than the current best block + - if the `block_height` is a block height greater than the current best block height: - MAY discard the `channel_update_2`. - - if the `timestamp` block height is more than 1440 blocks less than the + - if the `block_height` block height is more than 1440 blocks less than the current best block height: - MAY discard the `channel_update_2`. - otherwise: From 9ab7e6d063018796a5e952506740e186dde23549 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Thu, 28 Sep 2023 15:40:28 +0200 Subject: [PATCH 3/6] fixup! bolt-taproot-gossip --- bolt-taproot-gossip.md | 1292 +++++++++++++++++++++------------------- 1 file changed, 668 insertions(+), 624 deletions(-) diff --git a/bolt-taproot-gossip.md b/bolt-taproot-gossip.md index 29e8607b4..b4fbcd55d 100644 --- a/bolt-taproot-gossip.md +++ b/bolt-taproot-gossip.md @@ -1,60 +1,40 @@ # Extension BOLT XX: Taproot Gossip -# Table of Contents - - * [Aim](#aim) - * [Overview](#overview) - * [Terminology](#terminology) - * [Type Definitions](#type-definitions) - * [TLV Based Messages](#tlv-based-messages) - * [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification) - * [Timestamp fields](#timestamp-fields) - * [Bootstrapping Taproot Gossip](#bootstrapping-taproot-gossip) - * [Specification](#specification) - * [Feature Bits](#feature-bits) - * [The `announcement_signatures_2` message](#the-announcement_signatures_2-message) - * [The `channel_announcement_2` message](#the-channel_announcement_2-message) - * [The `node_announcement_2` message](#the-node_announcement_2-message) - * [The `channel_update_2` message](#the-channel_update_2-message) - * [Appendix A: Algorithms](#appendix-a-algorithms) - * [Partial Signature Calculation](#partial-signature-calculation) - * [Partial Signature Verification](#partial-signature-verification) - * [Appendix B: Test Vectors](#appendix-b-test-vectors) - * [Acknowledgements](#acknowledgements) - -## Aim - This document aims to update the gossip protocol defined in [BOLT 7][bolt-7] to allow for advertisement and verification of taproot channels. An entirely new set of gossip messages are defined that use [BIP-340][bip-340] signatures and -that use a purely TLV based schema. - -## Overview - -The initial version of the Lightning Network gossip protocol as defined in -[BOLT 7][bolt-7] was designed around P2WSH funding transactions. For these -channels, the `channel_announcement` message is used to advertise the channel to -the rest of the network. Nodes in the network use the content of this message to -prove that the channel is sufficiently bound to the Lightning Network context -by being provided enough information to prove that the script is a 2-of-2 -multi-sig and that it is owned by the nodes advertising the channel. This -ownership proof is done by including signatures in the `channel_announcement` -from both the node ID keys along with the bitcoin keys used in the P2WSH script. -This proof and verification protocol is, however, not compatible with SegWit V1 -(P2TR) outputs and so cannot be used to advertise the channels defined in the -[Simple Taproot Channel][simple-taproot-chans] proposal. This document thus aims -to define an updated gossip protocol that will allow nodes to both advertise and -verify taproot channels. This part of the update affects the -`announcement_signatures` and `channel_announcement` messages. - -The opportunity is also taken to rework the `node_announcement` and -`channel_update` messages to take advantage of [BIP-340][bip-340] signatures and -TLV fields. Timestamp fields are also updated to be block heights instead of -Unix timestamps. +that use a mostly TLV based structure. + +# Table Of Contents + +* [Terminology](#terminology) +* [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification) +* [TLV Based Messages](#tlv-based-messages) +* [Block-height fields](#block-height-fields) +* [Bootstrapping Taproot Gossip](#bootstrapping-taproot-gossip) +* [Specification](#specification) + * [Type Definitions](#type-definitions) + * [Features Bits](#feature-bits) + * [Features Bit Contexts](#feature-bit-contexts) + * [`open_channel` Extra Requirements](#openchannel-extra-requirements) + * [`channel_ready` Extensions](#channelready-extensions) + * [The `announcement_signatures_2` Message](#the-announcementsignatures2-message) + * [The `channel_announcement_2` Message](#the-channelupdate2-message) + * [The `node_announcement_2` Message](#the-nodeannouncement2-message) + * [The `channel_update_2` Message](#the-channelupdate2-message) +* [Appendix A: Algorithms](#appendix-a-algorithms) + * [Partial Signature Calculation](#partial-signature-calculation) + * [Partial Signature Verification](#partial-signature-verification) + * [Verifying the `channel_announcement_2` signature](#verifying-the-channelannouncement2-signature) + * [The 3-of-3 MuSig2 Scenario](#the-3-of-3-musig2-scenario) + * [The 4-of-4 MuSig2 Scenario](#the-4-of-4-musig2-scenario) + * [Signature Message Construction](#signature-message-construction) +* [Appendix B: Test Vectors](#appendix-b-test-vectors) +* [Acknowledgements](#acknowledgements) ## Terminology -- Collectively, the set of new gossip messages will be referred to as +- Collectively, the set of new gossip messages will be referred to as `taproot gossip`. - `node_1` and `node_2` refer to the two parties involved in opening a channel. - `node_ID_1` and `node_ID_2` respectively refer to the public keys that @@ -63,91 +43,132 @@ Unix timestamps. that `node_1` and `node_2` will use for the specific channel being opened. The funding transaction's output will be derived from these two keys. -## Type Definitions +## Taproot Channel Proof and Verification -The following convenient types are defined: +All Taproot channel funding transaction outputs are SegWit V1 (P2TR) outputs of +the following form: -* `bip340_sig`: a 64-byte bitcoin Elliptic Curve Schnorr signature as - per [BIP-340][bip-340]. -* `partial_signature`: a 32-byte partial MuSig2 signature as defined - in [BIP-MuSig2][bip-musig2]. -* `public_nonce`: a 66-byte public nonce as defined in [BIP-MuSig2][bip-musig2]. -* `utf8`: a byte as part of a UTF-8 string. A writer MUST ensure an array of - these is a valid UTF-8 string, a reader MAY reject any messages containing an - array of these which is not a valid UTF-8 string. +``` +OP_1 +``` -## TLV Based Messages +Ideally, the construction of the `taproot_output_key` should not matter to a +verifier of a channel. What a verifier cares about is whether the UTXO is +unspent and if the associated channel announcement contains a signature that +proves that the owner of the UTXO has participated in the signature +construction. -The initial set of Lightning Network messages consisted of fields that had to -be present. Later on, TLV encoding was introduced which provided a backward -compatible way to extend messages. To ensure that the new messages defined in -this document remain as future-proof as possible, the messages will be pure TLV -streams. By making all fields in the messages TLV records, fields that we -consider mandatory today can easily be dropped in future (when coupled with a -new feature bit) without needing to completely redefine the gossip message in -order to make the field optional. +The simplest verification of a channel-announcement signature would then be to +check that the signature is valid for the following aggregate 3-of-3 MuSig2 +public key: -## Taproot Channel Proof and Verification +``` +P_agg = MuSig2.KeyAgg(MuSig2.KeySort(node_id_1, node_id_2, taproot_output_key)) +``` -Taproot channel funding transaction outputs will be SegWit V1 (P2TR) outputs of -the following form: +This is simple and the spec can cater for this verification method today. +However, the spec must also contain recommendations for the construction of a +channel along with recommendations for the construction of a channel +announcement signature. The `taproot_output_key` will most likely be constructed +out of two or more keys where both channel peers own at least one key each and +so to compute a valid signature for the `P_agg` key noted above, the two channel +parties would need to make use of a nested MuSig2 protocol. Such a protocol has +yet to be specified and so this document can not yet rely on or reference such +a protocol. + +Therefore, this document will also cater for the verification and construction +of a channel announcement signature for the following 4-of-4 MuSig2 public key: ``` -OP_1 +P_agg = MuSig2.KeyAgg(MuSig2.KeySort(node_id_1, node_id_2, bitcoin_key_1, bitcoin_key_2)) +``` + +In this case, the `taproot_output_key` is expected to be constructed in one of +two ways. The first way is as a pure key path spend output as follows: + +``` +taproot_output_key = MuSig2.KeyAgg(MuSig2.KeySort(bitcoin_key_1, bitcoin_key_2)) ``` -where +The second way includes a possible tweak: + ``` taproot_internal_key = MuSig2.KeyAgg(MuSig2.KeySort(bitcoin_key_1, bitcoin_key_2)) -taproot_output_key = taproot_internal_key + tagged_hash("TapTweak", taproot_internal_key) * G +taproot_output_key = taproot_internal_key + tagged_hash("TapTweak", merkle_root_hash) * G ``` -`taproot_interal_key` is the aggregate key of `bitcoin_key_1` and -`bitcoin_key_2` after first sorting the keys using the -[MuSig2 KeySort][musig-keysort] algorithm and then running the -[MuSig2 KeyAgg][musig-keyagg] algorithm. - -Then, to commit to spending the taproot output via the keyspend path, a -[BIP86][bip86-tweak] tweak is added to the internal key to calculate the -`taproot_output_key`. - -As with legacy channels, nodes will want to perform some checks before adding -an announced taproot channel to their routing graph: - -1. The funding output of the channel being advertised exists on-chain, is an - unspent UTXO and has a sufficient number of confirmations. To allow this - check, the SCID of the channel will continue to be included in the channel - announcement. -2. The funding transaction is sufficiently bound to the Lightning context. - Nodes will do this by checking that they are able to derive the output key - found on-chain by using the advertised `bitcoin_key_1` and `bitcoin_key_2` - along with a [BIP86 tweak][bip86-tweak]. This provides a slightly weaker - binding to the LN context than legacy channels do but at least somewhat - limits how the output can be spent due to the script-path being disabled. - The context binding with legacy channels is greater because an attacker - trying to create gossip spam would need to create 2-of-2 multisig P2WSH - outputs on-chain that would require them to then pay for the bytes of two - signatures at the time of spending the output. This extra cost provided some - extra deterrence for attackers. This deterrence is not present with P2TR - transactions. -3. The owners of `bitcoin_key_1` and `bitcoin_key_2` agree to be associated with - a channel owned by `node_1` and `node_2`. -4. The owners of `node_ID_1` and `node_ID_2` agree to being associated with the - output paying to `bitcoin_key_1` and `bitcoin_key_2`. - -For legacy channels, these last two proofs are made possible by including four -separate signatures in the `channel_announcement`. However, [BIP-340][bip-340] -signatures and the MuSig2 protocol allow us to now aggregate these four -signatures into a single one. Verifiers will then be able to aggregate the four -keys (`bitcoin_key_1`, `bitcoin_key_2`, `node_ID_1` and `node_ID_2`) using -MuSig2 key aggregation, and then they can do a single signature verification -check instead of four individual checks. +In the case of Simple Taproot Channels, the `merkle_root_hash` will be equal to +the serialisation of the `taproot_internal_key`. + +The verification method used all depends on which information is provided in the +`channel_announcement_2` message. All of these verification methods require +the `node_id_1` and `node_id_2` to be provided along with a `short_channel_id` +that will allow the verifier to fetch the funding output from which the +`taproot_output_key` can be extracted. + +1. If no bitcoin keys are provided, then the signature must be verified against + the following public key: + + ``` + P_agg = MuSig2.KeyAgg(MuSig2.KeySort(node_id_1, node_id_2, taproot_output_key)) + ``` + + Allowing this proof type allows nodes to be somewhat future-proof since they + will be able to verify and make use of channels using a proof construction + not yet defined. + +2. If the two bitcoin keys (`bitcoin_key_1` and `bitcoin_key_2`) are provided + but no `merkle_root_hash` is provided then the verification steps are as + follows: + + 1. Compute the following aggregate 2-of-2 MuSig2 public key: + ``` + P_agg_out = MuSig2.KeyAgg(MuSig2.KeySort(bitcoin_key_1, bitcoin_key_2)) + ``` + 2. Assert that `P_agg_out` is equal to `taproot_output_key`. + 3. Now, compute the following aggregate 4-of-4 MuSig2 public key: + ``` + P_agg = MuSig2.KeyAgg(MuSig2.KeySort(node_id_1, node_id_2, bitcoin_key_1, bitcoin_key_2)) + ``` + 4. The signature must then be verified against `P_agg`. + +3. If the two bitcoin keys and the `merkle_root_hash` is provided, then the + verification steps are as follows: + + 1. Compute the following aggregate 2-of-2 MuSig2 public key: + ``` + P_internal = MuSig2.KeyAgg(MuSig2.KeySort(bitcoin_key_1, bitcoin_key_2)) + ``` + 2. The compute the following output public key: + ``` + P_output = P_internal + tagged_hash("TapTweak", merkle_root_hash) * G + ``` + 3. Assert that `P_output` is equal to `taproot_output_key`. + 4. Now, compute the following aggregate 4-of-4 MuSig2 public key: + ``` + P_agg = MuSig2.KeyAgg(MuSig2.KeySort(node_id_1, node_id_2, bitcoin_key_1, bitcoin_key_2)) + ``` + 5. The signature must then be verified against `P_agg`. + +In terms of construction of the proofs, this document covers case 2 and 3. + +## TLV Based Messages + +The initial set of Lightning Network messages consisted of a flat set of +serialised fields that were mandatory. Later on, TLV encoding was introduced +which provided a backward compatible way to extend messages. To ensure that the +new messages defined in this document remain as future-proof as possible, the +messages will mostly be pure TLV streams with a fixed 64-byte signature over the +tlv stream appended at the front of the message. By making all fields in the +messages TLV records, fields that we consider mandatory today can easily be +dropped in future (when coupled with a new feature bit) without needing to +completely redefine the gossip message in order to make the field optional. ## Block-height fields In the messages defined in this document, block heights are used as timestamps -instead of the UNIX timestamps used in the legacy set of gossip messages. +instead of the UNIX timestamps used in the legacy set of gossip messages. ### Rate Limiting @@ -157,25 +178,23 @@ block. To allow for bursts, nodes are encouraged not to use the latest block height for their latest announcements/updates but rather to backdate and use older block heights that they have not used in an announcement/update. There of course needs to be a limit on the start block height that the node can use: -for `channel_update_2` messages, the first timestamp must be the block height in -which the channel funding transaction was mined and all updates after the -initial one must have increasing timestamps. Nodes are then responsible for -building up their own timestamp buffer: if they want to be able to send -multiple `channel_update_2` messages per block, then they will need to ensure -that there are blocks during which they do not broadcast any updates. This +for `channel_update_2` messages, the first `blockheight` must be the block +height in which the channel funding transaction was mined and all updates after +the initial one must have increasing block heights. Nodes are then responsible +for building up their own timestamp buffer: if they want to be able to send +multiple `channel_update_2` messages per block, then they will need to ensure +that there are blocks during which they do not broadcast any updates. This provides an incentive for nodes not to spam the network with too many updates. -To also prevent nodes from building up too large of a burst-buffer with which -they can spam the network and to give a limit to how low the block height on a -`node_announcement_2` can be: nodes should not be allowed to use a block height -smaller 2016 (~ one week worth of blocks) below the current block height. +TODO: +- how do we choose a minimum block-height for `node_announcement_2`? ### Simplifies Channel Announcement Queries In the legacy gossip protocol, the timestamp of the `channel_announcement` is hard to define since the message itself does not have a `timestamp` field. This -makes timestamp based gossip queries tricky. By using block heights as -timestamps instead, there is an implicit timestamp associated with the +makes timestamp based gossip queries tricky. By using block heights as +timestamps instead, there is an implicit timestamp associated with the `channel_announcement_2`: the block in which the funding transaction is mined. ## Bootstrapping Taproot Gossip @@ -186,8 +205,8 @@ protocol, the following scenarios may exist for any node on the network: | scenario | has legacy channels | has taproot channels | should send `node_announcement` | should send `node_announcement_2` | |----------|---------------------|-----------------------|---------------------------------|-----------------------------------| | 1 | no | no | no | no | -| 2 | yes | no | yes | no | -| 3 | yes | yes | yes | no | +| 2 | yes | no | yes | ? | +| 3 | yes | yes | yes | ? | | 4 | no | yes | no | yes | ### Scenario 1 @@ -197,91 +216,76 @@ or new node announcement messages. ### Scenario 2 -If a node has legacy channels but no taproot channels, they should broadcast -only a legacy `node_announcement` message. Both taproot-gossip aware and unaware -nodes will be able to verify the node announcement since both groups are able to -process the `channel_announcement` for the legacy channel(s). The reason why -upgraded nodes should continue to broadcast the legacy announcement is because -this is the most effective way of spreading the `option_taproot_gossip` feature -bit since un-upgraded nodes can assist in spreading the message. +If a node has legacy channels but no taproot channels, they should continue to +broadcast the legacy `node_announcement` message so that un-upgraded nodes can +continue to receive `node_annoucement`s from these nodes which will initially +also be the most effective way to spread the `option_taproot_gossip` feature +bit to the rest of the network which will then allow upgraded nodes to find +each-other. + +TODO: should these nodes also send the new node announcement? if so: +- how do we deal with differences in the two announcements? +- also, how does a receiving node confirm which announcement is the latest +one given that they don't use the same timestamp type? ### Scenario 3 -If a node has both legacy channels and taproot channels, then like Scenario 2 -nodes, they should continue broadcasting the legacy `node_announcement` -message. +Similar to scenario 2. ### Scenario 4 -In this scenario, a node has only taproot channels and no legacy channels. This -means that they cannot broadcast a legacy `node_announcement` message since -un-upgraded nodes will drop this message due to the fact that no legacy -`channel_announcement` message would have been received for that node. These -nodes will also not be able to use a legacy `node_announcement` to propagate -their new `node_announcement_2` message. +If a node has no more legacy channels, then it will not be able to advertise +a legacy `node_announcement` since un-upgraded nodes will drop the announcements +due to no open channel will be known for that node. So in this case, only a +new `node_announcement_2` can be used. ### Considerations & Suggestions While the network is in the upgrade phase, the following suggestions apply: -- Keeping at least a single, announced, legacy channel open during the initial - phase of the transition to the new gossip protocol could be very beneficial - since nodes can continue to broadcast their legacy `node_announcement` and - thus more effectively advertise their support for `option_taproot_gossip`. -- Nodes are encouraged to actively connect to other nodes that advertise the - `option_taproot_gossip` feature bit as this is the only way in which they - will learn about taproot channel announcements and updates. -- Nodes should not use the new `node_announcement_2` message until they have - no more announced legacy channels. - -### Alternative Approaches - -An alternative approach would be to add an optional TLV to the legacy -`node_annoucement` that includes the serialised `node_announcement_2`. The nice -thing about this is that it allows the new `node_announcement_2` message to -propagate quickly through the network before the upgrade is complete. The -downside of this approach is that it would more than double the size of the -legacy `node_announcement` and most of the information would be duplicated. It -also makes gossip queries tricky since `node_announcement_2` uses a block-height -based timestamp instead of the unix timestamp used by the legacy message. -There also does not seem to be a big benefit in spreading the -`node_announcement_2` message quickly since the speed of propagation of the -`channel_announcement_2` and `channel_update_2` messages will still depend on a -network wide upgrade. +- Nodes are encouraged to actively connect to other nodes that advertise the + `option_taproot_gossip` feature bit as this is the only way in which they + will learn about taproot channel announcements and updates. This should be + done while taking care not to split the network. ## Specification -### Feature Bits +### Type Definitions -Unlike the original set of gossip messages, it needs to be explicitly advertised -that nodes are aware of the new gossip messages defined in this document at -least until the whole network has upgraded to only using taproot gossip. We thus -define a new feature bit, `option_taproot_gossip` to be included in the `init` -message as well as the _old_ `node_announcement` message. Note that for all -other feature bits with the `N` and `C` contexts, it can be assumed that those -contexts will switch to the new `node_announcement_2` and -`channel_announcement_2` messages for all feature bits _except_ for -`option_taproot_gossip` which only makes sense in the context of the old -`node_announcement` message and not the new `node_announcement_v2` message. -The `option_taproot` feature bit can also be implied when using the new taproot -gossip messages. +The following convenient types are defined: -| Bits | Name | Description | Context | Dependencies | -|-------|-------------------------|---------------------------------------------------|---------|------------------| -| 32/33 | `option_taproot_gossip` | Nodes that understand the taproot gossip messages | IN | `option_taproot` | +* `bip340_sig`: a 64-byte bitcoin Elliptic Curve Schnorr signature as + per [BIP-340][bip-340]. +* `partial_signature`: a 32-byte partial MuSig2 signature as defined + in [BIP-MuSig2][bip-musig2]. +* `public_nonce`: a 66-byte public nonce as defined in [BIP-MuSig2][bip-musig2]. +* `utf8`: a byte as part of a UTF-8 string. A writer MUST ensure an array of + these is a valid UTF-8 string, a reader MAY reject any messages containing an + array of these which is not a valid UTF-8 string. +* `boolean_tlv`: a zero length TLV record. If the TLV is present then true is + implied, otherwise false is implied. + +### Feature Bits -A node can be assumed to understand the new gossip v2 messages if: +A new feature bit, `option_taproot_gossip`, is introduced. Nodes can use this +feature bit in the `init` and _legacy_ `node_announcement` messages to advertise +that they understand the new set of taproot gossip messages and that will +therefore be able to route over Taproot Channels. If a node advertises +both the `option_taproot_gossip` _and_ the `option_taproot` feature bits, then +that node has the ability to open and announce a Simple Taproot Channel. -- They advertise `option_taproot_gossip` in the `init` or - legacy `node_announcement` messages - OR -- They have broadcast one of the new gossip messages defined in this document. +| Bits | Name | Description | Context | Dependencies | +|-------|-------------------------|-------------------------------------------|---------|--------------| +| 32/33 | `option_taproot_gossip` | Node understands taproot gossip messages | IN | | -Advertisement of the `option_taproot_gossip` feature bit should be taken to -mean: +### Feature Bit Contexts -- The node understands and is able to forward all the taproot gossip messages. -- The node may be willing to open an announced taproot channel. +For all feature bits other than `option_taproot_gossip` defined in +[Bolt 9][bolt-9-features] with the `N` and `C` contexts, it can be assumed that +those contexts will now refer to the new `node_announcement_2` and +`channel_announcement_2` messages defined in this document. The +`option_taproot_gossip` feature bit only makes sense in the context of the +legacy messages since it can be implied with the new taproot gossip messages. ### `open_channel` Extra Requirements @@ -289,16 +293,14 @@ These extra requirements only apply if the `option_taproot` channel type is set in the `open_channel` message. The sender: - - if `option_taproot_gossip` was negotiated: - MAY set the `announce_channel` bit in `channel_flags` - otherwise: - MUST NOT set the `announce_channel` bit. -The receiving node MUST fail the channel if: - -- if `option_taproot_gossip` was not negotiated and the `announce_channel` - bit in the `channel_flags` was set. +The receiver: +- if `option_taproot_gossip` was not negotiated and the `announce_channel` bit + in `channel_flags` was set, MUST fail the channel. ### `channel_ready` Extensions @@ -307,92 +309,100 @@ These extensions only apply if the `option_taproot` channel type was set in the 1. `tlv_stream`: `channel_ready_tlvs` 2. types: - 1. type: 0 (`announcement_node_pubnonce`) - 2. data: - * [`66*byte`: `public_nonce`] - 3. type: 2 (`announcement_bitcoin_pubnonce`) - 4. data: - * [`66*byte`: `public_nonce`] - -### Requirements - -The sender: - - - MUST set the `announcement_node_pubnonce` and - `announcement_bitcoin_pubnonce` tlv fields in `channel_ready`. - - SHOULD use the MuSig2 `NonceGen` algorithm to generate two unique secret - nonces and use these to determine the corresponding public nonces: - `announcement_node_pubnonce` and `announcement_bitcoin_pubnonce`. - -The recipient: - - - MUST fail the channel if: - - if the `announcement_node_pubnonce` or `announcement_bitcoin_pubnonce` tlv - fields are missing. - - if the `announcement_node_pubnonce` and `announcement_bitcoin_pubnonce` - are equal. - -### Rationale + 1. type: 0 (`announcement_node_pubnonce`) + 2. data: + * [`66*byte`: `public_nonce`] + 3. type: 2 (`announcement_bitcoin_pubnonce`) + 4. data: + * [`66*byte`: `public_nonce`] -The final signature included in the `channel_announcement_v2` message will be a -single [BIP-340][bip-340] signature that needs to be valid for a public key -derived by aggregating all the `node_ID` and `bitcoin_key` public keys. The -signature for this key will thus be created by aggregating (via MuSig2) four -partial signatures. One for each of the keys: `node_ID_1`, `node_ID_2`, -`bitcoin_key_1` and `bitcoin_key_2`. A nonce will need to be generated and -exchanged for each of the keys and so each node will need to send the other node -two nonces. The `announcement_node_nonce` is for `node_ID_x` and the -`announcement_bitcoin_nonce` is for `bitcoin_key_x`. +#### Requirements -Since the channel can only be announced once the `channel_ready` messages have -been exchanged and since it is generally preferred to keep nonce exchanges as -Just In Time as possible, the nonces are exchanged via the `channel_ready` -message. +The sender: -## The `announcement_signatures_2` Message +- MAY send `channel_ready` message without the `announcement_node_pubnonce` and + `announcement_bitcoin_pubnonce` fields. +- Once the channel is ready to be announced, the node: + - SHOULD send `channel_ready` with the `announcement_node_pubnonce` and + `announcement_bitcoin_pubnonce` fields set. The `announcement_node_pubnonce` + must be set to the public nonce to be used for signing with the node's + bitcoin key and the `announcement_bitcoin_pubnonce` must be set to the + public nonce to be used for signing with the node's node ID key. + - Upon reconnection, if a fully signed `channel_announcement_2` has not yet + been constructed: + - SHOULD re-send `channel_ready` with the nonce fields set. +- Once a `channel_ready` message with announcement nonces has been both sent and + received: + - MUST proceed with constructing and sending the `announcement_signatures_2` + message. + +- TODO: recommend nonce generation technique. +- TODO: can we guarantee progress here? + +The recipient: + +- If the nonce fields are set: + - If only one of the nonce fields are set: + - MUST ignore the message. + - SHOULD send a warning. + - MAY fail the connection. + - If the channel has not reached sufficient confirmations: + - SHOULD ignore the message. + - Otherwise: + - MUST store the nonces so that they can be used for the partial signature + construction required for constructing the `announcement_signatures` + message. + - If it has not yet done so, SHOULD respond with its own `channel_ready` + message with the nonce fields set. + +#### Rationale + +It cannot be a requirement that a node include the nonce fields in the +`channel_ready` since for cases such as zero-conf channels, nodes may send +`channel_ready` multiple times throughout the life of the channel to update it's +preferred channel alias, and it does not make sense to require that the nonce +fields be populated once the channel has already been announced. + +### The `announcement_signatures_2` Message Like the legacy `announcement_signatures` message, this is a direct message between the two endpoints of a channel and serves as an opt-in mechanism to -allow the announcement of the channel to the rest of the network. - -1. type: xxx (`announcement_signatures_2`) -2. data (tlv_stream): - 1. type: 0 (`channel_id`) - 2. data: - * [`channel_id`:`channel_id`] - 3. type: 2 (`short_channel_id`) - 4. data: - * [`short_channel_id`:`short_channel_id`] - 5. type: 4 (`partial_signature`) - 6. data: - * [`partial_signature`:`partial_signature`] - -### Requirements - -The requirements are similar to the ones defined for the legacy -`announcement_signatures`. The below requirements assume that the +allow the announcement of the channel to the rest of the network. + +1. type: 260 (`announcement_signatures_2`) +2. data: + * [`channel_id`:`channel_id`] + * [`short_channel_id`:`short_channel_id`] + * [`partial_signature`:`partial_signature`] + +#### Requirements + +The requirements are similar to the ones defined for the legacy +`announcement_signatures`. The below requirements assume that the `option_taproot` channel type was set in `open_channel`. A node: -- if the `open_channel` message has the `announce_channel` bit set AND a +- if the `open_channel` message has the `announce_channel` bit set AND a `shutdown` message has not been sent: - - MUST send the `announcement_signatures_2` message once `channel_ready` - has been sent and received AND the funding transaction has at least six - confirmations. - - MUST set the `partial_signature` field to the 32-byte `partial_sig` value of - the partial signature calculated as described in [Partial Signature - Calculation](#partial-signature-calculation). The message to be signed is - `MsgHash("channel_announcement", "announcement_sig", m)` where `m` is the - serialisation of the `channel_announcement_2` message excluding the - `announcement_sig` field (see the - [`MsgHash`](#signature-message-construction) definition). + - MUST send the `announcement_signatures_2` message once a `channel_ready` + message containing the announcement nonces has been sent and received AND + the funding transaction has at least six confirmations. + - MUST set the `partial_signature` field to the 32-byte `partial_sig` value + of the partial signature calculated as described in [Partial Signature + Calculation](#partial-signature-calculation). The message to be signed is + `MsgHash("channel_announcement", "announcement_sig", m)` where `m` is the + serialisation of the `channel_announcement_2` message tlv stream (see the + [`MsgHash`](#signature-message-construction) definition). - otherwise: - MUST NOT send the `announcement_signatures_2` message. - upon reconnection (once the above timing requirements have been met): - - MUST respond to the first `announcement_signatures_2` message with its own - `announcement_signatures_2` message. + - MUST re-send a `channel_ready` message with the nonce fields set and await + a reply. + - Then, MUST respond to the first `announcement_signatures_2` message with + its own `announcement_signatures_2` message. - if it has NOT received an `announcement_signatures_2` message: - - SHOULD retransmit the `announcement_signatures_2` message. + - SHOULD retransmit the `channel_ready` and `announcement_signatures_2` + messages. A recipient node: - if the `short_channel_id` is NOT correct: @@ -408,239 +418,182 @@ A recipient node: - MAY send a `warning` and close the connection, or send an `error` and fail the channel. -### Rationale +#### Rationale The message contains the necessary partial signature, by the sender, that the recipient will be able to combine with their own partial signature to construct -the signature to put in the `channel_announcement_v2` message. Unlike the legacy -`announcement_signatures` message, `announcement_signatures_v2` only has one +the signature to put in the `channel_announcement_2` message. Unlike the legacy +`announcement_signatures` message, `announcement_signatures_2` only has one signature field. This field is a MuSig2 partial signature which is the aggregation of the two signatures that the sender would have created (one for `bitcoin_key_x` and another for `node_ID_x`). -## The `channel_announcement_2` Message +### The `channel_announcement_2` Message -This gossip message contains ownership information regarding a taproot channel. -It ties each on-chain Bitcoin key that makes up the taproot output key to the -associated Lightning node key, and vice-versa. The channel is not practically -usable until at least one side has announced its fee levels and expiry, using +This gossip message contains ownership information regarding a taproot channel. +It ties each on-chain Bitcoin key that makes up the taproot output key to the +associated Lightning node key, and vice-versa. The channel is not practically +usable until at least one side has announced its fee levels and expiry, using `channel_update_2`. See [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification) for more information regarding the requirements for proving the existence of a channel. -1. type: xxx (`channel_announcement_2`) -2. data: (tlv_stream): - 1. type: 0 (`announcement_sig`) - 2. data: - * [`bip340_sig`:`bip340_sig`] - 3. type: 1 (`chain_hash`) - 4. data: - * [`chain_hash`:`chain_hash`] - 5. type: 2 (`features`) - 6. data: - * [`...*byte`: `features`] - 7. type: 4 (`short_channel_id`) - 8. data: - * [`short_channel_id`:`short_channel_id`] - 9. type: 6 (`node_id_1`) - 10. data: - * [`point`:`point`] - 11. type: 8 (`node_id_2`) - 12. data: - * [`point`:`point`] - 13. type: 3 (`bitcoin_key_1`) - 14. data: - * [`point`:`point`] - 15. type: 5 (`bitcoin_key_2`) - 16. data: - * [`point`:`point`] - 17. type: 7 (`tap_tweak`) - 18. data: - * [`point`:`point`] - -### Requirements - -The origin node: - -- If the chain being referred to is not the Bitcoin blockchain: - - MUST set `chain_hash` to the 32-byte hash that uniquely identifies the chain - that the channel was opened within: -- otherwise, MUST not set `chain_has` as the _Bitcoin blockchain_ is assumed. -- MUST set `short_channel_id` to refer to the confirmed funding transaction, as - specified in [BOLT #2](02-peer-protocol.md#the-channel_ready-message). - - Note: the corresponding output MUST be a P2TR, as described - in [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification). -- 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 two compressed keys sorted in ascending lexicographic order. -- MUST set `bitcoin_key_1` and `bitcoin_key_2` to `node_id_1` and `node_id_2`'s - respective `funding_pubkey`s. -- MUST set `features` based on what features were negotiated for this channel, - according to [BOLT #9](09-features.md#assigned-features-flags) -- MUST set `announcement_sig` signature to the [BIP-340][bip-340] signature - calculated by passing the partial signatures sent and received during the - `announcement_signatures_2` exchange to the - [MuSig2 PartialSigAgg][musig-partial-sig-agg] function. - -The receiving node: - -- If any even typed messages are not present: - - SHOULD send a `warning`. - - MAY close the connection. - - MUST ignore the message. -- MUST verify the integrity AND authenticity of the message by verifying the - `announcement_sig` as per [BIP 340][bip-340-verify]. -- if there is an unknown even bit in the `features` field: - - MUST NOT attempt to route messages through the channel. -- if the `short_channel_id`'s output does NOT correspond to a P2TR (using - `bitcoin_key_1` and `bitcoin_key_2`, as specified in - [BOLT #3](03-transactions.md#funding-transaction-output)) OR the output is - spent: - - MUST ignore the message. -- if the specified `chain_hash` is unknown to the receiver: - - MUST ignore the message. -- otherwise: - - if `announcement_sig` is invalid OR NOT correct: - - SHOULD send a `warning`. - - MAY close the connection. - - MUST ignore the message. - - otherwise: - - if `node_id_1` OR `node_id_2` are blacklisted: - - SHOULD ignore the message. - - otherwise: - - if the transaction referred to was NOT previously announced as a - channel: - - SHOULD queue the message for rebroadcasting. - - MAY choose NOT to for messages longer than the minimum - expected length. - - if it has previously received a valid `channel_announcement_2`, for - the same transaction, in the same block, but for a - different `node_id_1` or `node_id_2`: - - SHOULD blacklist the previous message's `node_id_1` - and `node_id_2`, as well as this `node_id_1` and `node_id_2` AND - forget any channels connected to them. - - otherwise: - - SHOULD store this `channel_announcement_2`. -- once its funding output has been spent OR reorganized out: - - SHOULD forget a channel after a 12-block delay. - -### Rationale - -Both nodes are required to sign to indicate they are willing to route other -payments via this channel (i.e. be part of the public network); requiring their -aggregated MuSig2 Schnorr signature proves that they control the channel. +1. type: 267 (`channel_announcement_2`) +2. data: + * [`bip340_sig`:`announcement_signature`] + * [`channel_announcement_2_tlvs`:`tlvs`] -The blacklisting of conflicting nodes disallows multiple different -announcements. Such conflicting announcements should never be broadcast by any -node, as this implies that keys have leaked. +1. `tlv_stream`: `channel_announcement_2_tlvs` +2. types: + 1. type: 0 (`chain_hash`) + 2. data: + * [`chain_hash`:`chain_hash`] + 1. type: 2 (`features`) + 2. data: + * [`...*byte`:`features`] + 1. type: 4 (`short_channel_id`) + 2. data: + * [`short_channel_id`:`short_channel_id`] + 1. type: 6 (`capacity_satoshis`) + 2. data: + * [`u64`:`capacity_satoshis`] + 1. type: 8 (`node_id_1`) + 2. data: + * [`point`:`node_id_1`] + 1. type: 10 (`node_id_2`) + 2. data: + * [`point`:`node_id_2`] + 1. type: 12 (`bitcoin_key_1`) + 2. data: + * [`point`:`bitcoin_key_1`] + 1. type: 14 (`bitcoin_key_2`) + 2. data: + * [`point`:`bitcoin_key_2`] + 1. type: 16 (`merkle_root_hash`) + 2. data: + * [`32*byte`:`hash`] -While channels should not be advertised before they are sufficiently deep, the -requirement against rebroadcasting only applies if the transaction has not moved -to a different block. +#### Message Field Descriptions -In order to avoid storing excessively large messages, yet still allow for -reasonable future expansion, nodes are permitted to restrict rebroadcasting -(perhaps statistically). +TODO -New channel features are possible in the future: backwards compatible (or -optional) features will have _odd_ feature bits, while incompatible features -will have _even_ feature bits -(["It's OK to be odd!"](00-introduction.md#glossary-and-terminology-guide)). +#### Requirements -A delay of 12-blocks is used when forgetting a channel on funding output spend -as to permit a new `channel_announcement_2` to propagate which indicates this -channel was spliced. +TODO -## The `node_announcement_2` Message +### The `node_announcement_2` Message -This gossip message, like the legacy `node_announcement` message, allows a node -to indicate extra data associated with it, in addition to its public key. +This gossip message, like the legacy `node_announcement` message, allows a node +to indicate extra data associated with it, in addition to its public key. To avoid trivial denial of service attacks, nodes not associated with an already known channel (legacy or taproot) are ignored. -Unlike the legacy `node_announcement` message, this message makes use of a -Schnorr signature instead of an ECDSA one. This will allow nodes to be backed +Unlike the legacy `node_announcement` message, this message makes use of a +BIP340 signature instead of an ECDSA one. This will allow nodes to be backed by multiple keys since MuSig2 can be used to construct the single signature. -The other two main differences from the legacy message are that the timestamp -is now a block height and that the message is purely TLV based. +1. type 269 +2. data: + * [`bip340_sig`:`announcement_sig`] + * [`node_announcement_2_tlvs`:`tlvs`] -1. type: xxx (`node_announcement_2`) -2. data: (tlv_stream): - 1. type: 0 (`announcement_sig`) +1. `tlv_stream`: `node_announcement_2_tlvs` +2. types: + 1. type: 0 (`features`) + 1. type: 1 (`color`) + 2. data: + * [`rgb_color`:`rgb_color`] 2. data: - * [`bip340_sig`:`bip340_sig`] - 3. type: 2 (`features`) - 4. data: * [`...*byte`: `features`] - 5. type: 4 (`block_height`) - 6. data: + 1. type: 2 (`block_height`) + 1. type: 3 (`alias`) + 2. data: + * [`...*utf8`:`alias`] + 2. data: * [`u32`: `block_height`] - 7. type: 6 (`node_ID`) - 8. data: + 1. type: 4 (`node_id`) + 2. data: * [`point`:`node_id`] - 9. type: 1 (`color`) - 10. data: - * [`rgb_color`:`rgb_color`] - 11. type: 3 (`alias`) - 12. data: - * [`...*utf8`:`alias`] - 13. type: 5 (`ipv4_addrs`) - 14. data: - * [`...*ipv4_addr`: `ipv4_addresses`] - 15. type: 7 (`ipv6_addrs`) - 16. data: - * [`...*ipv6_addr`: `ipv6_addresses`] - 17. type: 9 (`tor_v3_addrs`) - 18. data: - * [`...*tor_v3_addr`: `tor_v3_addresses`] - 19. type: 11 (`dns_hostname`) - 20. data: - * [`dns_hostname`: `dns_hostname`] + 1. type: 5 (`ipv4_addrs`) + 2. data: + * [`...*ipv4_addr`: `ipv4_addresses`] + 1. type: 7 (`ipv6_addrs`) + 2. data: + * [`...*ipv6_addr`: `ipv6_addresses`] + 1. type: 9 (`tor_v3_addrs`) + 2. data: + * [`...*tor_v3_addr`: `tor_v3_addresses`] + 1. type: 11 (`dns_hostnames`) + 2. data: + * [`...*dns_hostname`: `dns_hostnames`] The following subtypes are defined: 1. subtype: `rgb_color` 2. data: - * [`byte`:`red`] - * [`byte`:`green`] - * [`byte`:`blue`] + * [`byte`:`red`] + * [`byte`:`green`] + * [`byte`:`blue`] -3. subtype: `ipv4_addr` -4. data: +1. subtype: `ipv4_addr` +2. data: * [`u32`:`addr`] - * [`tu16`:`port`] + * [`u16`:`port`] -5. subtype: `ipv6_addr` -6. data: +1. subtype: `ipv6_addr` +2. data: * [`16*byte`:`addr`] - * [`tu16`:`port`] - -7. subtype: `tor_v3_addr` -8. data: - * [`35*utf8`:`onion_addr`] - * [`tu16`:`port`] + * [`u16`:`port`] -9. subtype: `dns_hostname` -10. data: - * [`...*utf8`:`hostname`] - * [`tu16`:`port`] +1. subtype: `tor_v3_addr` +2. data: + * [`35*utf8`:`onion_addr`] + * [`u16`:`port`] -`tor_v3_address` is a Tor version 3 ([prop224]) onion service address; -Its `onion_addr` encodes: -`[32:32_byte_ed25519_pubkey] || [2:checksum] || [1:version]`, where -`checksum = sha3(".onion checksum" | pubkey || version)[:2]`. +1. subtype: `dns_hostname` +2. data: + * [`u16`:`len`] + * [`len*utf8`:`hostname`] + * [`u16`:`port`] -The `dns_hostname` `hostname` MUST be ASCII characters. Non-ASCII characters -MUST be encoded using [Punycode][punycode]. The length of the `hostname` cannot -exceed 255 bytes. +#### Message Field Descriptions -### Requirements +- `bip340_sig` is the [BIP340][bip-340] signature for the `node_id` key. The + message to be signed is `MsgHash("node_announcement_2", "bip340_sig", m)` + where `m` is the serialised TLV stream (see the + [`MsgHash`](#signature-message-construction) definition). +- `features` is a bit vector with bits set according to [BOLT #9](09-features.md#assigned-features-flags) +- `block_height` allows for ordering or messages in the case of multiple + announcements and also allows for natural rate limiting of + `node_announcement_2` messages. +- `node_id` is the public key associated with this node. It must match a node ID + that has previously been announced in the `node_id_1` or `node_id_2` fields of + a `channel_announcement` or `channel_announcement_2` message for a channel + that is still open. +- `rgb_color` is an optional field that a node may use to assign itself a color. +- `alias` is an optional field that a node may use to assign itself an alias + that can then be used for a nicer UX on intelligence services. If this field + is set, then it MUST be 32 utf8 characters or less. +- `ipv4_addr` is an ipv4 address and port. +- `ipv6_addr` is an ipv6 address and port. +- `tor_v3_addr` is a Tor version 3 ([prop224]) onion service address; + Its `onion_addr` encodes: + `[32:32_byte_ed25519_pubkey] || [2:checksum] || [1:version]`, where + `checksum = sha3(".onion checksum" | pubkey || version)[:2]`. +- `dns_hostname` is a DNS hostname. The `hostname` MUST be ASCII characters. + Non-ASCII characters MUST be encoded using [Punycode][punycode]. The length of + the `hostname` cannot exceed 255 bytes. + +#### Requirements + +TODO: flesh out when it is ok to send new vs old node announcement. Is it ever +ok to send both? if so - what if the info inside them differs? The sender: +- MUST set TLV fields 0, 2 and 4. - MUST set `announcement_sig` to a valid [BIP340][bip-340] signature for the `node_id` key. The message to be signed is `MsgHash("node_announcement_2", "announcement_sig", m)` where `m` is the @@ -649,11 +602,13 @@ The sender: [`MsgHash`](#signature-message-construction) definition). - MAY set `color` and `alias` to customise appearance in maps and graphs. - If the node sets the `alias`: - - MUST use 32 utf8 characters or less. + - MUST use 32 utf8 characters or less. - MUST set `block_height` to be greater than that of any previous `node_announcement_2` it has previously created. - - MUST set it to a block height less than the latest block's height but no - more than 1440 lower. +- TODO: how to determine a lower bound for the block_height of the node_ann? + cant say "must be greater than or = oldest advertised channel" since a node + could open a new channel and close the previous which would then invalidate + the node_announcement. - If the node wishes to announce its willingness to accept incoming network connections: - SHOULD set at least one of types 7-10. @@ -665,12 +620,10 @@ The sender: - MUST not create a `ipv4_addr`, `ipv6_addr` or `dns_hostname` with a `port` equal to 0. - MUST set `features` according to [BOLT #9][bolt-9-features]. -- SHOULD only start using this message once they no longer have announced legacy - channels. - -The receiving node: -- If any type between even-typed values are missing: +The receiver: + +- If type 0, 2 or 4 is missing: - SHOULD send a `warning`. - MAY close the connection. - MUST ignore the message. @@ -682,7 +635,7 @@ The receiving node: - SHOULD send a `warning`. - MAY close the connection. - MUST NOT process the message further. -- if `announcement_sig` is NOT a valid [BIP340][bip-340] signature (using +- if `announcement_sig` is NOT a valid [BIP340][bip-340] signature (using `node_id` over the message): - SHOULD send a `warning`. - MAY close the connection. @@ -694,17 +647,16 @@ The receiving node: - MUST NOT route a payment _through_ the node. - if `port` is equal to 0 for any `ipv6_addr` OR `ipv4_addr` OR `hostname`: - SHOULD ignore that address. -- if `node_id` is NOT previously known from a `channel_announcement` OR - `channel_announcement_2` message, OR if `blockheight` is NOT greater than the +- if `node_id` is NOT previously known from a `channel_announcement` OR + `channel_announcement_2` message, OR if `blockheight` is NOT greater than the last-received `node_announcement_2` from this `node_id`: - - SHOULD ignore the message. + - SHOULD ignore the message. - otherwise: - - if `block_height` is greater than the last-received `node_announcement_2` + - if `block_height` is greater than the last-received `node_announcement_2` from this `node_id`: - - SHOULD queue the message for rebroadcasting. + - SHOULD queue the message for rebroadcasting. - MAY use `rgb_color` AND `alias` to reference nodes in interfaces. - SHOULD insinuate their self-signed origins. -- SHOULD ignore any legacy `node_announcement` message for this `node_ID`. ### Rationale @@ -713,24 +665,21 @@ optional) ones will have _odd_ `feature` _bits_, incompatible ones will have _even_ `feature` _bits_. These will be propagated normally; incompatible feature bits here refer to the nodes, not the `node_announcement_2` message itself. -Since the legacy `node_announcement` uses a UNIX based `timestamp` field and -this message uses block heights, deciding which message is the latest one could -be tricky. To simplify the logic, the decision is made that once a -`node_announcement_2` is received, then any legacy `node_announcement` messages -received for the same `node_id` can be ignored. - ### Security Considerations for Node Aliases -The security considerations for node aliases mentioned in +The security considerations for node aliases mentioned in [BOLT #7][bolt-7-alias-security] apply here too. -## The `channel_update_2` Message +### The `channel_update_2` Message + +- TODO: should updates for legacy channels also sometimes be broadcast using the + new format for easier set reconciliation? -After a channel has been initially announced via `channel_announcement_2`, each -side independently announces the fees and minimum expiry delta it requires to -relay HTLCs through this channel. Each uses the 8-byte short channel id that -matches the `channel_announcement_2` and the 1-bit `channel_flags` field to -indicate which end of the channel it's on (origin or final). A node can do this +After a channel has been initially announced via `channel_announcement_2`, each +side independently announces the fees and minimum expiry delta it requires to +relay HTLCs through this channel. Each uses the 8-byte short channel id that +matches the `channel_announcement_2` and the `direction` field to +indicate which end of the channel it's on (origin or final). A node can do this multiple times, in order to change fees. Note that the `channel_update` gossip message is only useful in the context @@ -741,165 +690,170 @@ come into play. When building the route, amounts and expiries for HTLCs need to be calculated backward from the destination to the source. The exact initial value for `amount_msat` and the minimal value for `cltv_expiry`, to be used for the last HTLC in the route, are provided in the payment request + (see [BOLT #11][[bolt-11-tagged-fields]]). +1. type 271 +2. data: + * [`bip340_sig`:`bip340_sig`] + * [`channel_update_2_tlvs`:`tlvs`] -1. type: xxx (`channel_update_2`) -2. data: (tlv_stream): - 1. type: 0 (`update_sig`) +1. `tlv_stream`: `channel_update_2_tlvs` +2. types: + 1. type: 0 (`chain_hash`) 2. data: - * [`bip340_sig`:`bip340_sig`] - 3. type: 1 (`chain_hash`) - 4. data: * [`chain_hash`:`chain_hash`] - 5. type: 2 (`block_height`) - 6. data: - * [`u32`: `block_height`] - 7. type: 4 (`channel_flags`) - 8. data: - * [`...*byte`, `channel_flags`] - 9. type: 6 (`cltv_expiry_delta`) - 10. data: - * [`tu32`, `cltv_expiry_delta`] - 11. type: 8 (`htlc_min_msat`) - 12. data: - * [`tu64`, `htlc_min_msat`] - 13. type: 10 (`htlc_max_msat`) - 14. data: - * [`tu64`, `htlc_max_msat`] - 15. type: 12 (`fee_base_msat`) - 16. data: - * [`tu32`, `fee_base_msat`] - 17. type: 14 (`fee_prop_millionths`) - 18. data: - * [`tu32`, `fee_prop_millionths`] - -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 concerning the channel. The following table specifies the meaning of its -individual bits: - -| Bit Position | Name | Meaning | -|--------------|-------------|----------------------------------| -| 0 | `direction` | Direction this update refers to. | -| 1 | `disable` | Disable the channel. | - -The `node_id` for the signature verification is taken from the corresponding -`channel_announcement_2`: `node_id_1` if the least-significant bit of flags is -0 or `node_id_2` otherwise. - -### Requirements + 1. type: 2 (`short_channel_id`) + 2. data: + * [`short_channel_id`:`short_channel_id`] + 1. type: 4 (`block_height`) + 2. data: + * [`u32`:`block_height`] + 1. type: 6 (`disable_flags`) + 2. data: + * [`byte`:`disable_flags`] + 1. type: 8 (`direction`) + 2. data: + * [`boolean_tlv`:`direction`] + 1. type: 10 (`cltv_expiry_delta`) + 2. data: + * [`u16`:`cltv_expiry_delta`] + 1. type: 12 (`htlc_minimum_msat`) + 2. data: + * [`u64`:`htlc_minimum_msat`] + 1. type: 14 (`htlc_maximum_msat`) + 2. data: + * [`u64`:`htlc_maximum_msat`] + 1. type: 16 (`fee_base_msat`) + 2. data: + * [`u32`:`fee_base_msat`] + 1. type: 18 (`fee_proportional_millionths`) + 2. data: + * [`u32`:`fee_proportional_millionths`] + + +The `disable_flags` bitfield is used to indicate that the channel is temporarily +disabled. The following table specifies the meaning of the individual bits: + +| Bit Position | Name | Meaning | +|---------------|------------|-------------------------------------------------| +| 0 | `incoming` | The node can't receive via this channel | +| 1 | `outgoing` | The node can't forward or send via this channel | + +Both the `incoming` and `outgoing` bit can be set to indicate that the channel +peer is offline. + +#### Message Field Descriptions + +- The `chain_hash` is used to identify the blockchain containing the channel + being referred to. +- `short_channel_id` is the unique identifier of the channel. If the channel is + unannounced, then this may be set to an agreed upon alias. +- `block_height` is the timestamp associated with the message. A node may not + send two `channel_update` messages with the same `block_height`. The + `block_height` must also be greater than or equal to the block height + indicated by the `short_channel_id` used in the `channel_announcement` and + must not be less than current best block height minus 2016 (~2 weeks of + blocks). +- The `disable` bit field can be used to advertise to the network that a channel + is disabled and that it should not be used for routing. The individual + `disable_flags` bits can be used to communicate more fine-grained information. +- The `direction` is used to indicate which node in the channel node pair + has created and signed this message. If the node was `node_id_1` in the + `channel_announcment` message then the `direction` is 0 (false) otherwise + it is 1 (true) and the node is `node_id_2` in the `channel_announcement` + message. +- `cltv_expiry_delta` is the number of blocks that the node will subtract from + an incoming HTLC's `cltv_expiry`. +- `htlc_minimum_msat` is the minimum HTLC value (in millisatoshi) that the + channel peer will accept. +- `htlc_maximum_msat` is the maximum value the node will send through this + channel for a single HTLC. + - MUST be less than or equal to the channel capacity + - MUST be less than or equal to the `max_htlc_value_in_flight_msat` it + received from the peer in the `open_channel` message. +- `fee_base_msat` is the base fee (in millisatoshis) that the node will charge + for an HTLC. +- `fee_proportional_millionths` is the amount (in millionths of a satoshi) that + node will charge per transferred satoshi. + +#### TLV Defaults + +For types 0, 6, 8, 10, 12, 14, 16 and 18, the following defaults apply if the +TLV is not present in the message: + +| `channel_update_2` TLV Type | Default Value | Comment | +|------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------------------------------------| +| 0 (`chain_hash`) | `6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000` | The hash of the genesis block of the mainnet Bitcoin blockchain. | +| 6 (`disable`) | empty | | +| 8 (`direction`) | false | | +| 10 (`cltv_expiry_delta`) | 80 | | +| 12 (`htlc_minimum_msat`) | 1 | | +| 14 (`htlc_maximum_msat`) | floor(channel capacity / 2) | // TODO: remove this since makes encoding/decoding dependent on things outside the message? | +| 16 (`fee_base_msat`) | 1000 | | +| 18 (`fee_proportional_millionths`) | 1 | | + +#### Requirements The origin node: -- If the chain being referred to is not the Bitcoin blockchain: - - MUST set `chain_hash` to the 32-byte hash that uniquely identifies the - chain that the channel was opened within: -- otherwise, MUST not set `chain_hash` as the _Bitcoin blockchain_ is assumed. -- MUST NOT send `channel_update_2` before `channel_ready` has been received. -- MUST NOT send `channel_update_2` for legacy (non-taproot) channels. -- MAY create a `channel_update_2` 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). + +- For all fields with defined defaults: + - SHOULD not include the field in the TLV stream if the default value is + desired. +- MUST use the `channel_update_2` message to communicate channel parameters of a + Taproot channel. +- MAY use the `channel_update_2` message to communicate channel parameters of a + legacy (P2SH) channel. +- MUST NOT send a created `channel_update_2` before `channel_ready` has been + received. +- For an unannounced channel (i.e. one where the `announce_channel` bit was not + set in `open_channel`): + - MAY create a `channel_update_2` to communicate the channel parameters to the + channel peer. - MUST set the `short_channel_id` to either an `alias` it has received from the peer, or the real channel `short_channel_id`. - - MUST NOT forward such a `channel_update` to other peers, for privacy + - MUST NOT forward such a `channel_update_2` to other peers, for privacy reasons. - - Note: such a `channel_update`, one not preceded by a - `channel_announcement`, is invalid to any other peer and would be - discarded. -- MUST set `update_sig` to a valid [BIP340][bip-340] signature for its own +- For announced channels: + - MUST set `chain_hash` AND `short_channel_id` to match the 32-byte hash AND + 8-byte channel ID that uniquely identifies the channel specified in the + `channel_announcement_2` message. +- MUST set `bip340_sig` to a valid [BIP340][bip-340] signature for its own `node_id` key. The message to be signed is - `MsgHash("channel_update_2", "update_sig", m)` where `m` is the serialisation - of the `channel_update` message excluding the `update_sig` field (see the + `MsgHash("channel_update_2", "bip340_sig", m)` where `m` is the serialised + TLV stream of the `channel_update` (see the [`MsgHash`](#signature-message-construction) definition). -- MUST set `chain_hash` AND `short_channel_id` to match the 32-byte hash AND - 8-byte channel ID that uniquely identifies the channel specified in the - `channel_announcement_2` message. -- if the origin node is `node_id_1` in the message: - - MUST set the `direction` bit of `channel_flags` to 0. -- otherwise: - - MUST set the `direction` bit of `channel_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. -- MAY create and send a `channel_update_2` 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 - settlement). - - MAY send a subsequent `channel_update_2` with the `disable` bit set to 0 - to re-enable the channel. -- MUST set `block_height` greater or equal to the block height that the - channel's funding transaction was mined in AND to greater than any - previously-sent `channel_update_2` for this `short_channel_id` AND no less - than 1440 blocks below the current best block height . -- MUST set `cltv_expiry_delta` to the number of blocks it will subtract from - an incoming HTLC's `cltv_expiry`. -- MUST set `htlc_minimum_msat` to the minimum HTLC value (in millisatoshi) - that the channel peer will accept. -- MUST set `fee_base_msat` to the base fee (in millisatoshi) it will charge - for any HTLC. -- 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_2`s +- SHOULD NOT create redundant `channel_update_2`s. - If it creates a new `channel_update_2` with updated channel parameters: - - SHOULD keep accepting the previous channel parameters for 10 minutes + - SHOULD keep accepting the previous channel parameters for 2 blocks. The receiving node: -- if the `short_channel_id` does NOT match a previous `channel_announcement_2`, - OR if the channel has been closed in the meantime: +- If the `short_channel_id` does NOT match a previous `channel_announcement_2` + or `channel_announcement`, OR if the channel has been closed in the meantime: - MUST ignore `channel_update_2`s that do NOT correspond to one of its own channels. -- SHOULD accept `channel_update_2`s for its own taproot channels (even if - non-public), in order to learn the associated origin nodes' forwarding - parameters. -- if `update_sig` is NOT a valid [BIP340][bip-340] signature (using `node_id` +- SHOULD accept `channel_update_2`s for its own channels (even if non-public), + in order to learn the associated origin nodes' forwarding parameters. +- if `bip340_sig` is NOT a valid [BIP340][bip-340] signature (using `node_id` over the message): - SHOULD send a `warning` and close the connection. - MUST NOT process the message further. -- if the specified `chain_hash` value is unknown (meaning it isn't active on - the specified chain): - - MUST ignore the channel update. -- if the `block_height` is equal to the last-received `channel_update_2` for - this `short_channel_id` AND `node_id`: - - if the fields below `block_height` differ: - - MAY blacklist this `node_id`. - - MAY forget all channels associated with it. - - if the fields below `block_height` are equal: - - SHOULD ignore this message -- if `block_height` is lower than that of the last-received - `channel_update_2` for this `short_channel_id` AND for `node_id`: - - SHOULD ignore the message. -- otherwise: - - if the `block_height` is a block height greater than the current best block - height: - - MAY discard the `channel_update_2`. - - if the `block_height` block height is more than 1440 blocks less than the - current best block height: - - MAY discard the `channel_update_2`. - - otherwise: - - SHOULD queue the message for rebroadcasting. -- if `htlc_maximum_msat` is 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. - -### Rationale -TODO +#### Rationale + +- An even type is used so that best-effort propagation can be used. -## Query Messages +### Query Messages -TODO: any updates that need to happen to this section? +TODO # Appendix A: Algorithms -### Partial Signature Calculation +## Partial Signature Calculation -When both nodes have exchanged `channel_ready` then they will each have the -following information: +When both nodes have exchanged a `channel_ready` message containing the +`announcement_node_pubnonce` and `announcement_bitcoin` fields then they will +each have the following information: - `node_1` will know: - `bitcoin_priv_key_1`, `node_ID_priv_key_1`, @@ -990,7 +944,7 @@ signature aggregation is simply the addition of the two signatures: Where `n` is the [secp256k1][secp256k1] curve order. -### Partial Signature Verification +## Partial Signature Verification Since the partial signature put in `announcement_signatures_2` is the addition of two of four signatures required to make up the final MuSig2 signature, the @@ -1031,25 +985,115 @@ found in the [MuSig2][musig-session-ctx] spec. - Let `g = 1` if `has_even_y(Q)`, otherwise `let g = -1 mod n` - Fail if `s*G != R_e + e*g*P` -### Signature Message Construction +## Verifying the `channel_announcement_2` signature + +For all the following cases, it should be verified that the output at the +provided `short_channel_id` is an unspent Taproot output. + +### The 3-of-3 MuSig2 Scenario + +In the case where a received `channel_announcement_2` message is received which +does not have the optional `bitcoin_key_*` fields, the signature of the message +should be verified as a 3-of-3 MuSig2 signature. The keys involved are: +`node_id_1`, `node_id_2` and the taproot output key (`tr_output_key`) found in +the channel's funding output specified by the provided `short_channel_id`. + +The full list of inputs required: +- `node_id_1` +- `node_id_2` +- `tr_output_key` +- `msg`: the serialised `channel_announcement_2` tlv stream. +- `sig`: the 64-byte BIP340 signature found in the + `channel_announcement_signature` field of the `channel_announcement_2` + message. This signature must be parsed into `R` and `s` values as defined in + BIP327. + +The aggregate key can be calculated as follows: + +``` +P_agg = MuSig2.KeyAgg(MuSig2.KeySort(`node_id_1`, `node_id_2`, `tr_output_key`)) +``` + +The signature can then be verified as follows: +- Let `pk` = `bytes(P_agg)` where the `bytes` function is defined in BIP340. +- Let `m` = `MsgHash("channel_announcement_2", "announcement_signature", msg)` +- Use the BIP340 `Verify` function to determine if the signature is valid by + passing in `pk`, `m` and `sig`. + +### The 4-of-4 MuSig2 Scenario + +In the case where a received `channel_announcement_2` message is received which +does have both the optional `bitcoin_key_*` fields, the signature of the message +should be verified as a 4-of-4 MuSig2 signature. The keys involved are: +`node_id_1`, `node_id_2`, `bitcoin_key_1` and `bitcoin_key_2`. The message may +also optionally contain the `merkle_root_hash` field in this case. + +Before the actual signature verification is done, it should first be asserted +that the taproot output key found in the funding output is in-fact made up of +the provided bitcoin keys. This can be done as follows: + +First, calculate the aggregate key used as the internal key for the taproot +output, `P_internal`: + +``` +P_internal = KeyAgg(MuSig2.KeySort(`bitcoin_key_1`, `bitcoin_key_2`)) +``` + +- Let `P_o` be the taproot output key found on-chain in the funding output + referred to by the SCID. +- if the `merkle_root_hash` field is _not_ provided: + - Fail the check if `P_internal != P_o` +- otherwise, if the `merkle_root_hash` is provided: + - let `p` = `bytes(P_internal)` + - let `t = hash_TapTweak(p || merkle_root_hash)` where `hash_TapTweak` uses + the `hash_name(x)` method defined in BIP340. + - Fail if `P_o != P_internal + t*G` + +If the above check is successful, then it has been shown that the output key +is constructed from the two provided bitcoin keys. So now the signature +verification can be done. + +The full list of inputs required: +- `node_id_1` +- `node_id_2` +- `bitcoin_key_1` +- `bitcoin_key_2` +- `msg`: the serialised `channel_announcement_2` tlv stream. +- `sig`: the 64-byte BIP340 signature found in the + `channel_announcement_signature` field of the `channel_announcement_2` + message. This signature must be parsed into `R` and `s` values as defined in + BIP327. + +The aggregate key can be calculated as follows: + +``` +P_agg = MuSig2.KeyAgg(MuSig2.KeySort(`node_id_1`, `node_id_2`, `bitcoin_key_1`, `bitcoin_key_2`)) +``` + +The signature can then be verified as follows: +- Let `pk` = `bytes(P_agg)` where the `bytes` function is defined in BIP340. +- Let `m` = `MsgHash("channel_announcement_2", "announcement_signature", msg)` +- Use the BIP340 `Verify` function to determine if the signature is valid by + passing in `pk`, `m` and `sig`. + +## Signature Message Construction The following `MsgHash` function is defined which can be used to construct a 32-byte message that can be used as a valid input to the [BIP-340][bip-340] signing and verification algorithms. _MsgHash:_ - - _inputs_: +- _inputs_: * `message_name`: UTF-8 string * `field_name`: UTF-8 string * `message`: byte array - - Let `tag` = "lightning" || `message_name` || `field_name` - - return SHA256(SHA256(`tag`) || SHA256(`tag`) || SHA256(`message`)) - +- Let `tag` = "lightning" || `message_name` || `field_name` +- return SHA256(SHA256(`tag`) || SHA256(`tag`) || SHA256(`message`)) # Appendix B: Test Vectors -TODO(elle) +TODO # Acknowledgements From 07a87448646dc06be7b0e175a3ebaa07602da4b0 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 6 May 2024 10:50:48 +0200 Subject: [PATCH 4/6] fixup! bolt-taproot-gossip --- bolt-taproot-gossip.md | 88 ++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/bolt-taproot-gossip.md b/bolt-taproot-gossip.md index b4fbcd55d..797bf5daf 100644 --- a/bolt-taproot-gossip.md +++ b/bolt-taproot-gossip.md @@ -254,7 +254,7 @@ While the network is in the upgrade phase, the following suggestions apply: The following convenient types are defined: -* `bip340_sig`: a 64-byte bitcoin Elliptic Curve Schnorr signature as +* `bip340sig`: a 64-byte bitcoin Elliptic Curve Schnorr signature as per [BIP-340][bip-340]. * `partial_signature`: a 32-byte partial MuSig2 signature as defined in [BIP-MuSig2][bip-musig2]. @@ -262,8 +262,6 @@ The following convenient types are defined: * `utf8`: a byte as part of a UTF-8 string. A writer MUST ensure an array of these is a valid UTF-8 string, a reader MAY reject any messages containing an array of these which is not a valid UTF-8 string. -* `boolean_tlv`: a zero length TLV record. If the TLV is present then true is - implied, otherwise false is implied. ### Feature Bits @@ -350,7 +348,7 @@ The recipient: - SHOULD ignore the message. - Otherwise: - MUST store the nonces so that they can be used for the partial signature - construction required for constructing the `announcement_signatures` + construction required for constructing the `announcement_signatures_2` message. - If it has not yet done so, SHOULD respond with its own `channel_ready` message with the nonce fields set. @@ -390,7 +388,7 @@ A node: - MUST set the `partial_signature` field to the 32-byte `partial_sig` value of the partial signature calculated as described in [Partial Signature Calculation](#partial-signature-calculation). The message to be signed is - `MsgHash("channel_announcement", "announcement_sig", m)` where `m` is the + `MsgHash("channel_announcement", "signature", m)` where `m` is the serialisation of the `channel_announcement_2` message tlv stream (see the [`MsgHash`](#signature-message-construction) definition). - otherwise: @@ -442,7 +440,7 @@ channel. 1. type: 267 (`channel_announcement_2`) 2. data: - * [`bip340_sig`:`announcement_signature`] + * [`bip340sig`:`signature`] * [`channel_announcement_2_tlvs`:`tlvs`] 1. `tlv_stream`: `channel_announcement_2_tlvs` @@ -494,9 +492,9 @@ Unlike the legacy `node_announcement` message, this message makes use of a BIP340 signature instead of an ECDSA one. This will allow nodes to be backed by multiple keys since MuSig2 can be used to construct the single signature. -1. type 269 +1. type: 269 (`node_announcement_2`) 2. data: - * [`bip340_sig`:`announcement_sig`] + * [`bip340sig`:`signature`] * [`node_announcement_2_tlvs`:`tlvs`] 1. `tlv_stream`: `node_announcement_2_tlvs` @@ -560,8 +558,8 @@ The following subtypes are defined: #### Message Field Descriptions -- `bip340_sig` is the [BIP340][bip-340] signature for the `node_id` key. The - message to be signed is `MsgHash("node_announcement_2", "bip340_sig", m)` +- `signature` is the [BIP340][bip-340] signature for the `node_id` key. The + message to be signed is `MsgHash("node_announcement_2", "signature", m)` where `m` is the serialised TLV stream (see the [`MsgHash`](#signature-message-construction) definition). - `features` is a bit vector with bits set according to [BOLT #9](09-features.md#assigned-features-flags) @@ -594,11 +592,11 @@ ok to send both? if so - what if the info inside them differs? The sender: - MUST set TLV fields 0, 2 and 4. -- MUST set `announcement_sig` to a valid [BIP340][bip-340] signature for the +- MUST set `signature` to a valid [BIP340][bip-340] signature for the `node_id` key. The message to be signed is - `MsgHash("node_announcement_2", "announcement_sig", m)` where `m` is the + `MsgHash("node_announcement_2", "signature", m)` where `m` is the serialisation of the `node_announcement_2` message excluding the - `announcement_sig` field (see the + `signature` field (see the [`MsgHash`](#signature-message-construction) definition). - MAY set `color` and `alias` to customise appearance in maps and graphs. - If the node sets the `alias`: @@ -635,7 +633,7 @@ The receiver: - SHOULD send a `warning`. - MAY close the connection. - MUST NOT process the message further. -- if `announcement_sig` is NOT a valid [BIP340][bip-340] signature (using +- if `signature` is NOT a valid [BIP340][bip-340] signature (using `node_id` over the message): - SHOULD send a `warning`. - MAY close the connection. @@ -692,9 +690,9 @@ value for `amount_msat` and the minimal value for `cltv_expiry`, to be used for the last HTLC in the route, are provided in the payment request (see [BOLT #11][[bolt-11-tagged-fields]]). -1. type 271 +1. type: 271 (`channel_update_2`) 2. data: - * [`bip340_sig`:`bip340_sig`] + * [`bip340sig`:`signature`] * [`channel_update_2_tlvs`:`tlvs`] 1. `tlv_stream`: `channel_update_2_tlvs` @@ -711,9 +709,7 @@ the last HTLC in the route, are provided in the payment request 1. type: 6 (`disable_flags`) 2. data: * [`byte`:`disable_flags`] - 1. type: 8 (`direction`) - 2. data: - * [`boolean_tlv`:`direction`] + 1. type: 8 (`second_peer`) 1. type: 10 (`cltv_expiry_delta`) 2. data: * [`u16`:`cltv_expiry_delta`] @@ -731,17 +727,21 @@ the last HTLC in the route, are provided in the payment request * [`u32`:`fee_proportional_millionths`] -The `disable_flags` bitfield is used to indicate that the channel is temporarily -disabled. The following table specifies the meaning of the individual bits: +The `disable_flags` bitfield is used to indicate that the channel is either +temporarily or permanently disabled. The following table specifies the meaning +of the individual bits: -| Bit Position | Name | Meaning | -|---------------|------------|-------------------------------------------------| -| 0 | `incoming` | The node can't receive via this channel | -| 1 | `outgoing` | The node can't forward or send via this channel | +| Bit Position | Name | Meaning | +|--------------|-------------|-------------------------------------------------------| +| 0 | `permanant` | The disable update is permanent (otherwise temporary) | +| 1 | `incoming` | The node can't receive via this channel | +| 2 | `outgoing` | The node can't forward or send via this channel | Both the `incoming` and `outgoing` bit can be set to indicate that the channel peer is offline. +If the `permanant` bit is set, then the channel can be considered closed. + #### Message Field Descriptions - The `chain_hash` is used to identify the blockchain containing the channel @@ -757,11 +757,10 @@ peer is offline. - The `disable` bit field can be used to advertise to the network that a channel is disabled and that it should not be used for routing. The individual `disable_flags` bits can be used to communicate more fine-grained information. -- The `direction` is used to indicate which node in the channel node pair - has created and signed this message. If the node was `node_id_1` in the - `channel_announcment` message then the `direction` is 0 (false) otherwise - it is 1 (true) and the node is `node_id_2` in the `channel_announcement` - message. +- The `second_peer` is used to indicate which node in the channel node pair has + created and signed this message. If present, the node was `node_id_2` in the + `channel_announcment`, otherwise the node is `node_id_1` in the + `channel_announcement` message. - `cltv_expiry_delta` is the number of blocks that the node will subtract from an incoming HTLC's `cltv_expiry`. - `htlc_minimum_msat` is the minimum HTLC value (in millisatoshi) that the @@ -778,14 +777,13 @@ peer is offline. #### TLV Defaults -For types 0, 6, 8, 10, 12, 14, 16 and 18, the following defaults apply if the +For types 0, 6, 10, 12, 14, 16 and 18, the following defaults apply if the TLV is not present in the message: | `channel_update_2` TLV Type | Default Value | Comment | |------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------------------------------------| | 0 (`chain_hash`) | `6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000` | The hash of the genesis block of the mainnet Bitcoin blockchain. | | 6 (`disable`) | empty | | -| 8 (`direction`) | false | | | 10 (`cltv_expiry_delta`) | 80 | | | 12 (`htlc_minimum_msat`) | 1 | | | 14 (`htlc_maximum_msat`) | floor(channel capacity / 2) | // TODO: remove this since makes encoding/decoding dependent on things outside the message? | @@ -817,9 +815,9 @@ The origin node: - MUST set `chain_hash` AND `short_channel_id` to match the 32-byte hash AND 8-byte channel ID that uniquely identifies the channel specified in the `channel_announcement_2` message. -- MUST set `bip340_sig` to a valid [BIP340][bip-340] signature for its own +- MUST set `signature` to a valid [BIP340][bip-340] signature for its own `node_id` key. The message to be signed is - `MsgHash("channel_update_2", "bip340_sig", m)` where `m` is the serialised + `MsgHash("channel_update_2", "signature", m)` where `m` is the serialised TLV stream of the `channel_update` (see the [`MsgHash`](#signature-message-construction) definition). - SHOULD NOT create redundant `channel_update_2`s. @@ -834,7 +832,7 @@ The receiving node: channels. - SHOULD accept `channel_update_2`s for its own channels (even if non-public), in order to learn the associated origin nodes' forwarding parameters. -- if `bip340_sig` is NOT a valid [BIP340][bip-340] signature (using `node_id` +- if `signature` is NOT a valid [BIP340][bip-340] signature (using `node_id` over the message): - SHOULD send a `warning` and close the connection. - MUST NOT process the message further. @@ -890,7 +888,7 @@ aggnonce = Musig2.NonceAgg(announcement_node_secnonce_1, announcement_bitcoin_pu ``` The message, `msg` that the peers will sign is the serialisation of -`channel_announcement_2` _without_ the `announcement_sig` field (i.e. without +`channel_announcement_2` _without_ the `signature` field (i.e. without type 0) With all the information mentioned, both peers can now construct the @@ -1003,10 +1001,9 @@ The full list of inputs required: - `node_id_2` - `tr_output_key` - `msg`: the serialised `channel_announcement_2` tlv stream. -- `sig`: the 64-byte BIP340 signature found in the - `channel_announcement_signature` field of the `channel_announcement_2` - message. This signature must be parsed into `R` and `s` values as defined in - BIP327. +- `sig`: the 64-byte BIP340 signature found in the `signature` field of the + `channel_announcement_2` message. This signature must be parsed into `R` and + `s` values as defined in BIP327. The aggregate key can be calculated as follows: @@ -1016,7 +1013,7 @@ P_agg = MuSig2.KeyAgg(MuSig2.KeySort(`node_id_1`, `node_id_2`, `tr_output_key`)) The signature can then be verified as follows: - Let `pk` = `bytes(P_agg)` where the `bytes` function is defined in BIP340. -- Let `m` = `MsgHash("channel_announcement_2", "announcement_signature", msg)` +- Let `m` = `MsgHash("channel_announcement_2", "signature", msg)` - Use the BIP340 `Verify` function to determine if the signature is valid by passing in `pk`, `m` and `sig`. @@ -1059,10 +1056,9 @@ The full list of inputs required: - `bitcoin_key_1` - `bitcoin_key_2` - `msg`: the serialised `channel_announcement_2` tlv stream. -- `sig`: the 64-byte BIP340 signature found in the - `channel_announcement_signature` field of the `channel_announcement_2` - message. This signature must be parsed into `R` and `s` values as defined in - BIP327. +- `sig`: the 64-byte BIP340 signature found in the `signature` field of the + `channel_announcement_2` message. This signature must be parsed into `R` and + `s` values as defined in BIP327. The aggregate key can be calculated as follows: @@ -1072,7 +1068,7 @@ P_agg = MuSig2.KeyAgg(MuSig2.KeySort(`node_id_1`, `node_id_2`, `bitcoin_key_1`, The signature can then be verified as follows: - Let `pk` = `bytes(P_agg)` where the `bytes` function is defined in BIP340. -- Let `m` = `MsgHash("channel_announcement_2", "announcement_signature", msg)` +- Let `m` = `MsgHash("channel_announcement_2", "signature", msg)` - Use the BIP340 `Verify` function to determine if the signature is valid by passing in `pk`, `m` and `sig`. From 82d3efa8ef4f2c1b8b528a7d3156f2ae179497a4 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 6 May 2024 12:03:39 +0200 Subject: [PATCH 5/6] fixup! bolt-taproot-gossip --- 07-routing-gossip.md | 132 +++++++++++++++++++++++++++-------------- bolt-taproot-gossip.md | 4 +- 2 files changed, 89 insertions(+), 47 deletions(-) diff --git a/07-routing-gossip.md b/07-routing-gossip.md index e306b6788..0efb95c46 100644 --- a/07-routing-gossip.md +++ b/07-routing-gossip.md @@ -624,13 +624,13 @@ Nodes can signal that they support extended gossip queries with the `gossip_quer `encoded_query_flags` is an array of bitfields, one bigsize per bitfield, one bitfield for each `short_channel_id`. Bits have the following meaning: -| Bit Position | Meaning | -| ------------- | ---------------------------------------- | -| 0 | Sender wants `channel_announcement` | -| 1 | Sender wants `channel_update` for node 1 | -| 2 | Sender wants `channel_update` for node 2 | -| 3 | Sender wants `node_announcement` for node 1 | -| 4 | Sender wants `node_announcement` for node 2 | +| Bit Position | Meaning | +|--------------|---------------------------------------------------| +| 0 | Sender wants `channel_announcement`/`_2` | +| 1 | Sender wants `channel_update`/`_2` for node 1 | +| 2 | Sender wants `channel_update`/`_2` for node 2 | +| 3 | Sender wants `node_announcement`/`_2` for node 1 | +| 4 | Sender wants `node_announcement`/`_2` for node 2 | Query flags must be minimally encoded, which means that one flag will be encoded with a single byte. @@ -640,11 +640,11 @@ Query flags must be minimally encoded, which means that one flag will be encoded * [`byte`:`full_information`] This is a general mechanism which lets a node query for the -`channel_announcement` and `channel_update` messages for specific channels -(identified via `short_channel_id`s). This is usually used either because -a node sees a `channel_update` for which it has no `channel_announcement` or -because it has obtained previously unknown `short_channel_id`s -from `reply_channel_range`. +`channel_announcement`/`_2` and `channel_update`/`_2` messages for specific +channels (identified via `short_channel_id`s). This is usually used either +because a node sees a `channel_update`/`_2` for which it has no +`channel_announcement`/`_2` or because it has obtained previously unknown +`short_channel_id`s from `reply_channel_range`. #### Requirements @@ -655,7 +655,7 @@ The sender: that the `short_channel_id`s refer to. - MUST set the first byte of `encoded_short_ids` to the encoding type. - MUST encode a whole number of `short_channel_id`s to `encoded_short_ids` - - MAY send this if it receives a `channel_update` for a + - MAY send this if it receives a `channel_update`/`_2` for a `short_channel_id` for which it has no `channel_announcement`. - SHOULD NOT send this if the channel referred to is not an unspent output. - MAY include an optional `query_flags`. If so: @@ -682,24 +682,25 @@ The receiver: - MAY close the connection. - MUST respond to each known `short_channel_id`: - if the incoming message does not include `encoded_query_flags`: - - with a `channel_announcement` and the latest `channel_update` for each end - - MUST follow with any `node_announcement`s for each `channel_announcement` + - with a `channel_announcement`/`_2` and the latest `channel_update`/_2` + for each end + - MUST follow with any `node_announcement`/`_2`s for each `channel_announcement`/`_2` - otherwise: - We define `query_flag` for the Nth `short_channel_id` in `encoded_short_ids` to be the Nth bigsize of the decoded `encoded_query_flags`. - if bit 0 of `query_flag` is set: - - MUST reply with a `channel_announcement` - - if bit 1 of `query_flag` is set and it has received a `channel_update` from `node_id_1`: - - MUST reply with the latest `channel_update` for `node_id_1` - - if bit 2 of `query_flag` is set and it has received a `channel_update` from `node_id_2`: - - MUST reply with the latest `channel_update` for `node_id_2` - - if bit 3 of `query_flag` is set and it has received a `node_announcement` from `node_id_1`: - - MUST reply with the latest `node_announcement` for `node_id_1` - - if bit 4 of `query_flag` is set and it has received a `node_announcement` from `node_id_2`: - - MUST reply with the latest `node_announcement` for `node_id_2` + - MUST reply with a `channel_announcement`/`_2` + - if bit 1 of `query_flag` is set and it has received a `channel_update`/`_2` from `node_id_1`: + - MUST reply with the latest `channel_update`/`_2` for `node_id_1` + - if bit 2 of `query_flag` is set and it has received a `channel_update`/`_2` from `node_id_2`: + - MUST reply with the latest `channel_update`/`_2` for `node_id_2` + - if bit 3 of `query_flag` is set and it has received a `node_announcement`/`_2` from `node_id_1`: + - MUST reply with the latest `node_announcement`/`_2` for `node_id_1` + - if bit 4 of `query_flag` is set and it has received a `node_announcement`/`_2` from `node_id_2`: + - MUST reply with the latest `node_announcement`/`_2` for `node_id_2` - SHOULD NOT wait for the next outgoing gossip flush to send these. - - SHOULD avoid sending duplicate `node_announcements` in response to a single `query_short_channel_ids`. + - SHOULD avoid sending duplicate `node_announcements`/`_2` in response to a single `query_short_channel_ids`. - MUST follow these responses with `reply_short_channel_ids_end`. - if does not maintain up-to-date channel information for `chain_hash`: - MUST set `full_information` to 0. @@ -734,12 +735,12 @@ timeouts. It also causes a natural ratelimiting of queries. `query_option_flags` is a bitfield represented as a minimally-encoded bigsize. Bits have the following meaning: -| Bit Position | Meaning | -| ------------- | ----------------------- | -| 0 | Sender wants timestamps | -| 1 | Sender wants checksums | +| Bit Position | Meaning | +|--------------|---------------------------------------| +| 0 | Sender wants timestamps/block heights | +| 1 | Sender wants checksums | -Though it is possible, it would not be very useful to ask for checksums without asking for timestamps too: the receiving node may have an older `channel_update` with a different checksum, asking for it would be useless. And if a `channel_update` checksum is actually 0 (which is quite unlikely) it will not be queried. +Though it is possible, it would not be very useful to ask for checksums without asking for timestamps/block heights too: the receiving node may have an older `channel_update` with a different checksum, asking for it would be useless. And if a `channel_update` checksum is actually 0 (which is quite unlikely) it will not be queried. 1. type: 264 (`reply_channel_range`) 2. data: @@ -753,15 +754,21 @@ Though it is possible, it would not be very useful to ask for checksums without 1. `tlv_stream`: `reply_channel_range_tlvs` 2. types: - 1. type: 1 (`timestamps_tlv`) + 1. type: 1 (`timestamps_blockheights_tlv`) 2. data: * [`byte`:`encoding_type`] - * [`...*byte`:`encoded_timestamps`] + * [`...*byte`:`encoded_timestamps_blockheights`] 1. type: 3 (`checksums_tlv`) 2. data: * [`...*channel_update_checksums`:`checksums`] -For a single `channel_update`, timestamps are encoded as: +For the `timestamps_blockheights_tlv` field, the contents depends on whether the +associated channel update message is for a channel announced using +`channel_announcement` or `channel_announcement_2`. + +If the channel was announced using `channel_announcement`, then the associated +update will be a `channel_update`, meaning that the contents will represent +timestamps and will be encoded as: 1. subtype: `channel_update_timestamps` 2. data: @@ -772,7 +779,20 @@ Where: * `timestamp_node_id_1` is the timestamp of the `channel_update` for `node_id_1`, or 0 if there was no `channel_update` from that node. * `timestamp_node_id_2` is the timestamp of the `channel_update` for `node_id_2`, or 0 if there was no `channel_update` from that node. -For a single `channel_update`, checksums are encoded as: +If the channel was announced usig `channel_announcement_2`, then the associated +update is a `channel_update_2` and the contents will represent block heights and +will be encoded as: + +1. subtype: `channel_update_blockheights` +2. data: + * [`u32`:`block_height_node_id_1`] + * [`u32`:`block_height_node_id_2`] + +Where: +* `block_height_node_id_1` is the block height of the `channel_update_2` for `node_id_1`, or 0 if there was no `channel_update_2` from that node. +* `block_height_node_id_2` is the block height of the `channel_update_2` for `node_id_2`, or 0 if there was no `channel_update_2` from that node. + +For a single `channel_update`/`_2`, checksums are encoded as: 1. subtype: `channel_update_checksums` 2. data: @@ -780,10 +800,10 @@ For a single `channel_update`, checksums are encoded as: * [`u32`:`checksum_node_id_2`] Where: -* `checksum_node_id_1` is the checksum of the `channel_update` for `node_id_1`, or 0 if there was no `channel_update` from that node. -* `checksum_node_id_2` is the checksum of the `channel_update` for `node_id_2`, or 0 if there was no `channel_update` from that node. +* `checksum_node_id_1` is the checksum of the `channel_update`/`_2` for `node_id_1`, or 0 if there was no `channel_update`/`_2` from that node. +* `checksum_node_id_2` is the checksum of the `channel_update`/`_2` for `node_id_2`, or 0 if there was no `channel_update`/`_2` from that node. -The checksum of a `channel_update` is the CRC32C checksum as specified in [RFC3720](https://tools.ietf.org/html/rfc3720#appendix-B.4) of this `channel_update` without its `signature` and `timestamp` fields. +The checksum of a `channel_update`/`_2` is the CRC32C checksum as specified in [RFC3720](https://tools.ietf.org/html/rfc3720#appendix-B.4) of this `channel_update`/`_2` without its `signature` and `timestamp`/`block_height` fields. This allows querying for channels within specific blocks. @@ -807,6 +827,10 @@ The receiver of `query_channel_range`: - MUST limit `number_of_blocks` to the maximum number of blocks whose results could fit in `encoded_short_ids` - MAY split block contents across multiple `reply_channel_range`. + - If the sender of `query_channel_range` has not advertised the + `option_taproot_gossip` feature bit then the response MUST only include + short channel IDs for channels announced with the `channel_announcement` + message. - the first `reply_channel_range` message: - MUST set `first_blocknum` less than or equal to the `first_blocknum` in `query_channel_range` - MUST set `first_blocknum` plus `number_of_blocks` greater than `first_blocknum` in `query_channel_range`. @@ -818,7 +842,7 @@ The receiver of `query_channel_range`: - MUST set `sync_complete` to `true`. If the incoming message includes `query_option`, the receiver MAY append additional information to its reply: -- if bit 0 in `query_option_flags` is set, the receiver MAY append a `timestamps_tlv` that contains `channel_update` timestamps for all `short_channel_id`s in `encoded_short_ids` +- if bit 0 in `query_option_flags` is set, the receiver MAY append a `timestamps_blockheights_tlv` that contains `channel_update`/`_2` timestamps for all `short_channel_id`s in `encoded_short_ids` - if bit 1 in `query_option_flags` is set, the receiver MAY append a `checksums_tlv` that contains `channel_update` checksums for all `short_channel_id`s in `encoded_short_ids` #### Rationale @@ -842,6 +866,16 @@ The addition of timestamp and checksum fields allow a peer to omit querying for * [`chain_hash`:`chain_hash`] * [`u32`:`first_timestamp`] * [`u32`:`timestamp_range`] + * [`gossip_timestamps_filter_tlvs`:`tlvs`] + +1. `tlv_stream`: `gossip_timestamps_filter_tlvs` +2. types: + 1. type: 2 (`first_block`) + 2. data: + * [`u32`:`block_height`] + 1. type: 4 (`block_height_range`) + 2. data: + * [`u32`:`num_blocks`] This message allows a node to constrain future gossip messages to a specific range. A node which wants any gossip messages has @@ -861,20 +895,26 @@ The sender: The receiver: - SHOULD send all gossip messages whose `timestamp` is greater or equal to `first_timestamp`, and less than `first_timestamp` plus - `timestamp_range`. + `timestamp_range`. This applies to the messages: `channel_announcement`, + `channel_update` and `node_announcement`. - MAY wait for the next outgoing gossip flush to send these. - - SHOULD send gossip messages as it generates them regardless of `timestamp`. + - SHOULD send all gossip messages whose `block_height` is greater than or + equal to `first_block`, and less than `first_block` plus `num_blocks`. + - SHOULD send gossip messages as it generates them regardless of `timestamp`/`block_height`. - Otherwise (relayed gossip): - SHOULD restrict future gossip messages to those whose `timestamp` is greater or equal to `first_timestamp`, and less than - `first_timestamp` plus `timestamp_range`. - - If a `channel_announcement` has no corresponding `channel_update`s: - - MUST NOT send the `channel_announcement`. + `first_timestamp` plus `timestamp_range` or whose `block_height` is + greater than or equal to `first_block`, and less than `first_block` plus + `num_blocks`. + - If a `channel_announcement`/`_2` has no corresponding `channel_update`/`_2`s: + - MUST NOT send the `channel_announcement`/`_2`. - Otherwise: - MUST consider the `timestamp` of the `channel_announcement` to be the `timestamp` of a corresponding `channel_update`. - - MUST consider whether to send the `channel_announcement` after receiving the first corresponding `channel_update`. - - If a `channel_announcement` is sent: - - MUST send the `channel_announcement` prior to any corresponding `channel_update`s and `node_announcement`s. + - MUST consider the `block_height` of the `channel_announcement_2` to be the height of the block it was mined in. + - MUST consider whether to send the `channel_announcement`/`_2` after receiving the first corresponding `channel_update`/`_2`. + - If a `channel_announcement`/`_2` is sent: + - MUST send the `channel_announcement`/`_2` prior to any corresponding `channel_update`/`_2`s and `node_announcement`/`_2`s. #### Rationale diff --git a/bolt-taproot-gossip.md b/bolt-taproot-gossip.md index 797bf5daf..8f8352518 100644 --- a/bolt-taproot-gossip.md +++ b/bolt-taproot-gossip.md @@ -843,7 +843,9 @@ The receiving node: ### Query Messages -TODO +TODO: + 1. new first block height & block range fields in gossip_timestamp_range + 2. add block-height query option (like timestamps query option) # Appendix A: Algorithms From dda5beeb29f64085f57acea02bf58e4587f9b3c3 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Thu, 27 Mar 2025 11:38:10 +0200 Subject: [PATCH 6/6] fix: latest discussed updates as per https://delvingbitcoin.org/t/updates-to-the-gossip-1-75-proposal-post-ln-summit-meeting/1202 --- bolt-taproot-gossip.md | 615 ++++++++++++++++++++++++++--------------- 1 file changed, 392 insertions(+), 223 deletions(-) diff --git a/bolt-taproot-gossip.md b/bolt-taproot-gossip.md index 8f8352518..d4e8200ec 100644 --- a/bolt-taproot-gossip.md +++ b/bolt-taproot-gossip.md @@ -1,9 +1,11 @@ -# Extension BOLT XX: Taproot Gossip +# Extension BOLT XX: Gossip V2 -This document aims to update the gossip protocol defined in [BOLT 7][bolt-7] to -allow for advertisement and verification of taproot channels. An entirely new -set of gossip messages are defined that use [BIP-340][bip-340] signatures and -that use a mostly TLV based structure. +This document aims to define a gossip protocol which can be used to advertise +and verify both P2WSH channels and P2TR channels. The aim is that this protocol +could eventually completely replace the existing gossip protocol defined in +[BOLT 7][bolt-7] which can only be used to advertise P2WSH channels. An entirely +new set of gossip messages are defined that use [BIP-340][bip-340] signatures +and that use a pure TLV based structure. # Table Of Contents @@ -15,13 +17,16 @@ that use a mostly TLV based structure. * [Specification](#specification) * [Type Definitions](#type-definitions) * [Features Bits](#feature-bits) - * [Features Bit Contexts](#feature-bit-contexts) - * [`open_channel` Extra Requirements](#openchannel-extra-requirements) - * [`channel_ready` Extensions](#channelready-extensions) - * [The `announcement_signatures_2` Message](#the-announcementsignatures2-message) - * [The `channel_announcement_2` Message](#the-channelupdate2-message) - * [The `node_announcement_2` Message](#the-nodeannouncement2-message) - * [The `channel_update_2` Message](#the-channelupdate2-message) + * [`option_gossip_v2`](#option_gossip_v2) + * [`option_gossip_v2_p2wsh`](#option_gossip_v2_p2wsh) + * [`option_gossip_announce_private`](#option_gossip_announce_private) + * [`open_channel` Extensions](#open_channel-extensions) + * [`channel_ready` Extensions](#channel_ready-extensions) + * [`announcement_signatures` Extra requirements](#announcement_signatures-extra-requirements) + * [The `announcement_signatures_2` Message](#the-announcement_signatures_2-message) + * [The `channel_announcement_2` Message](#the-channel_announcement_2-message) + * [The `node_announcement_2` Message](#the-node_announcement_2-message) + * [The `channel_update_2` Message](#the-channel_update_2-message) * [Appendix A: Algorithms](#appendix-a-algorithms) * [Partial Signature Calculation](#partial-signature-calculation) * [Partial Signature Verification](#partial-signature-verification) @@ -34,8 +39,6 @@ that use a mostly TLV based structure. ## Terminology -- Collectively, the set of new gossip messages will be referred to as - `taproot gossip`. - `node_1` and `node_2` refer to the two parties involved in opening a channel. - `node_ID_1` and `node_ID_2` respectively refer to the public keys that `node_1` and `node_2` use to identify their nodes in the network. @@ -101,11 +104,11 @@ taproot_output_key = taproot_internal_key + tagged_hash("TapTweak", merkle_root_ In the case of Simple Taproot Channels, the `merkle_root_hash` will be equal to the serialisation of the `taproot_internal_key`. -The verification method used all depends on which information is provided in the -`channel_announcement_2` message. All of these verification methods require -the `node_id_1` and `node_id_2` to be provided along with a `short_channel_id` -that will allow the verifier to fetch the funding output from which the -`taproot_output_key` can be extracted. +If the funding output is P2TR, then the verification method used all depends on +which information is provided in the `channel_announcement_2` message. All of +these verification methods require the `node_id_1` and `node_id_2` to be +provided along with a `short_channel_id` that will allow the verifier to fetch +the funding output from which the `taproot_output_key` can be extracted. 1. If no bitcoin keys are provided, then the signature must be verified against the following public key: @@ -151,24 +154,24 @@ that will allow the verifier to fetch the funding output from which the ``` 5. The signature must then be verified against `P_agg`. -In terms of construction of the proofs, this document covers case 2 and 3. - ## TLV Based Messages The initial set of Lightning Network messages consisted of a flat set of serialised fields that were mandatory. Later on, TLV encoding was introduced which provided a backward compatible way to extend messages. To ensure that the new messages defined in this document remain as future-proof as possible, the -messages will mostly be pure TLV streams with a fixed 64-byte signature over the -tlv stream appended at the front of the message. By making all fields in the -messages TLV records, fields that we consider mandatory today can easily be -dropped in future (when coupled with a new feature bit) without needing to -completely redefine the gossip message in order to make the field optional. +messages will be pure TLV streams with a set TLV range of signed fields and +unsigned fields. That way, any signature fields can be put in the un-signed +range along with any other large and non-mandatory fields such as SPV proofs. +By making all fields in the messages TLV records, fields that we consider +mandatory today can easily be dropped in future (when coupled with a new +feature bit) without needing to completely redefine the gossip message in order +to make the field optional. ## Block-height fields In the messages defined in this document, block heights are used as timestamps -instead of the UNIX timestamps used in the legacy set of gossip messages. +instead of the UNIX timestamps used in the BOLT 7 set of gossip messages. ### Rate Limiting @@ -178,7 +181,7 @@ block. To allow for bursts, nodes are encouraged not to use the latest block height for their latest announcements/updates but rather to backdate and use older block heights that they have not used in an announcement/update. There of course needs to be a limit on the start block height that the node can use: -for `channel_update_2` messages, the first `blockheight` must be the block +for `channel_update_2` messages, the lowest allowed `blockheight` is the block height in which the channel funding transaction was mined and all updates after the initial one must have increasing block heights. Nodes are then responsible for building up their own timestamp buffer: if they want to be able to send @@ -186,67 +189,33 @@ multiple `channel_update_2` messages per block, then they will need to ensure that there are blocks during which they do not broadcast any updates. This provides an incentive for nodes not to spam the network with too many updates. -TODO: -- how do we choose a minimum block-height for `node_announcement_2`? - ### Simplifies Channel Announcement Queries -In the legacy gossip protocol, the timestamp of the `channel_announcement` is +In the BOLT 7 gossip protocol, the timestamp of the `channel_announcement` is hard to define since the message itself does not have a `timestamp` field. This makes timestamp based gossip queries tricky. By using block heights as timestamps instead, there is an implicit timestamp associated with the `channel_announcement_2`: the block in which the funding transaction is mined. -## Bootstrapping Taproot Gossip - -While the network upgrades from the legacy gossip protocol to the taproot gossip -protocol, the following scenarios may exist for any node on the network: - -| scenario | has legacy channels | has taproot channels | should send `node_announcement` | should send `node_announcement_2` | -|----------|---------------------|-----------------------|---------------------------------|-----------------------------------| -| 1 | no | no | no | no | -| 2 | yes | no | yes | ? | -| 3 | yes | yes | yes | ? | -| 4 | no | yes | no | yes | - -### Scenario 1 - -These nodes have no announced channels and so should not be broadcasting legacy -or new node announcement messages. - -### Scenario 2 - -If a node has legacy channels but no taproot channels, they should continue to -broadcast the legacy `node_announcement` message so that un-upgraded nodes can -continue to receive `node_annoucement`s from these nodes which will initially -also be the most effective way to spread the `option_taproot_gossip` feature -bit to the rest of the network which will then allow upgraded nodes to find -each-other. - -TODO: should these nodes also send the new node announcement? if so: -- how do we deal with differences in the two announcements? -- also, how does a receiving node confirm which announcement is the latest -one given that they don't use the same timestamp type? - -### Scenario 3 - -Similar to scenario 2. - -### Scenario 4 - -If a node has no more legacy channels, then it will not be able to advertise -a legacy `node_announcement` since un-upgraded nodes will drop the announcements -due to no open channel will be known for that node. So in this case, only a -new `node_announcement_2` can be used. - -### Considerations & Suggestions - -While the network is in the upgrade phase, the following suggestions apply: - -- Nodes are encouraged to actively connect to other nodes that advertise the - `option_taproot_gossip` feature bit as this is the only way in which they - will learn about taproot channel announcements and updates. This should be - done while taking care not to split the network. +## Interaction with BOLT 7 + +The idea is that the gossip message defined in this document could eventually +replace those defined in BOLT 7. The messages defined in this document can +therefore be used to advertise both P2WSH and P2TR channels. Doing this will +allow older channels to make use of the new gossip protocol and all its +advantages without needing to close all their channels and reopen them as PT2R +channels. The two protocols are to be seen as disjoint. This means, for example, +that a node may only advertise a `node_announcement_2` if it has advertised +a `channel_announcement_2`. This makes it easier to reason about the protocol. +Any nodes that understand both protocols are encouraged to persist both +advertisements in their database to cater for gossip syncing with older +peers, but they should favour the new protocol when making routing decisions. + +While the network is in the upgrade phase, nodes will likely want to advertise +on both the old and new protocols for P2WSH channels so that older nodes +continue to see their channels. Eventually, when most of the network has +advertised their understanding of the new protocol, nodes can stop advertising +on the old protocol. ## Specification @@ -263,47 +232,91 @@ The following convenient types are defined: these is a valid UTF-8 string, a reader MAY reject any messages containing an array of these which is not a valid UTF-8 string. -### Feature Bits - -A new feature bit, `option_taproot_gossip`, is introduced. Nodes can use this -feature bit in the `init` and _legacy_ `node_announcement` messages to advertise -that they understand the new set of taproot gossip messages and that will -therefore be able to route over Taproot Channels. If a node advertises -both the `option_taproot_gossip` _and_ the `option_taproot` feature bits, then -that node has the ability to open and announce a Simple Taproot Channel. - -| Bits | Name | Description | Context | Dependencies | -|-------|-------------------------|-------------------------------------------|---------|--------------| -| 32/33 | `option_taproot_gossip` | Node understands taproot gossip messages | IN | | +### Pure TLV messages -### Feature Bit Contexts +All the messages defined in this document are pure TLV streams. The signed TLV +range is defined as the inclusive ranges: 0 to 159 and 1000000000 to 2999999999. -For all feature bits other than `option_taproot_gossip` defined in -[Bolt 9][bolt-9-features] with the `N` and `C` contexts, it can be assumed that -those contexts will now refer to the new `node_announcement_2` and -`channel_announcement_2` messages defined in this document. The -`option_taproot_gossip` feature bit only makes sense in the context of the -legacy messages since it can be implied with the new taproot gossip messages. - -### `open_channel` Extra Requirements +### Feature Bits -These extra requirements only apply if the `option_taproot` channel type is set -in the `open_channel` message. +The proposed gossip upgrade is quite large and will require a lot of new code +for most implementations. It is therefore proposed that the upgrade be done +across a few feature bits. The following feature bits are proposed: + +| Bits | Name | Description | Context | Dependencies | +|-------|----------------------------------|-----------------------------------------------------------|---------|--------------------| +| 70/71 | `option_gossip_v2` | Node understands gossip v2 protocol | IN* | | +| 72/73 | `option_gossip_v2_p2wsh` | Node can advertise P2WSH channels with gossip v2 protocol | IN | `option_gossip_v2` | +| 74/75 | `option_gossip_announce_private` | Node is able to announce a previously unannounced channel | IN | | + +The N* context above serves to indicate the legacy `node_announcement` message. +All the rest of the contexts are for the new gossip messages defined in this +document. The `option_gossip_v2` bit is implied if a node is making use of +the new set of gossip messages. + +#### `option_gossip_v2` + +This feature bit indicates that a node is able to understand all the new gossip +`_v2` messages defined in this document. This means it is able to verify both +P2TR and P2WSH channels announced with the new protocol If this feature bit is +set along with `option_taproot`, then the node is also able to open and +announce Simple Taproot Channels using the new gossip protocol. This bit can +be set in the `init` message along with the _legacy_ `node_announcement` +message. + +#### `option_gossip_v2_p2wsh` + +This feature bit depends on `option_gossip_v2` and indicates that a node is able +to use the new gossip protocol to advertise P2WSH channels. This means both that +for new channels, it can use the new gossip protocol to advertise them and that +for any existing, public, P2WSH channels, it can re-advertise them using the new +gossip protocol. + +The reason this is a separate feature bit is that for some implementations, it +will be quite a large lift to support managing both sets of gossip messages for +a single channel and to support the flow of signing the announcement for +an existing channel. By separating out the bits, nodes can start announce +Simple Taproot Channels before they are able to re-announce their existing P2WSH +channels using the new gossip protocol. + +#### `option_gossip_announce_private` + +This feature bit indicates that a node is able to advertise a channel that +started out as unannounced. This means allowing the signing flow of the +`channel_announcement` and/or `channel_announcement_2` messages at any point +during the channel's lifetime even if the `announce_channel` bit was not set in +the `open_channel` message + +#### Future feature bits + +More feature bits may be added here to define, for example, different types of +channel proofs. An example is SPV proofs: a feature bit can be defined that +indicates that a node is able to produce an SPV proof and attach it to its +`channel_announcement_2` message if asked. + +### `open_channel` Extensions + +- If the `option_taproot` channel type was set in `open_channel`: + - The sender: + - If `option_gossip_v2` was negotiated: + - MAY set the `announce_channel` bit in `channel_flags` + - otherwise: + - MUST NOT set the `announce_channel` bit. + + - The receiver: + - if `option_gossip_v2` was not negotiated and the `announce_channel` bit + in `channel_flags` was set, MUST fail the channel. -The sender: -- if `option_taproot_gossip` was negotiated: - - MAY set the `announce_channel` bit in `channel_flags` -- otherwise: - - MUST NOT set the `announce_channel` bit. +#### Rationale -The receiver: -- if `option_taproot_gossip` was not negotiated and the `announce_channel` bit - in `channel_flags` was set, MUST fail the channel. +- The `option_taproot` channel type was defined before this spec and limited + peers that negotiated the channel type to open unannounced channels only. + This document defines how peers can go about announcing these channels, and so + this restriction can be lifted. ### `channel_ready` Extensions -These extensions only apply if the `option_taproot` channel type was set in the -`open_channel` message along with the `announce_channel` channel flag. +The following extensions are defined for the `channel_ready` message: 1. `tlv_stream`: `channel_ready_tlvs` 2. types: @@ -314,13 +327,19 @@ These extensions only apply if the `option_taproot` channel type was set in the 4. data: * [`66*byte`: `public_nonce`] -#### Requirements +#### Requirements: + +The following requirements apply if the `announce_channel` bit was set in the +`channel_flags` field of the `open_channel` message. Nodes advertising the +`option_gossip_announce_private` bit, may also choose to send the +`channel_ready` message at any point during the channel's lifetime in which +case, the following requirements also apply even if the `announce_channel` bit +was not set in `open_channel`. The sender: -- MAY send `channel_ready` message without the `announcement_node_pubnonce` and - `announcement_bitcoin_pubnonce` fields. -- Once the channel is ready to be announced, the node: +- If the negotiated channel type is `option_taproot` and `option_gossip_v2` was + negotiated, then when the node is ready to advertise the channel: - SHOULD send `channel_ready` with the `announcement_node_pubnonce` and `announcement_bitcoin_pubnonce` fields set. The `announcement_node_pubnonce` must be set to the public nonce to be used for signing with the node's @@ -329,13 +348,34 @@ The sender: - Upon reconnection, if a fully signed `channel_announcement_2` has not yet been constructed: - SHOULD re-send `channel_ready` with the nonce fields set. -- Once a `channel_ready` message with announcement nonces has been both sent and - received: - - MUST proceed with constructing and sending the `announcement_signatures_2` - message. - -- TODO: recommend nonce generation technique. -- TODO: can we guarantee progress here? + - Once a `channel_ready` message with the nonce fields has been both sent + and received: + - MUST proceed with constructing and sending the + `announcement_signatures_2` message. +- If the negotiated channel type is not `option_taproot` (ie, it is a P2WSH + channel) and the `option_gossip_v2_p2wsh` bit was negotiated, then when the + node is ready to advertise the channel: + - MAY send `channel_ready` either with or without the nonce fields set. + - If the nonce fields are set, then the node MUST proceed with + constructing and sending the `announcement_signatures_2` message + in preparation for advertising the channel using the V2 protocol. + - Upon reconnection, if a fully signed `channel_announcement_2` has not + yet been constructed: + - SHOULD re-send `channel_ready` with the nonce fields set. + - Once a `channel_ready` message with the nonce fields has been both sent + and received: + - MUST proceed with constructing and sending the + `announcement_signatures_2` message. + - If they are not set, then node may proceed with constructing and + sending the `announcement_signatures` message in preparation for + advertising the channel using the V1 protocol. + - Nodes may initiate the signing flow for both the V1 and V2 protocol + and so should be able to handle receiving both the + `announcement_signatures` and `announcement_signatures_2` messages. +- For any channel type, if the channel peers have negotiated the + `option_gossip_announce_private` bit, then the node may send `channel_ready` + at any point during the channel's lifetime to exchange nonces to use + for the construction of the `announcement_signatures_2` message. The recipient: @@ -361,23 +401,53 @@ It cannot be a requirement that a node include the nonce fields in the preferred channel alias, and it does not make sense to require that the nonce fields be populated once the channel has already been announced. +### `announcement_signatures` Extra requirements + +If peers have negotiated the `option_gossip_announce_private` bit, then the +`announcement_signatures` message can be used to initiate the signing flow for +a previously unannounced channel via the `channel_announcement` message at +any point during the channel's lifecycle. All existing requirements of the +message remain. + ### The `announcement_signatures_2` Message Like the legacy `announcement_signatures` message, this is a direct message between the two endpoints of a channel and serves as an opt-in mechanism to -allow the announcement of the channel to the rest of the network. +allow the announcement of the channel to the rest of the network. This message +is used to exchange the partial signatures required to construct the final +signature for the `channel_announcement_2` message. + +This message can be sent in two cases: + +1) At the start of the channel's lifetime if the `announce_channel` bit was set + in the `channel_flags` field of the `open_channel` message. +2) At any other point in the channel's lifetime if the + `option_gossip_announce_private` bit was negotiated between the channel peers. 1. type: 260 (`announcement_signatures_2`) 2. data: - * [`channel_id`:`channel_id`] - * [`short_channel_id`:`short_channel_id`] - * [`partial_signature`:`partial_signature`] + * [`announcement_signatures_2_tlvs`:`tlvs`] -#### Requirements +1. `tlv_stream`: `announcement_signatures_2_tlvs` +2. types: + 1. type: 0 (`channel_id`) + 2. data: + * [`channel_id`:`channel_id`] + 1. type: 2 (`short_channel_id`) + 2. data: + * [`short_channel_id`:`short_channel_id`] + 1. type: 4 (`partial_signature`) + * [`partial_signature`:`partial_signature`] + + +#### Requirements: The requirements are similar to the ones defined for the legacy -`announcement_signatures`. The below requirements assume that the -`option_taproot` channel type was set in `open_channel`. +`announcement_signatures` in that it should only be sent once a channel +has reached a sufficient number of confirmations meaning that nodes are able +to construct a valid `channel_announcement_2` for the channel. +This may be used for P2WSH channels IF the `option_gossip_v2_p2wsh` bit was +negotiated. A node: - if the `open_channel` message has the `announce_channel` bit set AND a @@ -391,6 +461,9 @@ A node: `MsgHash("channel_announcement", "signature", m)` where `m` is the serialisation of the `channel_announcement_2` message tlv stream (see the [`MsgHash`](#signature-message-construction) definition). +- otherwise if the `option_gossip_announce_private` bit has been negotiated: + - MAY send the `announcement_signatures_2` message at any point during the + channel's lifetime with the same constraints as defined above. - otherwise: - MUST NOT send the `announcement_signatures_2` message. - upon reconnection (once the above timing requirements have been met): @@ -428,19 +501,12 @@ aggregation of the two signatures that the sender would have created (one for ### The `channel_announcement_2` Message -This gossip message contains ownership information regarding a taproot channel. -It ties each on-chain Bitcoin key that makes up the taproot output key to the -associated Lightning node key, and vice-versa. The channel is not practically -usable until at least one side has announced its fee levels and expiry, using -`channel_update_2`. - -See [Taproot Channel Proof and Verification](#taproot-channel-proof-and-verification) -for more information regarding the requirements for proving the existence of a -channel. +This gossip message contains ownership information regarding either a P2TR or +P2WSH channel. The channel is not practically usable until at least one side has +announced its fee levels and expiry, using `channel_update_2`. 1. type: 267 (`channel_announcement_2`) 2. data: - * [`bip340sig`:`signature`] * [`channel_announcement_2_tlvs`:`tlvs`] 1. `tlv_stream`: `channel_announcement_2_tlvs` @@ -472,29 +538,131 @@ channel. 1. type: 16 (`merkle_root_hash`) 2. data: * [`32*byte`:`hash`] + 1. type: 18 (`outpoint`) + 2. data: + * [`sha256`:`txid`] + * [`u16`:`index`] + 1. type: 160 (`signature`) + 2. data: + * [`bip340sig`:`sig`] #### Message Field Descriptions -TODO +- The `chain_hash` is used to identify the blockchain containing the channel + being referred to. +- `short_channel_id`: the short channel ID that can be used to uniquely identify + the channel on-chain. +- `outpoint`: the funding transactions outpoint. A node may use this along with + a bitcoin backend's `txindex` to look up the funding transaction. +- `capacity_satoshis`: the capacity of the channel in satoshis. This must be + less than or equal to the value of the output identified by the `outpoint` + and `short_channel_id` fields. +- `node_id_1` and `node_id_2`: the public keys of the two nodes involved in the + channel. +- `bitcoin_key_1` and `bitcoin_key_2`: optional public keys used to derive the + funding transaction's output. +- `merkle_root_hash`: an optional hash to use as the merkle root hash when + deriving the tweak to apply to the internal key in the case of a P2TR channel. +- `signature`: a BIP 340 signature over the serialisation of the fields in the + message's signed range. The public key that the signature should be verified + against depends on the channel type along with which other fields in the + message have been set. + +#### Requirements: -#### Requirements +The sender: +- If the chain that channel was opened with differs from the Bitcoin mainnet + blockchain, then the `chain_hash` MUST be set to the 32-byte hash that + uniquely identifies the chain. Otherwise, the field should not be set. +- MUST set `short_channel_id` to refer to the confirmed funding transaction, + as specified in [BOLT #2](02-peer-protocol.md#the-channel_ready-message). +- MUST set `outpoint` to the refer to funding transaction. This MUST refer to + the same output as the `short_channel_id` field. +- MUST set `capacity_satoshis` to the capacity of the channel in satoshis. This + must be less than or equal to the value of the output identified by the + `outpoint` and `short_channel_id` fields. +- 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 two compressed keys sorted in ascending lexicographic order. +- If the channel being announced is a P2WSH type, then the `bitcoin_key_1` and + `bitcoin_key_2` fields MUST be set and the `merkle_root_hash` field MUST NOT + be set. See [Partial Signature Calculation](#partial-signature-calculation) + for details on how to compute the `signature` field in this scenario. +- If the channel being announced is a P2TR type, then the `bitcoin_key_1`, + `bitcoin_key_2` and `merkle_root_hash` fields are optional and the `signature` + construction depends on how these fields are set and how `P_agg` has been + derived. See [Partial Signature Calculation](#partial-signature-calculation) + for details on how to compute the `signature` field in this scenario. +- The `signature` will always be over the serialised signed-range fields of the + message. + +The receiver: + +- MUST verify the integrity AND authenticity of the `channel_announcement_2` + message by verifying the signature. This verification will depend on the + channel type along with which fields have been set in the message. +- Either the `short_channel_id` or the `outpoint` may be used to retrieve the + channel's funding script. This can then be used to determine if the channel in + question is a P2WSH channel or a P2TR channel. +- If the channel is a P2WSH channel: + - The `bitcoin_key_1` and `bitcoin_key_2` fields MUST be set and the + `merkle_root_hash` field MUST NOT be set. The message should be ignored + otherwise. + - The `signature` field must be valid according to the rules defined in + [Verifying the `channel_announcement_2` signature](#verifying-the-channel_announcement_2-signature). +- otherwise: + - The `bitcoin_key_1`, `bitcoin_key_2` and `merkle_root_hash` fields are + optional. + - The `signature` field must be valid according to the rules defined in + [Verifying the `channel_announcement_2` signature](#verifying-the-channel_announcement_2-signature). +- If the `signature` is invalid: + - SHOULD send a `warning`. + - MAY close the connection. + - MUST ignore the message. +- otherwise: + - if `node_id_1` OR `node_id_2` are blacklisted: + - SHOULD ignore the message. + - otherwise: + - if the transaction referred to was NOT previously announced as a + channel: + - SHOULD queue the message for rebroadcasting. + - MAY choose NOT to for messages longer than the minimum expected + length. + - if it has previously received a valid `channel_announcement_v2`, for + the same transaction, in the same block, but for a different + `node_id_1` or `node_id_2`: + - SHOULD blacklist the previous message's `node_id_1` and `node_id_2`, + as well as this `node_id_1` and `node_id_2` AND forget any channels + connected to them. + - otherwise: + - SHOULD store this `channel_announcement`. + +- once its funding output has been spent OR reorganized out: + - SHOULD forget a channel after a 12-block delay. + +#### TLV Defaults + +The following defaults TLV values apply if the TLV is not present in the +message: + +| `channel_announcement_2` TLV Type | Default Value | Comment | +|------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------------------------------------| +| 0 (`chain_hash`) | `6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000` | The hash of the genesis block of the mainnet Bitcoin blockchain. | -TODO ### The `node_announcement_2` Message -This gossip message, like the legacy `node_announcement` message, allows a node +This gossip message, like the `node_announcement` message, allows a node to indicate extra data associated with it, in addition to its public key. To avoid trivial denial of service attacks, nodes not associated with an already -known channel (legacy or taproot) are ignored. +known channel (advertised via a `channel_announcement_2` message) are ignored. -Unlike the legacy `node_announcement` message, this message makes use of a +Unlike the `node_announcement` message, this message makes use of a BIP340 signature instead of an ECDSA one. This will allow nodes to be backed by multiple keys since MuSig2 can be used to construct the single signature. 1. type: 269 (`node_announcement_2`) 2. data: - * [`bip340sig`:`signature`] * [`node_announcement_2_tlvs`:`tlvs`] 1. `tlv_stream`: `node_announcement_2_tlvs` @@ -526,6 +694,9 @@ by multiple keys since MuSig2 can be used to construct the single signature. 1. type: 11 (`dns_hostnames`) 2. data: * [`...*dns_hostname`: `dns_hostnames`] + 1. type: 160 (`signature`) + 2. data: + * [`bip340sig`:`sig`] The following subtypes are defined: @@ -560,7 +731,7 @@ The following subtypes are defined: - `signature` is the [BIP340][bip-340] signature for the `node_id` key. The message to be signed is `MsgHash("node_announcement_2", "signature", m)` - where `m` is the serialised TLV stream (see the + where `m` is the serialised signed range of the TLV stream (see the [`MsgHash`](#signature-message-construction) definition). - `features` is a bit vector with bits set according to [BOLT #9](09-features.md#assigned-features-flags) - `block_height` allows for ordering or messages in the case of multiple @@ -586,27 +757,21 @@ The following subtypes are defined: #### Requirements -TODO: flesh out when it is ok to send new vs old node announcement. Is it ever -ok to send both? if so - what if the info inside them differs? - The sender: - MUST set TLV fields 0, 2 and 4. - MUST set `signature` to a valid [BIP340][bip-340] signature for the `node_id` key. The message to be signed is `MsgHash("node_announcement_2", "signature", m)` where `m` is the - serialisation of the `node_announcement_2` message excluding the - `signature` field (see the - [`MsgHash`](#signature-message-construction) definition). + serialisation of the signed TLV range of the `node_announcement_2` message + (see the [`MsgHash`](#signature-message-construction) definition). - MAY set `color` and `alias` to customise appearance in maps and graphs. - If the node sets the `alias`: - MUST use 32 utf8 characters or less. - MUST set `block_height` to be greater than that of any previous - `node_announcement_2` it has previously created. -- TODO: how to determine a lower bound for the block_height of the node_ann? - cant say "must be greater than or = oldest advertised channel" since a node - could open a new channel and close the previous which would then invalidate - the node_announcement. + `node_announcement_2` it has previously created. The `blockheight` should + always be greater than or equal to funding block of the oldest channel that + the node has advertised via `channel_announcement_2`. - If the node wishes to announce its willingness to accept incoming network connections: - SHOULD set at least one of types 7-10. @@ -670,29 +835,15 @@ The security considerations for node aliases mentioned in ### The `channel_update_2` Message -- TODO: should updates for legacy channels also sometimes be broadcast using the - new format for easier set reconciliation? - After a channel has been initially announced via `channel_announcement_2`, each side independently announces the fees and minimum expiry delta it requires to relay HTLCs through this channel. Each uses the 8-byte short channel id that -matches the `channel_announcement_2` and the `direction` field to +matches the `channel_announcement_2` and the `second_peer` field to indicate which end of the channel it's on (origin or final). A node can do this multiple times, in order to change fees. -Note that the `channel_update` gossip message is only useful in the context -of *relaying* payments, not *sending* payments. When making a payment -`A` -> `B` -> `C` -> `D`, only the `channel_update`s related to channels -`B` -> `C` (announced by `B`) and `C` -> `D` (announced by `C`) will -come into play. When building the route, amounts and expiries for HTLCs need -to be calculated backward from the destination to the source. The exact initial -value for `amount_msat` and the minimal value for `cltv_expiry`, to be used for -the last HTLC in the route, are provided in the payment request - -(see [BOLT #11][[bolt-11-tagged-fields]]). 1. type: 271 (`channel_update_2`) 2. data: - * [`bip340sig`:`signature`] * [`channel_update_2_tlvs`:`tlvs`] 1. `tlv_stream`: `channel_update_2_tlvs` @@ -725,10 +876,13 @@ the last HTLC in the route, are provided in the payment request 1. type: 18 (`fee_proportional_millionths`) 2. data: * [`u32`:`fee_proportional_millionths`] + 1. type: 160 (`signature`) + 2. data: + * [`bip340sig`:`sig`] The `disable_flags` bitfield is used to indicate that the channel is either -temporarily or permanently disabled. The following table specifies the meaning +temporarily or permanently disabled. The following table specifies the meaning of the individual bits: | Bit Position | Name | Meaning | @@ -740,7 +894,7 @@ of the individual bits: Both the `incoming` and `outgoing` bit can be set to indicate that the channel peer is offline. -If the `permanant` bit is set, then the channel can be considered closed. +If the `permanant` bit is set, then the channel can be considered closed. #### Message Field Descriptions @@ -751,16 +905,15 @@ If the `permanant` bit is set, then the channel can be considered closed. - `block_height` is the timestamp associated with the message. A node may not send two `channel_update` messages with the same `block_height`. The `block_height` must also be greater than or equal to the block height - indicated by the `short_channel_id` used in the `channel_announcement` and - must not be less than current best block height minus 2016 (~2 weeks of - blocks). + indicated by the `short_channel_id` used in the `channel_announcement_2` and + must not be greater than current best block height. - The `disable` bit field can be used to advertise to the network that a channel is disabled and that it should not be used for routing. The individual `disable_flags` bits can be used to communicate more fine-grained information. -- The `second_peer` is used to indicate which node in the channel node pair has +- The `second_peer` is used to indicate which node in the channel node pair has created and signed this message. If present, the node was `node_id_2` in the - `channel_announcment`, otherwise the node is `node_id_1` in the - `channel_announcement` message. + `channel_announcment_2`, otherwise the node is `node_id_1` in the + `channel_announcement_2` message. - `cltv_expiry_delta` is the number of blocks that the node will subtract from an incoming HTLC's `cltv_expiry`. - `htlc_minimum_msat` is the minimum HTLC value (in millisatoshi) that the @@ -798,15 +951,13 @@ The origin node: - SHOULD not include the field in the TLV stream if the default value is desired. - MUST use the `channel_update_2` message to communicate channel parameters of a - Taproot channel. -- MAY use the `channel_update_2` message to communicate channel parameters of a - legacy (P2SH) channel. + any channel advertised via `channel_announcement_2`. - MUST NOT send a created `channel_update_2` before `channel_ready` has been received. -- For an unannounced channel (i.e. one where the `announce_channel` bit was not - set in `open_channel`): - - MAY create a `channel_update_2` to communicate the channel parameters to the - channel peer. +- For an unannounced channel (i.e. one where `announcement_signatures_2` has + not been exchanged): + - MAY create a `channel_update_2` to communicate the channel parameters to + the channel peer. - MUST set the `short_channel_id` to either an `alias` it has received from the peer, or the real channel `short_channel_id`. - MUST NOT forward such a `channel_update_2` to other peers, for privacy @@ -837,23 +988,19 @@ The receiving node: - SHOULD send a `warning` and close the connection. - MUST NOT process the message further. -#### Rationale - -- An even type is used so that best-effort propagation can be used. - ### Query Messages -TODO: - 1. new first block height & block range fields in gossip_timestamp_range - 2. add block-height query option (like timestamps query option) +TODO: +1. new first block height & block range fields in gossip_timestamp_range +2. add block-height query option (like timestamps query option) # Appendix A: Algorithms ## Partial Signature Calculation When both nodes have exchanged a `channel_ready` message containing the -`announcement_node_pubnonce` and `announcement_bitcoin` fields then they will -each have the following information: +`announcement_node_pubnonce` and `announcement_bitcoin_pubnonce` fields then +they will each have the following information: - `node_1` will know: - `bitcoin_priv_key_1`, `node_ID_priv_key_1`, @@ -886,12 +1033,11 @@ P_agg = Musig2.KeyAgg(Musig2.KeySort(node_ID_1, node_ID_2, bitcoin_key_1, bitcoi Next, the aggregate public nonce, `aggnonce`, can be calculated: ``` -aggnonce = Musig2.NonceAgg(announcement_node_secnonce_1, announcement_bitcoin_pubnonce_1, announcement_node_secnonce_2, announcement_bitcoin_pubnonce_2) +aggnonce = Musig2.NonceAgg(announcement_node_pubnonce_1, announcement_bitcoin_pubnonce_1, announcement_node_pubnonce_2, announcement_bitcoin_pubnonce_2) ``` -The message, `msg` that the peers will sign is the serialisation of -`channel_announcement_2` _without_ the `signature` field (i.e. without -type 0) +The message, `msg` that the peers will sign is the serialisation of all the +TLV fields in the signed ranges of the `channel_announcement_2` message. With all the information mentioned, both peers can now construct the [`Session Context`][musig-session-ctx] defined by the MuSig2 protocol which is @@ -988,23 +1134,24 @@ found in the [MuSig2][musig-session-ctx] spec. ## Verifying the `channel_announcement_2` signature For all the following cases, it should be verified that the output at the -provided `short_channel_id` is an unspent Taproot output. +provided `short_channel_id` or `outpoint` is an unspent P2WSH or P2TR output. ### The 3-of-3 MuSig2 Scenario -In the case where a received `channel_announcement_2` message is received which -does not have the optional `bitcoin_key_*` fields, the signature of the message -should be verified as a 3-of-3 MuSig2 signature. The keys involved are: -`node_id_1`, `node_id_2` and the taproot output key (`tr_output_key`) found in -the channel's funding output specified by the provided `short_channel_id`. +In the case where the funding transaction is a P2TR output and the received +`channel_announcement_2` message is does not have the optional `bitcoin_key_*` +fields, the signature of the message should be verified as a 3-of-3 MuSig2 +signature. The keys involved are: `node_id_1`, `node_id_2` and the taproot +output key (`tr_output_key`) found in the channel's funding output specified by +the provided `short_channel_id`. The full list of inputs required: - `node_id_1` - `node_id_2` - `tr_output_key` - `msg`: the serialised `channel_announcement_2` tlv stream. -- `sig`: the 64-byte BIP340 signature found in the `signature` field of the - `channel_announcement_2` message. This signature must be parsed into `R` and +- `sig`: the 64-byte BIP340 signature found in the `signature` field of the + `channel_announcement_2` message. This signature must be parsed into `R` and `s` values as defined in BIP327. The aggregate key can be calculated as follows: @@ -1021,11 +1168,29 @@ The signature can then be verified as follows: ### The 4-of-4 MuSig2 Scenario -In the case where a received `channel_announcement_2` message is received which -does have both the optional `bitcoin_key_*` fields, the signature of the message -should be verified as a 4-of-4 MuSig2 signature. The keys involved are: -`node_id_1`, `node_id_2`, `bitcoin_key_1` and `bitcoin_key_2`. The message may -also optionally contain the `merkle_root_hash` field in this case. +There are two possibilities here: the channel is a P2WSH channel or a P2TR +channel. + +#### P2WSH Channels + +In the case where the funding transaction is a P2WSH output, then the received +`channel_announcement_2` message MUST have both the optional `bitcoin_key_*` +fields and the `merkle_root_hash` should not be set. The verifier must then +ensure that the funding output matches the following P2WSH script: + + `2 2 OP_CHECKMULTISIG` + +After this has been verified, the signature of the message should be verified. +This is the same for P2TR channels and is described below. + +#### P2TR Channels + +In the case where the funding transaction is a P2TR output and the received +`channel_announcement_2` message has both the optional `bitcoin_key_*` fields, +the signature of the message should be verified as a 4-of-4 MuSig2 signature. +The keys involved are: `node_id_1`, `node_id_2`, `bitcoin_key_1` and +`bitcoin_key_2`. The message may also optionally contain the +`merkle_root_hash` field in this case. Before the actual signature verification is done, it should first be asserted that the taproot output key found in the funding output is in-fact made up of @@ -1049,17 +1214,20 @@ P_internal = KeyAgg(MuSig2.KeySort(`bitcoin_key_1`, `bitcoin_key_2`)) - Fail if `P_o != P_internal + t*G` If the above check is successful, then it has been shown that the output key -is constructed from the two provided bitcoin keys. So now the signature -verification can be done. +is constructed from the two provided bitcoin keys. + +#### Signature Verification + +For both the above cases, the following signature verification applies: The full list of inputs required: - `node_id_1` - `node_id_2` - `bitcoin_key_1` - `bitcoin_key_2` -- `msg`: the serialised `channel_announcement_2` tlv stream. -- `sig`: the 64-byte BIP340 signature found in the `signature` field of the - `channel_announcement_2` message. This signature must be parsed into `R` and +- `msg`: the serialised signed range of the `channel_announcement_2` message. +- `sig`: the 64-byte BIP340 signature found in the `signature` field of the + `channel_announcement_2` message. This signature must be parsed into `R` and `s` values as defined in BIP327. The aggregate key can be calculated as follows: @@ -1108,6 +1276,7 @@ ideas mentioned in the following references: taproot channel verification should work. [bolt-7]: ./07-routing-gossip.md +[bolt-3]: ./03-transactions.md [bolt-7-alias-security]: ./07-routing-gossip.md#security-considerations-for-node-aliases [bolt-9-features]: ./09-features.md#bolt-9-assigned-feature-flags [bolt-11]: ./11-payment-encoding.md