diff --git a/.aspell.en.pws b/.aspell.en.pws index f1a1d35e1..c527a657d 100644 --- a/.aspell.en.pws +++ b/.aspell.en.pws @@ -391,3 +391,5 @@ griefing unspendable pkh kB +unblind +unblinded \ No newline at end of file diff --git a/02-peer-protocol.md b/02-peer-protocol.md index 8a5751c01..f43c68611 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -990,6 +990,12 @@ is destined, is described in [BOLT #4](04-onion-routing.md). * [`u32`:`cltv_expiry`] * [`1366*byte`:`onion_routing_packet`] +1. `tlv_stream`: `update_add_htlc_tlvs` +2. types: + 1. type: 0 (`blinding_point`) + 2. data: + * [`point`:`blinding`] + #### Requirements A sending node: @@ -1025,6 +1031,8 @@ A sending node: - for the first HTLC it offers: - MUST set `id` to 0. - MUST increase the value of `id` by 1 for each successive offer. + - if it is relaying a payment inside a blinded route: + - MUST set `blinding_point` (see [Route Blinding](04-onion-routing.md#route-blinding)) `id` MUST NOT be reset to 0 after the update is complete (i.e. after `revoke_and_ack` has been received). It MUST continue incrementing instead. @@ -1049,6 +1057,8 @@ A receiving node: - if other `id` violations occur: - MAY send a `warning` and close the connection, or send an `error` and fail the channel. + - if `blinding_point` is provided: + - MUST use the corresponding blinded private key to decrypt the `onion_routing_packet` (see [Route Blinding](04-onion-routing.md#route-blinding)) The `onion_routing_packet` contains an obfuscated list of hops and instructions for each hop along the path. It commits to the HTLC by setting the `payment_hash` as associated data, i.e. includes the `payment_hash` in the computation of HMACs. @@ -1131,6 +1141,17 @@ A node: commitment transactions: - MUST NOT send an `update_fulfill_htlc`, `update_fail_htlc`, or `update_fail_malformed_htlc`. + - When failing an incoming HTLC: + - If `current_blinding_point` is set in the onion payload and it is not the + final node: + - MUST send an `update_fail_htlc` error using the + `invalid_onion_blinding` failure code with the `sha256_of_onion` + of the onion it received, for any local or downstream errors. + - SHOULD add a random delay before sending `update_fail_htlc`. + - If `blinding_point` is set in the incoming `update_add_htlc`: + - MUST send an `update_fail_malformed_htlc` error using the + `invalid_onion_blinding` failure code with the `sha256_of_onion` + of the onion it received, for any local or downstream errors. A receiving node: - if the `id` does not correspond to an HTLC in its current commitment transaction: @@ -1170,6 +1191,9 @@ errors. However, without re-checking the actual encrypted packet sent, it won't know whether the error was its own or the remote's; so such detection is left as an option. +Nodes inside a blinded route must use `invalid_onion_blinding` to avoid +leaking information to senders trying to probe the blinded route. + ### Committing Updates So Far: `commitment_signed` When a node has changes for the remote commitment, it can apply them, diff --git a/04-onion-routing.md b/04-onion-routing.md index b2242e052..ed8cf2f3e 100644 --- a/04-onion-routing.md +++ b/04-onion-routing.md @@ -50,6 +50,7 @@ A node: * [Packet Structure](#packet-structure) * [Payload Format](#payload-format) * [Basic Multi-Part Payments](#basic-multi-part-payments) + * [Route Blinding](#route-blinding) * [Accepting and Forwarding a Payment](#accepting-and-forwarding-a-payment) * [Payload for the Last Node](#payload-for-the-last-node) * [Non-strict Forwarding](#non-strict-forwarding) @@ -198,9 +199,18 @@ This is formatted according to the Type-Length-Value format defined in [BOLT #1] 2. data: * [`32*byte`:`payment_secret`] * [`tu64`:`total_msat`] + 1. type: 10 (`encrypted_recipient_data`) + 2. data: + * [`...*byte`:`encrypted_data`] + 1. type: 12 (`current_blinding_point`) + 2. data: + * [`point`:`blinding`] 1. type: 16 (`payment_metadata`) 2. data: * [`...*byte`:`payment_metadata`] + 1. type: 18 (`total_amount_msat`) + 2. data: + * [`tu64`:`total_msat`] `short_channel_id` is the ID of the outgoing channel used to route the message; the receiving peer should operate the other end of this channel. @@ -229,39 +239,97 @@ leaking its position in the route. ### Requirements -The writer: - - For every node: +The creator of `encrypted_recipient_data` (usually, the recipient of payment): + + - MUST create `encrypted_data_tlv` for each node in the blinded route (including itself). + - MUST include `encrypted_data_tlv.short_channel_id` and `encrypted_data_tlv.payment_relay` for each non-final node. + - MUST set `encrypted_data_tlv.payment_constraints` for each non-final node: + - `max_cltv_expiry` to the largest block height at which the route is allowed to be used, starting + from the final node and adding `encrypted_data_tlv.payment_relay.cltv_expiry_delta` at each hop. + - `htlc_minimum_msat` to the largest minimum HTLC value the nodes will allow. + - If it sets `encrypted_data_tlv.allowed_features`: + - MUST set it to an empty array. + - MUST compute the total fees and cltv delta of the route as follows and communicate them to the sender: + - `total_fee_base_msat(n+1) = (fee_base_msat(n+1) * 1000000 + total_fee_base_msat(n) * (1000000 + fee_proportional_millionths(n+1)) + 1000000 - 1) / 1000000` + - `total_fee_proportional_millionths(n+1) = ((total_fee_proportional_millionths(n) + fee_proportional_millionths(n+1)) * 1000000 + total_fee_proportional_millionths(n) * fee_proportional_millionths(n+1) + 1000000 - 1) / 1000000` + - MUST create the `encrypted_recipient_data` from the `encrypted_data_tlv` as required in [Route Blinding](#route-blinding). + +The writer of `tlv_payload`: + + - For every node inside a blinded route: + - MUST include the `encrypted_recipient_data` provided by the recipient + - For the first node in the blinded route: + - MUST include the `blinding_point` provided by the recipient in `current_blinding_point` + - If it is the final node: + - MUST include `amt_to_forward`, `outgoing_cltv_value` and `total_amount_msat`. + - MUST NOT include any other tlv field. + - For every node outside of a blinded route: - MUST include `amt_to_forward` and `outgoing_cltv_value`. - - For every non-final node: - - MUST include `short_channel_id` - - MUST NOT include `payment_data` - - For the final node: - - MUST NOT include `short_channel_id` - - if the recipient provided `payment_secret`: - - MUST include `payment_data` - - MUST set `payment_secret` to the one provided - - MUST set `total_msat` to the total amount it will send - - if the recipient provided `payment_metadata`: - - MUST include `payment_metadata` with every HTLC - - MUST not apply any limits to the size of payment_metadata except the limits implied by the fixed onion size + - For every non-final node: + - MUST include `short_channel_id` + - MUST NOT include `payment_data` + - For the final node: + - MUST NOT include `short_channel_id` + - if the recipient provided `payment_secret`: + - MUST include `payment_data` + - MUST set `payment_secret` to the one provided + - MUST set `total_msat` to the total amount it will send + - if the recipient provided `payment_metadata`: + - MUST include `payment_metadata` with every HTLC + - MUST not apply any limits to the size of `payment_metadata` except the limits implied by the fixed onion size The reader: - - MUST return an error if `amt_to_forward` or `outgoing_cltv_value` are not present. - - if it is not the final node: + + - If `encrypted_recipient_data` is present: + - If `blinding_point` is set in the incoming `update_add_htlc`: + - MUST return an error if `current_blinding_point` is present. + - MUST use that `blinding_point` as the blinding point for decryption. + - Otherwise: + - MUST return an error if `current_blinding_point` is not present. + - MUST use that `current_blinding_point` as the blinding point for decryption. + - SHOULD add a random delay before returning errors. + - MUST return an error if `encrypted_recipient_data` does not decrypt using the + blinding point as described in [Route Blinding](#route-blinding). + - If `payment_constraints` is present: + - MUST return an error if: + - the expiry is greater than `encrypted_recipient_data.payment_constraints.max_cltv_expiry`. + - the amount is below `encrypted_recipient_data.payment_constraints.htlc_minimum_msat`. + - If `allowed_features` is missing: + - MUST process the message as if it were present and contained an empty array. - MUST return an error if: - - `short_channel_id` is not present, - - it cannot forward the HTLC to the peer indicated by the channel `short_channel_id`. - - incoming `amount_msat` - `fee` < `amt_to_forward` (where `fee` is the advertised fee as described in [BOLT #7](07-routing-gossip.md#htlc-fees)) - - `cltv_expiry` - `cltv_expiry_delta` < `outgoing_cltv_value` - - if it is the final node: - - MUST treat `total_msat` as if it were equal to `amt_to_forward` if it - is not present. + - `encrypted_recipient_data.allowed_features.features` contains an unknown feature bit (even if it is odd). + - the payment uses a feature not included in `encrypted_recipient_data.allowed_features.features`. + - If it is not the final node: + - MUST return an error if the payload contains other tlv fields than `encrypted_recipient_data` and `current_blinding_point`. + - MUST return an error if `encrypted_recipient_data` does not contain either `short_channel_id` or `next_node_id`. + - MUST return an error if `encrypted_recipient_data` does not contain `payment_relay`. + - MUST use values from `encrypted_recipient_data.payment_relay` to calculate `amt_to_forward` and `outgoing_cltv_value` as follows: + - `amt_to_forward = ((amount_msat - fee_base_msat) * 1000000 + 1000000 + fee_proportional_millionths - 1) / (1000000 + fee_proportional_millionths)` + - `outgoing_cltv_value = cltv_expiry - payment_relay.cltv_expiry_delta` + - If it is the final node: + - MUST return an error if the payload contains other tlv fields than `encrypted_recipient_data`, `current_blinding_point`, `amt_to_forward`, `outgoing_cltv_value` and `total_amount_msat`. + - MUST return an error if `amt_to_forward`, `outgoing_cltv_value` or `total_amount_msat` are not present. + - MUST return an error if `amt_to_forward` is below what it expects for the payment. + - MUST return an error if incoming `cltv_expiry` < `outgoing_cltv_value`. + - MUST return an error if incoming `cltv_expiry` < `current_block_height` + `min_final_cltv_expiry_delta`. + - Otherwise (it is not part of a blinded route): + - MUST return an error if `blinding_point` is set in the incoming `update_add_htlc` or `current_blinding_point` is present. + - MUST return an error if `amt_to_forward` or `outgoing_cltv_value` are not present. + - if it is not the final node: + - MUST return an error if: + - `short_channel_id` is not present, + - it cannot forward the HTLC to the peer indicated by the channel `short_channel_id`. + - incoming `amount_msat` - `fee` < `amt_to_forward` (where `fee` is the advertised fee as described in [BOLT #7](07-routing-gossip.md#htlc-fees)) + - `cltv_expiry` - `cltv_expiry_delta` < `outgoing_cltv_value` + - If it is the final node: + - MUST treat `total_msat` as if it were equal to `amt_to_forward` if it is not present. - MUST return an error if: - incoming `amount_msat` < `amt_to_forward`. - incoming `cltv_expiry` < `outgoing_cltv_value`. - incoming `cltv_expiry` < `current_block_height` + `min_final_cltv_expiry_delta`. -Additional requirements are specified [below](#basic-multi-part-payments). +Additional requirements are specified [here](#basic-multi-part-payments) for +multi-part payments, and [here](#route-blinding) for blinded payments. ### Basic Multi-Part Payments @@ -275,6 +343,10 @@ ultimate sender that the rest of the payment will follow in succeeding HTLCs; we call these outstanding HTLCs which have the same preimage, an "HTLC set". +Note that there are two distinct tlv fields that can be used to transmit +`total_msat`. The last one, `total_amount_msat`, was introduced with +blinded paths for which the `payment_secret` doesn't make sense. + `payment_metadata` is to be included in every payment part, so that invalid payment details can be detected as early as possible. @@ -352,6 +424,170 @@ otherwise meets the amount criterion (eg. some other failure, or invoice timeout), however if it were to fulfill only some of them, intermediary nodes could simply claim the remaining ones. +### Route Blinding + +Nodes receiving onion packets may hide their identity from senders by +"blinding" an arbitrary amount of hops at the end of an onion path. + +When using route blinding, nodes find a route to themselves from a given +"introduction node" and initial "blinding point". They then use ECDH with +each node in that route to create a "blinded" node ID and an encrypted blob +(`encrypted_data`) for each one of the blinded nodes. + +They communicate this blinded route and the encrypted blobs to the sender. +The sender finds a route to the introduction node and extends it with the +blinded route provided by the recipient. The sender includes the encrypted +blobs in the corresponding onion payloads: they allow nodes in the blinded +part of the route to "unblind" the next node and correctly forward the packet. + +Note that there are two ways for the sender to reach the introduction +point: one is to create a normal (unblinded) payment, and place the +initial blinding point in `current_blinding_point` along with the +`encrypted_data` in the onion payload for the introduction point to +start the blinded path. The second way is to create a blinded path to +the introduction point, set `next_blinding_override` inside the +`encrypted_data_tlv` on the hop prior to the introduction point to the +initial blinding point, and have it sent to the introduction node. + +The `encrypted_data` is a TLV stream, encrypted for a given blinded node, that +may contain the following TLV fields: + +1. `tlv_stream`: `encrypted_data_tlv` +2. types: + 1. type: 1 (`padding`) + 2. data: + * [`...*byte`:`padding`] + 1. type: 2 (`short_channel_id`) + 2. data: + * [`short_channel_id`:`short_channel_id`] + 1. type: 4 (`next_node_id`) + 2. data: + * [`point`:`node_id`] + 1. type: 6 (`path_id`) + 2. data: + * [`...*byte`:`data`] + 1. type: 8 (`next_blinding_override`) + 2. data: + * [`point`:`blinding`] + 1. type: 10 (`payment_relay`) + 2. data: + * [`u16`:`cltv_expiry_delta`] + * [`u32`:`fee_proportional_millionths`] + * [`tu32`:`fee_base_msat`] + 1. type: 12 (`payment_constraints`) + 2. data: + * [`u32`:`max_cltv_expiry`] + * [`tu64`:`htlc_minimum_msat`] + 1. type: 14 (`allowed_features`) + 2. data: + * [`...*byte`:`features`] + +#### Requirements + +A recipient N(r) creating a blinded route `N(0) -> N(1) -> ... -> N(r)` to itself: + +- MUST create a blinded node ID `B(i)` for each node using the following algorithm: + - `e(0) <- {0;1}^256` + - `E(0) = e(0) * G` + - For every node in the route: + - let `N(i) = k(i) * G` be the `node_id` (`k(i)` is `N(i)`'s private key) + - `ss(i) = SHA256(e(i) * N(i)) = SHA256(k(i) * E(i))` (ECDH shared secret known only by `N(r)` and `N(i)`) + - `B(i) = HMAC256("blinded_node_id", ss(i)) * N(i)` (blinded `node_id` for `N(i)`, private key known only by `N(i)`) + - `rho(i) = HMAC256("rho", ss(i))` (key used to encrypt the payload for `N(i)` by `N(r)`) + - `e(i+1) = SHA256(E(i) || ss(i)) * e(i)` (blinding ephemeral private key, only known by `N(r)`) + - `E(i+1) = SHA256(E(i) || ss(i)) * E(i)` (NB: `N(i)` MUST NOT learn `e(i)`) +- MAY replace `E(i+1)` with a different value, but if it does: + - MUST set `encrypted_data_tlv(i).next_blinding_override` to `E(i+1)` +- MAY store private data in `encrypted_data_tlv(r).path_id` to verify that the route is used in the right context and was created by them +- SHOULD add padding data to ensure all `encrypted_data_tlv(i)` have the same length +- MUST encrypt each `encrypted_data_tlv(i)` with ChaCha20-Poly1305 using the corresponding `rho(i)` key and an all-zero nonce to produce `encrypted_recipient_data(i)` +- MUST communicate the blinded node IDs `B(i)` and `encrypted_recipient_data(i)` to the sender +- MUST communicate the real node ID of the introduction point `N(0)` to the sender +- MUST communicate the first blinding ephemeral key `E(0)` to the sender + +A reader: + +- If it receives `blinding_point` (`E(i)`) from the prior peer: + - MUST use `b(i)` instead of its private key `k(i)` to decrypt the onion. + Note that the node may instead tweak the onion ephemeral key with + `HMAC256("blinded_node_id", ss(i))` which achieves the same result. +- Otherwise: + - MUST use `k(i)` to decrypt the onion, to extract `current_blinding_point` (`E(i)`). +- MUST compute: + - `ss(i) = SHA256(k(i) * E(i))` (standard ECDH) + - `b(i) = HMAC256("blinded_node_id", ss(i)) * k(i)` + - `rho(i) = HMAC256("rho", ss(i))` + - `E(i+1) = SHA256(E(i) || ss(i)) * E(i)` +- MUST decrypt the `encrypted_data` field using `rho(i)` and use the + decrypted fields to locate the next node +- If the `encrypted_data` field is missing or cannot be decrypted: + - MUST return an error +- If `encrypted_data` contains a `next_blinding_override`: + - MUST use it as the next blinding point instead of `E(i+1)` +- Otherwise: + - MUST use `E(i+1)` as the next blinding point +- MUST forward the onion and include the next blinding point in the lightning + message for the next node + +The final recipient: + +- MUST compute: + - `ss(r) = SHA256(k(r) * E(r))` (standard ECDH) + - `b(r) = HMAC256("blinded_node_id", ss(r)) * k(r)` + - `rho(r) = HMAC256("rho", ss(r))` +- MUST decrypt the `encrypted_data` field using `rho(r)` +- If the `encrypted_data` field is missing or cannot be decrypted: + - MUST return an error +- MUST ignore the message if the `path_id` does not match the blinded route it + created + +#### Rationale + +Route blinding is a lightweight technique to provide recipient anonymity. +It's more flexible than rendezvous routing because it simply replaces the public +keys of the nodes in the route with random public keys while letting senders +choose what data they put in the onion for each hop. Blinded routes are also +reusable in some cases (e.g. onion messages). + +Each node in the blinded route needs to receive `E(i)` to be able to decrypt +the onion and the `encrypted_data` payload. Protocols that use route blinding +must specify how this value is propagated between nodes. + +When concatenating two blinded routes generated by different nodes, the +last node of the first route needs to know the first `blinding_point` of the +second route: the `next_blinding_override` field must be used to transmit this +information. + +The final recipient must verify that the blinded route is used in the right +context (e.g. for a specific payment) and was created by them. Otherwise a +malicious sender could create different blinded routes to all the nodes that +they suspect could be the real recipient and try them until one accepts the +message. The recipient can protect against that by storing `E(r)` and the +context (e.g. a `payment_hash`), and verifying that they match when receiving +the onion. Otherwise, to avoid additional storage cost, it can put some private +context information in the `path_id` field (e.g. the `payment_preimage`) and +verify that when receiving the onion. Note that it's important to use private +information in that case, that senders cannot have access to. + +Whenever the introduction point receives a failure from the blinded route, it +should add a random delay before forwarding the error. Failures are likely to +be probing attempts and message timing may help the attacker infer its distance +to the final recipient. + +The `padding` field can be used to ensure that all `encrypted_data` have the +same length. It's particularly useful when adding dummy hops at the end of a +blinded route, to prevent the sender from figuring out which node is the final +recipient. + +When route blinding is used for payments, the recipient specifies the fees and +expiry that blinded nodes should apply to the payment instead of letting the +sender configure them. The recipient also adds additional constraints to the +payments that can go through that route to protect against probing attacks that +would let malicious nodes unblind the identity of the blinded nodes. It should +set `payment_constraints.max_cltv_expiry` to restrict the lifetime of a blinded +route and reduce the risk that an intermediate node updates its fees and rejects +payments (which could be used to unblind nodes inside the route). + # Accepting and Forwarding a Payment Once a node has decoded the payload it either accepts the payment locally, or forwards it to the peer indicated as the next hop in the payload. @@ -796,6 +1032,12 @@ The association between the forward and return packets is handled outside of this onion routing protocol, e.g. via association with an HTLC in a payment channel. +Error handling for HTLCs with `blinding_point` is particularly fraught, +since differences in implementations (or versions) may be leveraged to +de-anonymize elements of the blinded path. Thus the decision turn every +error into `invalid_onion_blinding` which will be converted to a normal +onion error by the introduction point. + ### Requirements The _erring node_: @@ -1007,15 +1249,27 @@ the decrypted byte stream. The complete amount of the multi-part payment was not received within a reasonable time. +1. type: BADONION|PERM|24 (`invalid_onion_blinding`) +2. data: + * [`sha256`:`sha256_of_onion`] + +An error occurred within the blinded path. + ### Requirements An _erring node_: - - MUST select one of the above error codes when creating an error message. - - MUST include the appropriate data for that particular error type. - - if there is more than one error: - - SHOULD select the first error it encounters from the list above. + - if `blinding_point` is set in the incoming `update_add_htlc`: + - MUST return an `invalid_onion_blinding` error. + - if `current_blinding_point` is set in the onion payload and it is not the + final node: + - MUST return an `invalid_onion_blinding` error. + - otherwise: + - MUST select one of the above error codes when creating an error message. + - MUST include the appropriate data for that particular error type. + - if there is more than one error: + - SHOULD select the first error it encounters from the list above. -Any _erring node_ MAY: +An _erring node_ MAY: - if the `realm` byte is unknown: - return an `invalid_realm` error. - if the per-hop payload in the onion is invalid (e.g. it is not a valid tlv stream) @@ -1029,6 +1283,15 @@ Any _erring node_ MAY: which were NOT included in the onion: - return a `required_node_feature_missing` error. +A _forwarding node_ MUST: + - if `blinding_point` is set in the incoming `update_add_htlc`: + - return an `invalid_onion_blinding` error. + - if `current_blinding_point` is set in the onion payload and it is not the + final node: + - return an `invalid_onion_blinding` error. + - otherwise: + - select one of the above error codes when creating an error message. + A _forwarding node_ MAY, but a _final node_ MUST NOT: - if the onion `version` byte is unknown: - return an `invalid_onion_version` error. diff --git a/09-features.md b/09-features.md index 21fdf09a9..ba0a0c5bf 100644 --- a/09-features.md +++ b/09-features.md @@ -19,32 +19,35 @@ for use of the channel, so the presentation of those features depends on the feature itself. The Context column decodes as follows: + * `I`: presented in the `init` message. * `N`: presented in the `node_announcement` messages * `C`: presented in the `channel_announcement` message. * `C-`: presented in the `channel_announcement` message, but always odd (optional). * `C+`: presented in the `channel_announcement` message, but always even (required). * `9`: presented in [BOLT 11](11-payment-encoding.md) invoices. - -| Bits | Name | Description | Context | Dependencies | Link | -|-------|----------------------------------|-----------------------------------------------------------|----------|-------------------|---------------------------------------| -| 0/1 | `option_data_loss_protect` | Requires or supports extra `channel_reestablish` fields | IN | | [BOLT #2][bolt02-retransmit] | -| 3 | `initial_routing_sync` | Sending node needs a complete routing information dump | I | | [BOLT #7][bolt07-sync] | -| 4/5 | `option_upfront_shutdown_script` | Commits to a shutdown scriptpubkey when opening channel | IN | | [BOLT #2][bolt02-open] | -| 6/7 | `gossip_queries` | More sophisticated gossip control | IN | | [BOLT #7][bolt07-query] | -| 8/9 | `var_onion_optin` | Requires/supports variable-length routing onion payloads | IN9 | | [Routing Onion Specification][bolt04] | -| 10/11 | `gossip_queries_ex` | Gossip queries can include additional information | IN | `gossip_queries` | [BOLT #7][bolt07-query] | -| 12/13 | `option_static_remotekey` | Static key for remote output | IN | | [BOLT #3](03-transactions.md) | -| 14/15 | `payment_secret` | Node supports `payment_secret` field | IN9 | `var_onion_optin` | [Routing Onion Specification][bolt04] | -| 16/17 | `basic_mpp` | Node can receive basic multi-part payments | IN9 | `payment_secret` | [BOLT #4][bolt04-mpp] | -| 18/19 | `option_support_large_channel` | Can create large channels | IN | | [BOLT #2](02-peer-protocol.md#the-open_channel-message) | -| 20/21 | `option_anchor_outputs` | Anchor outputs | IN | `option_static_remotekey` | [BOLT #3](03-transactions.md) | -| 22/23 | `option_anchors_zero_fee_htlc_tx` | Anchor commitment type with zero fee HTLC transactions | IN | `option_static_remotekey` | [BOLT #3][bolt03-htlc-tx], [lightning-dev][ml-sighash-single-harmful]| -| 26/27 | `option_shutdown_anysegwit` | Future segwit versions allowed in `shutdown` | IN | | [BOLT #2][bolt02-shutdown] | -| 44/45 | `option_channel_type` | Node supports the `channel_type` field in open/accept | IN | | [BOLT #2](02-peer-protocol.md#the-open_channel-message) | -| 46/47 | `option_scid_alias` | Supply channel aliases for routing | IN | | [BOLT #2][bolt02-channel-ready] | -| 48/49 | `option_payment_metadata` | Payment metadata in tlv record | 9 | | [BOLT #11](11-payment-encoding.md#tagged-fields) -| 50/51 | `option_zeroconf` | Understands zeroconf channel types | IN | `option_scid_alias` | [BOLT #2][bolt02-channel-ready] | +* `B`: presented in the `allowed_features` field of a blinded path. + +| Bits | Name | Description | Context | Dependencies | Link | +|-------|-----------------------------------|-----------------------------------------------------------|----------|---------------------------|-----------------------------------------------------------------------| +| 0/1 | `option_data_loss_protect` | Requires or supports extra `channel_reestablish` fields | IN | | [BOLT #2][bolt02-retransmit] | +| 3 | `initial_routing_sync` | Sending node needs a complete routing information dump | I | | [BOLT #7][bolt07-sync] | +| 4/5 | `option_upfront_shutdown_script` | Commits to a shutdown scriptpubkey when opening channel | IN | | [BOLT #2][bolt02-open] | +| 6/7 | `gossip_queries` | More sophisticated gossip control | IN | | [BOLT #7][bolt07-query] | +| 8/9 | `var_onion_optin` | Requires/supports variable-length routing onion payloads | IN9 | | [Routing Onion Specification][bolt04] | +| 10/11 | `gossip_queries_ex` | Gossip queries can include additional information | IN | `gossip_queries` | [BOLT #7][bolt07-query] | +| 12/13 | `option_static_remotekey` | Static key for remote output | IN | | [BOLT #3](03-transactions.md) | +| 14/15 | `payment_secret` | Node supports `payment_secret` field | IN9 | `var_onion_optin` | [Routing Onion Specification][bolt04] | +| 16/17 | `basic_mpp` | Node can receive basic multi-part payments | IN9 | `payment_secret` | [BOLT #4][bolt04-mpp] | +| 18/19 | `option_support_large_channel` | Can create large channels | IN | | [BOLT #2](02-peer-protocol.md#the-open_channel-message) | +| 20/21 | `option_anchor_outputs` | Anchor outputs | IN | `option_static_remotekey` | [BOLT #3](03-transactions.md) | +| 22/23 | `option_anchors_zero_fee_htlc_tx` | Anchor commitment type with zero fee HTLC transactions | IN | `option_static_remotekey` | [BOLT #3][bolt03-htlc-tx], [lightning-dev][ml-sighash-single-harmful] | +| 24/25 | `option_route_blinding` | Node supports blinded paths | IN9 | `var_onion_optin` | [BOLT #4](bolt04-route-blinding) | +| 26/27 | `option_shutdown_anysegwit` | Future segwit versions allowed in `shutdown` | IN | | [BOLT #2][bolt02-shutdown] | +| 44/45 | `option_channel_type` | Node supports the `channel_type` field in open/accept | IN | | [BOLT #2](02-peer-protocol.md#the-open_channel-message) | +| 46/47 | `option_scid_alias` | Supply channel aliases for routing | IN | | [BOLT #2][bolt02-channel-ready] | +| 48/49 | `option_payment_metadata` | Payment metadata in tlv record | 9 | | [BOLT #11](11-payment-encoding.md#tagged-fields) | +| 50/51 | `option_zeroconf` | Understands zeroconf channel types | IN | `option_scid_alias` | [BOLT #2][bolt02-channel-ready] | ## Definitions @@ -100,4 +103,5 @@ This work is licensed under a [Creative Commons Attribution 4.0 International Li [bolt07-sync]: 07-routing-gossip.md#initial-sync [bolt07-query]: 07-routing-gossip.md#query-messages [bolt04-mpp]: 04-onion-routing.md#basic-multi-part-payments +[bolt04-route-blinding]: 04-onion-routing.md#route-blinding [ml-sighash-single-harmful]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-September/002796.html diff --git a/bolt04/blinded-payment-onion-test.json b/bolt04/blinded-payment-onion-test.json new file mode 100644 index 000000000..97406fb1f --- /dev/null +++ b/bolt04/blinded-payment-onion-test.json @@ -0,0 +1,183 @@ +{ + "comment": "test vector for a payment onion sent to a partially blinded route", + "generate": { + "comment": "This section contains test data for creating a payment onion that sends to the provided blinded route.", + "session_key": "0303030303030303030303030303030303030303030303030303030303030303", + "associated_data": "4242424242424242424242424242424242424242424242424242424242424242", + "final_amount_msat": 100000, + "final_cltv": 749000, + "blinded_payinfo": { + "comment": "total costs for using the blinded path", + "fee_base_msat": 10100, + "fee_proportional_millionths": 251, + "cltv_expiry_delta": 150 + }, + "blinded_route": { + "comment": "This section contains a blinded route that the sender will use for his payment, usually obtained from a Bolt 12 invoice.", + "introduction_node_id": "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c", + "blinding": "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "hops": [ + { + "alias": "Bob", + "blinded_node_id": "03da173ad2aee2f701f17e59fbd16cb708906d69838a5f088e8123fb36e89a2c25", + "encrypted_data": "cd7b00ff9c09ed28102b210ac73aa12d63e90852cebc496c49f57c499a2888b49f2e72b19446f7e60a818aa2938d8c625415b992b8928a7321edb8f7cea40de362bed082ad51acc6156dca5532fb68" + }, + { + "alias": "Carol", + "blinded_node_id": "02e466727716f044290abf91a14a6d90e87487da160c2a3cbd0d465d7a78eb83a7", + "encrypted_data": "cc0f16524fd7f8bb0f4e8d40ad71709ef140174c76faa574cac401bb8992fef76c4d004aa485dd599ed1cf2715f570f656a5aaecaf1ee8dc9d0fa1d424759be1932a8f29fac08bc2d2a1ed7159f28b" + }, + { + "alias": "Dave", + "blinded_node_id": "036861b366f284f0a11738ffbf7eda46241a8977592878fe3175ae1d1e4754eccf", + "encrypted_data": "0fa1a72cff3b64a3d6e1e4903cf8c8b0a17144aeb249dcb86561adee1f679ee8db3e561d9e49895fd4bcebf6f58d6f61a6d41a9bf5aa4b0453437856632e8255c351873143ddf2bb2b0832b091e1b4" + }, + { + "alias": "Eve", + "blinded_node_id": "021982a48086cb8984427d3727fe35a03d396b234f0701f5249daa12e8105c8dae", + "encrypted_data": "da1c7e5f7881219884beae6ae68971de73bab4c3055d9865b1afb60722a63c688768042ade22f2c22f5724767d171fd221d3e579e43b354cc72e3ef146ada91a892d95fc48662f5b158add0af457da" + } + ] + }, + "full_route": { + "comment": "The sender adds one normal hop through Alice, who doesn't support blinded payments (and doesn't charge a fee). The sender provides the initial blinding point in Bob's onion payload, and encrypted_data for each node in the blinded route.", + "hops": [ + { + "alias": "Alice", + "pubkey": "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619", + "payload": "14020301ae2d04030b6e5e0608000000000000000a", + "tlvs": { + "outgoing_channel_id": "0x0x10", + "amt_to_forward": 110125, + "outgoing_cltv_value": 749150 + } + }, + { + "alias": "Bob", + "pubkey": "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c", + "payload": "740a4fcd7b00ff9c09ed28102b210ac73aa12d63e90852cebc496c49f57c499a2888b49f2e72b19446f7e60a818aa2938d8c625415b992b8928a7321edb8f7cea40de362bed082ad51acc6156dca5532fb680c21024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "tlvs": { + "current_blinding_point": "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "encrypted_recipient_data": { + "padding": "0000000000000000000000000000000000000000000000000000000000000000", + "short_channel_id": "0x0x1", + "payment_relay": { + "cltv_expiry_delta": 50, + "fee_proportional_millionths": 0, + "fee_base_msat": 10000 + }, + "payment_constraints": { + "max_cltv_expiry": 750150, + "htlc_minimum_msat": 50 + }, + "allowed_features": { + "features": [] + } + } + } + }, + { + "alias": "Carol", + "pubkey": "02e466727716f044290abf91a14a6d90e87487da160c2a3cbd0d465d7a78eb83a7", + "payload": "510a4fcc0f16524fd7f8bb0f4e8d40ad71709ef140174c76faa574cac401bb8992fef76c4d004aa485dd599ed1cf2715f570f656a5aaecaf1ee8dc9d0fa1d424759be1932a8f29fac08bc2d2a1ed7159f28b", + "tlvs": { + "encrypted_recipient_data": { + "short_channel_id": "0x0x2", + "next_blinding_override": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + "payment_relay": { + "cltv_expiry_delta": 75, + "fee_proportional_millionths": 150, + "fee_base_msat": 100 + }, + "payment_constraints": { + "max_cltv_expiry": 750100, + "htlc_minimum_msat": 50 + }, + "allowed_features": { + "features": [] + } + } + } + }, + { + "alias": "Dave", + "pubkey": "036861b366f284f0a11738ffbf7eda46241a8977592878fe3175ae1d1e4754eccf", + "payload": "510a4f0fa1a72cff3b64a3d6e1e4903cf8c8b0a17144aeb249dcb86561adee1f679ee8db3e561d9e49895fd4bcebf6f58d6f61a6d41a9bf5aa4b0453437856632e8255c351873143ddf2bb2b0832b091e1b4", + "tlvs": { + "encrypted_recipient_data": { + "padding": "00000000000000000000000000000000000000000000000000000000000000000000", + "short_channel_id": "0x0x3", + "payment_relay": { + "cltv_expiry_delta": 25, + "fee_proportional_millionths": 100 + }, + "payment_constraints": { + "max_cltv_expiry": 750025, + "htlc_minimum_msat": 50 + }, + "allowed_features": { + "features": [] + } + } + } + }, + { + "alias": "Eve", + "pubkey": "021982a48086cb8984427d3727fe35a03d396b234f0701f5249daa12e8105c8dae", + "payload": "6002030186a004030b6dc80a4fda1c7e5f7881219884beae6ae68971de73bab4c3055d9865b1afb60722a63c688768042ade22f2c22f5724767d171fd221d3e579e43b354cc72e3ef146ada91a892d95fc48662f5b158add0af457da12030249f0", + "tlvs": { + "amt_to_forward": 100000, + "total_amount_msat": 150000, + "outgoing_cltv_value": 749000, + "encrypted_recipient_data": { + "padding": "00000000000000000000000000000000000000000000000000000000", + "path_id": "c9cf92f45ade68345bc20ae672e2012f4af487ed4415", + "payment_constraints": { + "max_cltv_expiry": 750000, + "htlc_minimum_msat": 50 + }, + "allowed_features": { + "features": [] + } + } + } + } + ] + }, + "onion": "0002531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337dadf610256c6ab518495dce9cdedf9391e21a71dada75be905267ba82f326c0513dda706908cfee834996700f881b2aed106585d61a2690de4ebe5d56ad2013b520af2a3c49316bc590ee83e8c31b1eb11ff766dad27ca993326b1ed582fb451a2ad87fbf6601134c6341c4a2deb6850e25a355be68dbb6923dc89444fdd74a0f700433b667bda345926099f5547b07e97ad903e8a01566a78ae177366239e793dac719de805565b6d0a1d290e273f705cfc56873f8b5e28225f7ded7a1d4ceffae63f91e477be8c917c786435976102a924ba4ba3de6150c829ce01c25428f2f5d05ef023be7d590ecdf6603730db3948f80ca1ed3d85227e64ef77200b9b557f427b6e1073cfa0e63e4485441768b98ab11ba8104a6cee1d7af7bb5ee9c05cf9cf4718901e92e09dfe5cb3af336a953072391c1e91fc2f4b92e124b38e0c6d17ef6ba7bbe93f02046975bb01b7f766fcfc5a755af11a90cc7eb3505986b56e07a7855534d03b79f0dfbfe645b0d6d4185c038771fd25b800aa26b2ed2e30b1e713659468618a2fea04fcd0473284598f76b11b0d159d343bc9711d3bea8d561547bcc8fff12317c0e7b1ee75bcb8082d762b6417f99d0f71ff7c060f6b564ad6827edaffa72eefcc4ce633a8da8d41c19d8f6aebd8878869eb518ccc16dccae6a94c690957598ce0295c1c46af5d7a2f0955b5400526bfd1430f554562614b5d00feff3946427be520dee629b76b6a9c2b1da6701c8ca628a69d6d40e20dd69d6e879d7a052d9c16f544b49738c7ff3cdd0613e9ed00ead7707702d1a6a0b88de1927a50c36beb78f4ff81e3dd97b706307596eebb363d418a891e1cb4589ce86ce81cdc0e1473d7a7dd5f6bb6e147c1f7c46fa879b4512c25704da6cdbb3c123a72e3585dc07b3e5cbe7fecf3a08426eee8c70ddc46ebf98b0bcb14a08c469cb5cfb6702acc0befd17640fa60244eca491280a95fbbc5833d26e4be70fcf798b55e06eb9fcb156942dcf108236f32a5a6c605687ba4f037eddbb1834dcbcd5293a0b66c621346ca5d893d239c26619b24c71f25cecc275e1ab24436ac01c80c0006fab2d95e82e3a0c3ea02d08ec5b24eb39205c49f4b549dcab7a88962336c4624716902f4e08f2b23cfd324f18405d66e9da3627ac34a6873ba2238386313af20d5a13bbd507fdc73015a17e3bd38fae1145f7f70d7cb8c5e1cdf9cf06d1246592a25d56ec2ae44cd7f75aa7f5f4a2b2ee49a41a26be4fab3f3f2ceb7b08510c5e2b7255326e4c417325b333cafe96dde1314a15dd6779a7d5a8a40622260041e936247eec8ec39ca29a1e18161db37497bdd4447a7d5ef3b8d22a2acd7f486b152bb66d3a15afc41dc9245a8d75e1d33704d4471e417ccc8d31645fdd647a2c191692675cf97664951d6ce98237d78b0962ad1433b5a3e49ddddbf57a391b14dcce00b4d7efe5cbb1e78f30d5ef53d66c381a45e275d2dcf6be559acb3c42494a9a2156eb8dcf03dd92b2ebaa697ea628fa0f75f125e4a7daa10f8dcf56ebaf7814557708c75580fad2bbb33e66ad7a4788a7aaac792aaae76138d7ff09df6a1a1920ddcf22e5e7007b15171b51ff81799355232ce39f7d5ceeaf704255d790041d6390a69f42816cba641ec81faa3d7c0fdec59dfe4ca41f31a692eaffc66b083995d86c575aea4514a3e09e8b3a1fa4d1591a2505f253ad0b6bfd9d87f063d2be414d3a427c0506a88ac5bdbef9b50d73bce876f85c196dca435e210e1d6713695b529ddda3350fb5065a6a8288abd265380917bac8ebbc7d5ced564587471dddf90c22ce6dbadea7e7a6723438d4cf6ac6dae27d033a8cadd77ab262e8defb33445ddb2056ec364c7629c33745e2338" + }, + "decrypt": { + "comment": "This section contains the internal values generated by intermediate nodes when decrypting their payload.", + "hops": [ + { + "alias": "Alice", + "onion": "0002531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337dadf610256c6ab518495dce9cdedf9391e21a71dada75be905267ba82f326c0513dda706908cfee834996700f881b2aed106585d61a2690de4ebe5d56ad2013b520af2a3c49316bc590ee83e8c31b1eb11ff766dad27ca993326b1ed582fb451a2ad87fbf6601134c6341c4a2deb6850e25a355be68dbb6923dc89444fdd74a0f700433b667bda345926099f5547b07e97ad903e8a01566a78ae177366239e793dac719de805565b6d0a1d290e273f705cfc56873f8b5e28225f7ded7a1d4ceffae63f91e477be8c917c786435976102a924ba4ba3de6150c829ce01c25428f2f5d05ef023be7d590ecdf6603730db3948f80ca1ed3d85227e64ef77200b9b557f427b6e1073cfa0e63e4485441768b98ab11ba8104a6cee1d7af7bb5ee9c05cf9cf4718901e92e09dfe5cb3af336a953072391c1e91fc2f4b92e124b38e0c6d17ef6ba7bbe93f02046975bb01b7f766fcfc5a755af11a90cc7eb3505986b56e07a7855534d03b79f0dfbfe645b0d6d4185c038771fd25b800aa26b2ed2e30b1e713659468618a2fea04fcd0473284598f76b11b0d159d343bc9711d3bea8d561547bcc8fff12317c0e7b1ee75bcb8082d762b6417f99d0f71ff7c060f6b564ad6827edaffa72eefcc4ce633a8da8d41c19d8f6aebd8878869eb518ccc16dccae6a94c690957598ce0295c1c46af5d7a2f0955b5400526bfd1430f554562614b5d00feff3946427be520dee629b76b6a9c2b1da6701c8ca628a69d6d40e20dd69d6e879d7a052d9c16f544b49738c7ff3cdd0613e9ed00ead7707702d1a6a0b88de1927a50c36beb78f4ff81e3dd97b706307596eebb363d418a891e1cb4589ce86ce81cdc0e1473d7a7dd5f6bb6e147c1f7c46fa879b4512c25704da6cdbb3c123a72e3585dc07b3e5cbe7fecf3a08426eee8c70ddc46ebf98b0bcb14a08c469cb5cfb6702acc0befd17640fa60244eca491280a95fbbc5833d26e4be70fcf798b55e06eb9fcb156942dcf108236f32a5a6c605687ba4f037eddbb1834dcbcd5293a0b66c621346ca5d893d239c26619b24c71f25cecc275e1ab24436ac01c80c0006fab2d95e82e3a0c3ea02d08ec5b24eb39205c49f4b549dcab7a88962336c4624716902f4e08f2b23cfd324f18405d66e9da3627ac34a6873ba2238386313af20d5a13bbd507fdc73015a17e3bd38fae1145f7f70d7cb8c5e1cdf9cf06d1246592a25d56ec2ae44cd7f75aa7f5f4a2b2ee49a41a26be4fab3f3f2ceb7b08510c5e2b7255326e4c417325b333cafe96dde1314a15dd6779a7d5a8a40622260041e936247eec8ec39ca29a1e18161db37497bdd4447a7d5ef3b8d22a2acd7f486b152bb66d3a15afc41dc9245a8d75e1d33704d4471e417ccc8d31645fdd647a2c191692675cf97664951d6ce98237d78b0962ad1433b5a3e49ddddbf57a391b14dcce00b4d7efe5cbb1e78f30d5ef53d66c381a45e275d2dcf6be559acb3c42494a9a2156eb8dcf03dd92b2ebaa697ea628fa0f75f125e4a7daa10f8dcf56ebaf7814557708c75580fad2bbb33e66ad7a4788a7aaac792aaae76138d7ff09df6a1a1920ddcf22e5e7007b15171b51ff81799355232ce39f7d5ceeaf704255d790041d6390a69f42816cba641ec81faa3d7c0fdec59dfe4ca41f31a692eaffc66b083995d86c575aea4514a3e09e8b3a1fa4d1591a2505f253ad0b6bfd9d87f063d2be414d3a427c0506a88ac5bdbef9b50d73bce876f85c196dca435e210e1d6713695b529ddda3350fb5065a6a8288abd265380917bac8ebbc7d5ced564587471dddf90c22ce6dbadea7e7a6723438d4cf6ac6dae27d033a8cadd77ab262e8defb33445ddb2056ec364c7629c33745e2338", + "node_privkey": "4141414141414141414141414141414141414141414141414141414141414141" + }, + { + "alias": "Bob", + "onion": "000280caa47c2a0ea677f6a77529e46caa04212153a8d5f829bee1e7339b17e2e2a9a3461d10472364a4ff12344beb6df96fb0c38ec47d1e956ddff5a665190fcca5ed02c3a3903fd8bbd4a4b95b197867c378b67b08f0624cfe80734ba512869c0fa22099beb1f6f1ea325b07ce7449736d7ffad79178b428d8ea2d7bc6578f12dbd788ef933f3b5ba352797c41f6786c3820c96726acf8bddf2cfa5d9c617d2b0bd5ab7b93f7964c98f44cf47db8422f47d11100236a29579f1cafcd38bd979814e1d2bf6d625edf50e1e21bfaf6268e3180dd7aafd3892da281c6dd53c1c366d0fdaf670b6ad84a38d6e8a3f4a80d132d686fd3b7443bc2250023bdb9303190f74c9220481cf99da30b5ec2bdb5a49028f5014e3eaeaa48429a0c78ebd3bb7c7d582c22b7d547cd269f0c4490373a81bf92687e73dac2075b4bda189ce0be225f5f510655e37a6e724a1415bede0a076b92a882cc2a82878ba67aaedf71454eb42b7f8638df8e21d5f708006e5112e2dc0a4afbcfed9f2c7959be812853ca8e313fbc99a0f38f1ee4479c96ccb836632b0808401db159bd2637f7a664013241e4664e994a0a9a3940115a702c60381e66d291e1ade1be2802e1226e311e3201a7c9682b6bc4354caff3d439adb1dfee53ad3fb3dd5e169d64796853bb323129f41213b166a7cac00f728c3e33bd7e59aa2ac0d1341cdb1532b507a0f446e51022a882ac16405442347b70f78c9b6e122f8e70096a4fae4c0405db5b869e0b7b59b09519c4dbf4d4980483906e837da0bee93f668ffaad37d6a4764211a02f95ad2dc2d942c198796741c20a3baf8efb5a53bd9c1a0148318d60a97d0013ab63269097ea295d62c1426d064f0b31c02e74a348ee0509998e701069f5a1e0c1086aed38d2ec87da69fb57a992d88ace3b4a16b0960f5a94936e2e684a9926cf4f911969a2a5d31fed0c7616d30197848253170e51274278873b11f3f5cc1b04b14aa5812524e4d86cbf08306c2aa671288324d7a009b2be533b1d7d0ce6defeeb630b86a9655f1e6424fcb559ed67457c115fba0d0719374802ea68fab299fd3f273be86fa3d2e7456020db2f47c6ec16c21ce6ec65de495e20af1941a5dcd65d910c1cb93f22e1318c173c645c81aed681c9704a8a541ac3d6ff604f46d0260468acbfec1b771b9eb8cd49a2124468dae786571895a569aae18438eaee6343ab2634823119fa2439634645d12e3b4a748b9cc0398b8416a834eb5d9e5cf619bbfaba4894d1c574c738caf530d0862f4cc75eb52bd3921d2d9edb09940edb1e3776423b0046d870ccdcc5d61f72e0440b97a93eeef21fb246a779d339be301a5971400749d6cc9911dfbf9de8ae86fac83c860fdd0e2bfa40af37c99d50e50fd6e5ae86597a201112ed404042b55e132f243dec481a2adc1d5e4b71e1efdea806ea900b2907ce877742d5ecf700ff3640f737863d0dd7207e462ee8d0e17d52047a88ae7446f419560d23968bf64957949e36953155b0ac2511c66be2890b4036329a21e132efb635297a64431899e0c351e50c6682c9b4d79b5d122466d02cd84f206369417d9c194a9349d3c631d72eb7857a9cd542906fc02ad6cdcf9bcf25ace3d826b6623fa5164351e14d3f0de5c8445a2ba3aae26595d0e31c3e307c1d56d4274f61f056145c1b8d6880872b9b10a8bfa4a923cad2edbcf5c50eba48936ed2bcc0be60eb721a74b46704aaae5ad24e2797852195dfacbb30a777d33b63d4dc4f35cfbe5e88fd1944c55a54fd53581446ea061ad29f4671da819ad7488c5dfc700f5f7a1b2af0d6a6e9d9ffc570a6d3209614ab4dc43728f3f0cd7eb4ce36ccd98936bbcbd32627384434bd01e9c0f93b2a5173fba184685e19b9af78afe876aa4e4b4242382b293133771d95a2bd83fa9c62", + "node_privkey": "4242424242424242424242424242424242424242424242424242424242424242", + "next_blinding": "034e09f450a80c3d252b258aba0a61215bf60dda3b0dc78ffb0736ea1259dfd8a0" + }, + { + "alias": "Carol", + "onion": "000288b48876fb0dc0d7375233ccaf2910dc0dc81ba52e5a7906f00d75e0d58dbd4bb7c2714870529410735f0951e72cbe981e2e167c0d8f3de33a36e39e78465aea2acad1e23c78b6fd342d63e37d214c912b4a0be344618f779138edc1b42a5ca3218ca2fea4be427f6cd0d387160db2bf6c2ba8e82941c8cf3626bd6bed7187f633012ef49df38f6b12963cb639e9eed1b9d269dcebcbd0b25287aa536ec85e7320b02e193122199a745ccbaaebd37f5d4b71f52f9b50feeb793eeef56924a046bc5e7003f6253e0284a8d3fe2e42c3564050f1e753cd32cc258ac0ffa6e05eecad5ba1286f78252e60dd884a65405ab673a85ba52adfa65c1086d4bb37ba2e0848adb2b04379775ad798492b14e8997f30ffa9cf5d432bdf5b246fce008fd876399beed827db58195f4f6192f6ff4ec63cb17fdcb497cb7aec26846a71dd8dca02fc3bb14dd7231a4d62a981bec54b71eb20331096dfa214a0ff4489ee96db663826ae8c850e9f06baa52a47b8eb576363f97e742aab2dc616acc6e74588e1d2ac16694febc90abaf5b1c684163c0e615a68d32633f01934adc8c6bf91fa3fd7aad033b7596d60402494e45e2c1632c40f7bfbd88a81a896a1d28ed6338c83e1eeaa467945d59998eb456c95f94bf1892e8f326ec2d5e0196b7073f106febc6ab8ca5bcc23f77ffc819bc1b5debce418ccc7d8391bbf33bceee6110beba170121bd99f54c956e64970bdab31227b03ee0ea3f01fbd9bd74015f6f82d04fab072e8f85f4370d09f41ee3e48eb959767bd989abb4eea42c4daa0437a7f747d7f9b70eb87b9f9b0b6f283b8205912601a432999b8869fd9fe5bad3572edac24da7184f9298f21ff60923db277264d29c846dd2f228f6fc53b6b60364237de64773f803f174ed10229c374f603ccc5fd3a62cb413ffe6f5630dc646bb33f231b2350537ec39e5d3f2fe1a1cb019ed0b18ad14019cad27afcca8ad70387ca110394c0432774f1aa1fa404b2e086c84a55388d3bd102501c78ef925cce89d76fa04c3f20f2d1f0ce507ac8b37b7913e3949ba12bbc5a4f6bac37c2415622d365bc8b83709a28e3d46f3850c89a3ff4d027fef6e3e4ce5c6c85f663c7eaec3c9730106fb82f53249a905533cfabee812aae51965b24b42f7ab471967bc8e73354e69141ee26a1f03684d5fb9c256a34de8257210e0390dd3962db521ae0a3bdab28300610ab2a634b699e5f092da5a061609ef6414bd805c8171f54ad6f285fb64ce0becca0b61188badcf8ef21190dad629e3fb3e89f55ebba829919540ebf5f8ae4283836d3c9133c1ca3365f6b9394916730411650686e0c2ab9c53b6cda9efdd5cfcb53ba9b6962bb6aa49d0a83a87460b60a9c7d2643ee99afe652883795f14014ec5df61b1e30c041c1fa6487f3c82f1ded5f83ffbef5017e197b7fb77be3b36e284a15e57d45bf9316dcaf97eb78ee4642b731ba05c5063bce1333fab4af6da97c80a96ee599b4df823efbedc250c0abba9783da7ddf2414b2a4774ff2880a7dc6791103e18b8631e39743cf9e87aed71700daa5dc72fdae520324741f92ea3d510ff555dea5e45f15cda87272d4559a12d4777680acb06993840e3c748da82c16cae556015fb2acd0335da11a3388575394048ab71199793ab706abc9d68add2075d79a5cc0f779845ee8b98951be61fd293d6c15b9d4653935bf17cf50bd31f8b79e60dba0e7fd6864754fd94262485a4f65e7eb3e1922f51b1a4dd2b4fd2c20d94d1213fbe90bd603dfc7e15176382e3ce0f43f980d44d23bf3c57f54a15f42c171a8f2511e28ac178c6f01396e50397a57ffb09c5e6c315bd3ae7983577c1a0386c6d5d9a2223438e321b0fedfdee58fa452d57dc11a256834bb49ac9deeec88e4bf563c7340f44a240caec941c7e50f09cf", + "node_privkey": "4343434343434343434343434343434343434343434343434343434343434343", + "next_blinding": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f" + }, + { + "alias": "Dave", + "onion": "0003f25471c0f2ff549a7fd7859100306bb6c294c209f34c77f782897f184b967c498efc246bdb8e060a6d1cf8dd0d4d732e33311fb96c9e9f1274005fa3d08b41704a1b7224c6300a7caead7baa0a8263eba2e0de6956ee8e4a1958264f47e4cf20d194eb576f5bd249ee4fece563f80fd76dc3eaca8f956188406d83195752b5c90c4b2a5e7ac3a8d5c62b17b551aff48ef6842a7e9326832c9a4a2fd415011150a9e71beb901fd9747bac8add1c694b612730dc86b5b19a0bbbc675947a953316e3303d7b30c182f94def9206671edac9a3ec3e52d28fc28247a1c73ab751bf61c82c3950f617e758f79bd0ba294defb20466eaf1e801462046baad3aec3e5b8868a7b037f23d73a47a7e74c77107334f37388cff863e452820c61d89728fa75c84bc7cdfc06dcdd1911f5f803353926d073efd65251380e174913aae03318ea5b6f0ec83998c55ab99bef62803ea2da9f6d1ea892b90efc4f8ffb685a5201a781da2e6ac5923645638c9709ae32171a00c0cd3d8c7eedfb06b4eedc7d3e566987e2e3805a038f21d78ded5d6c7137a5e8e592f3180ee4d5f4e1289176f67fc38690d0958bc82e240b72b10577f340f1e14b8633f0b6d9729ff4618be2a972400a015a871ba33be70335f652a8d70f2bd32421d6ac2af781d667dad787d6aef4505a15d046579e46eebe757444cffca6d0610f0dd36a7ce57af969bd0c3f7006298ef406a25f689daf58f875d44d2423ebf195b503f11c37c506ea6abe50a463f7bb5e9b964604d832724de768513f6b38bf71715e1feea8a6e86797788d487146891564919da1372016ed8f08c7fcbff66a4a65a3d0fcd8e3daac6eba41f5d65ef2d8075364a9e78b3a273549f6eac4abb72e912e237990367e0d43e89945f8ac3907be5a6c662139485a50cb5ce3f0ba08586c39f6c515368ec3f91b72295f1b7a73a9df322ae9a45d363d6c616be3300083764cbdee31221f25a318f095feacb09f957c96db30fccca47a0215b576c3ed925a0bad05d6400abe318c11f36628c387a4ee38832182cd44b3cd48e5422c1f1e3b57218dfe72c611f5415127720e60f6e2400607e61841b76de1704bcbeb0daf1377ccb2253916de2b6d490bb71ba0a44fea2e94f2423d723934557d5905e01b2b80232a884e258d46dc92ea11e0818d0ece5b914f02049866e151801ab8c9aea155479b354dc91151fb9ba43277458f9760dd859faaa139e3b9ab36a1dbc36a93ef2c90598b20cb30ef3c4f23a2d6178b4d1da668fb328a25d84d30a132d9f2a6a988cbe2e5c2be01cb6db4b4725a50d6cdacf5fb083e7d650a25bec1407fbc047d26076c7596429a29606ad527e97ef0824ad6c1b05831a3e5b71c63a528918a3301cdd4061fc1fcce3da601961f2602a2b002ac8404125c2d52666263858a923e197efcda873c32d86897352e4f2264ad6a1b48acc0fe78ff55cb442cb2bb5fa2880810e1d00aa0247057fb80b7ed36cf9647af41b44ee4a63ee2d6f652526404572520a7d2d9dcde4e62df0c3be89f8471550594cdd16a51a9cacc58729c092c68506162fe65edc2314055d389f724ced189d826a546b5c4d08a43d977b3cf033de5760b71a7cc38ee5851592031aafb467a89b3b6c7ed67b15d44c48d6baedce3e95e08ec7c55038f3eba90ccb900895734f0fb7efe54961ce493369cc56416898a9bed7c2482871c15a7f1eb5ed17c33657fc31333539c2dfb59461af09e7049228113b5c9feea5a6e9959c18c51b19c90995afb9c76f2c0c820964cd7989c993a73925818a656c6a18dcd1a1e3782b2eae06dd5a41250ec2d1c203626ab9920c1673339eff04b1eb0cab85ef5909f571f9b83cdf21697c9f5cfa1c76e7bca955510e2126b3bb989a4ac21cf948f965e48bc363d2997437797b4f770e8b65", + "node_privkey": "4444444444444444444444444444444444444444444444444444444444444444", + "next_blinding": "03e09038ee76e50f444b19abf0a555e8697e035f62937168b80adf0931b31ce52a" + }, + { + "alias": "Eve", + "onion": "0002ef43c4dfe9aee14248c445406ac7980474ce106c504d9025f57963739130adfd06eb26201baee8866af2d1b7a7ab26595349dad002af0590193aaa8f400ab394f5994ec831aeeecb64421c566e3556cbdd7e7e50deb1fc49fd5e007308ab6494415514abff978899623f9b6065ca1e243bb78170118e8b8c8b53b750b59cc1ec017d167adbb3aabab7c2d84fbf94f5d827239f4c2b9d2c3cfe68fe5641f25e386202a4b6edff2a71e700229df7230c8ca31bd5588f04799e9640c9c20a47cba713f3cc5ad3202e14bb520880f2a8409d8e7835cae21b48a651c2d47fe6af785889ab98f1416f6e4ad67a66ae681e9a8828bad3f9b6890221c4a7ec80531d6b63eb30843f613ce644795bc8bcee60e8f7b36f3fd04de762f103c52efaf36a2f3bbbaac482d6271dc4180c10bcc076c04d06ea7fd8fb6a647e0e10523b05da2d89e4139fb55c2315cd01bdcbd57587fef8442d7ff5620630fd2d2e79739d90be811bf2cba60415d6cba2cea14ba1859f3122cd905c4e12e3e2a1ab6fab54b2ec40e434626e2d3c3195c02c82a8bd64d226c2328ac72ca12197d9908eaf54333717448ce6ed73adc0ac05e2ee1d735131d87918beb8995993dc8f63fe10f2c8eba2be7ab8bb44d9f78f59ef3e4c180bd75e4eef2381450c6f0480d543997305f1d07815993b5aca8d88d474966d9abec93bb069a16aa2da75b87f94576e01d08a17d3e0e3d0370f010733a7d7affb12cdf94c259a62607fce71003535c4727305de5ff7bba3840922844b3a45f62c29715fccf440517ef121450f6962396fba9b07036d085582405dcae6ee95964b66bc7c85b8d02d90091500db3cebf6de584f86b7b55335a8c9aa26381b00747f055cc458a2cadfccf9c29702bf941447beaca6583cca09492a57d4b03b2ca00dbaf41dfd6a9b249381626a7debe475735a7e39e77a363eccf14669046f656cc09ad448da8d8b545e6a604f46dc481786d09a94c63cf23f49ba367d2929466364dbce2a8ffce3dadf8f4cef8a56e1fefa1a3304a953fe83018e57d8a95694b02d994fea2630a9a3d5f1e2f6d6142d503ec4152871f7122d7e566a03261f554639e7a759e0e73846f71d5cace37d91336fc9ca9396bf64ca2cf45fa2db779b3b5c63b04f1c0c1fb79fdfcf5a82b0202df934ae1720a7ce1e047cbec3f82737b50168c974f4623cacce87e3f5bd5232caca7956d28ffedcf11ac5998662c5f6b13c6126584ca2e894d3fcbad4d130bbe22e88a135e0020cdd43853e0b3af3800e9544854d211e873cf68ab683578d501d69ec5dc7fce42ac436d58243880c1b88227b0681c6c9dd8a8ad0793202b15ab63b787b748e258da3e68d0e649fc4ac081a71de8adbc891c113d5f722686b6ac4ed9e3cc247bc4a4643416f480627e9de20f7307f434a499f5c6951c2e8b3ff51d455bf65ceb5ee3dee47b968ac2642e13d8a68f903b73627c2e75788fecca5836371a908eea4f1ea44db2315bc185f77e478efeaaa4da2da13fe7aeaa79ed1d04876a8b2b7b333c5de8c4c9a50274c2eb7b9bd2a3630c57173174781fc9785235f830cefa1c82080eaffdef257f18eedc9ddfd25a696a11a3dc56cd836be72f5f4a2cbb6316d5d3b1ad91a7ec7d877f28d2c29a5525b0b24362699281b0e3b48f38caf1085045fe9089f9e6fb29e4b47aa4cecf68c9bf72073469bd9beeea5e88bfe554cb6a81231149ba7fe7784c154fd8b0f9179ecdf1e9fd5c2939ec1ab16df9cbe9359101ebce933d4f65d3f66f87afaecfe9c046b52f4878b6c430329df7bd879fba8864fcbd9b782bf545734699b9b5a66b466dcedc0c9368803b5b0f1232950cef398ad3e057a5db964bd3e5c8a5717b30b41601a4f11ad63afe404cb6f1e8ea5fd7a8e085b65ca5136146febf4d47928dcc9a9e0", + "node_privkey": "4545454545454545454545454545454545454545454545454545454545454545", + "next_blinding": "038fc6859a402b96ce4998c537c823d6ab94d1598fca02c788ba5dd79fbae83589" + } + ] + } +} \ No newline at end of file diff --git a/bolt04/route-blinding-test.json b/bolt04/route-blinding-test.json new file mode 100644 index 000000000..c69cc72be --- /dev/null +++ b/bolt04/route-blinding-test.json @@ -0,0 +1,179 @@ +{ + "comment": "test vector for using blinded routes", + "generate": { + "comment": "This section contains test data for creating a blinded route. This route is the concatenation of two blinded routes: one from Dave to Eve and one from Bob to Carol.", + "hops": [ + { + "comment": "Bob creates a Bob -> Carol route with the following session_key and concatenates it with the Dave -> Eve route.", + "session_key": "0202020202020202020202020202020202020202020202020202020202020202", + "alias": "Bob", + "node_id": "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c", + "tlvs": { + "padding": "0000000000000000000000000000000000000000000000000000", + "short_channel_id": "0x0x1729", + "payment_relay": { + "cltv_expiry_delta": 36, + "fee_proportional_millionths": 150, + "fee_base_msat": 10000 + }, + "payment_constraints": { + "max_cltv_expiry": 748005, + "htlc_minimum_msat": 1500 + }, + "allowed_features": { + "features": [] + }, + "unknown_tag_561": "123456" + }, + "encoded_tlvs": "011a0000000000000000000000000000000000000000000000000000020800000000000006c10a0800240000009627100c06000b69e505dc0e00fd023103123456", + "ephemeral_privkey": "0202020202020202020202020202020202020202020202020202020202020202", + "ephemeral_pubkey": "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "shared_secret": "76771bab0cc3d0de6e6f60147fd7c9c7249a5ced3d0612bdfaeec3b15452229d", + "rho": "ba217b23c0978d84c4a19be8a9ff64bc1b40ed0d7ecf59521567a5b3a9a1dd48", + "encrypted_data": "cd4100ff9c09ed28102b210ac73aa12d63e90852cebc496c49f57c49982088b49f2e70b99287fdee0aa58aa39913ab405813b999f66783aa2fe637b3cda91ffc0913c30324e2c6ce327e045183e4bffecb", + "blinded_node_id": "03da173ad2aee2f701f17e59fbd16cb708906d69838a5f088e8123fb36e89a2c25" + }, + { + "comment": "Notice the next_blinding_override tlv in Carol's payload, indicating that Bob concatenated his route with another blinded route starting at Dave.", + "alias": "Carol", + "node_id": "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007", + "tlvs": { + "short_channel_id": "0x0x1105", + "next_blinding_override": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + "payment_relay": { + "cltv_expiry_delta": 48, + "fee_proportional_millionths": 100, + "fee_base_msat": 500 + }, + "payment_constraints": { + "max_cltv_expiry": 747969, + "htlc_minimum_msat": 1500 + }, + "allowed_features": { + "features": [] + } + }, + "encoded_tlvs": "020800000000000004510821031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f0a0800300000006401f40c06000b69c105dc0e00", + "ephemeral_privkey": "0a2aa791ac81265c139237b2b84564f6000b1d4d0e68d4b9cc97c5536c9b61c1", + "ephemeral_pubkey": "034e09f450a80c3d252b258aba0a61215bf60dda3b0dc78ffb0736ea1259dfd8a0", + "shared_secret": "dc91516ec6b530a3d641c01f29b36ed4dc29a74e063258278c0eeed50313d9b8", + "rho": "d1e62bae1a8e169da08e6204997b60b1a7971e0f246814c648125c35660f5416", + "encrypted_data": "cc0f16524fd7f8bb0b1d8d40ad71709ef140174c76faa574cac401bb8992fef76c4d004aa485dd599ed1cf2715f57ff62da5aaec5d7b10d59b04d8a9d77e472b9b3ecc2179334e411be22fa4c02b467c7e", + "blinded_node_id": "02e466727716f044290abf91a14a6d90e87487da160c2a3cbd0d465d7a78eb83a7" + }, + { + "comment": "Eve creates a Dave -> Eve blinded route using the following session_key.", + "session_key": "0101010101010101010101010101010101010101010101010101010101010101", + "alias": "Dave", + "node_id": "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991", + "tlvs": { + "padding": "0000000000000000000000000000000000000000000000000000000000000000000000", + "short_channel_id": "0x0x561", + "payment_relay": { + "cltv_expiry_delta": 144, + "fee_proportional_millionths": 250 + }, + "payment_constraints": { + "max_cltv_expiry": 747921, + "htlc_minimum_msat": 1500 + }, + "allowed_features": { + "features": [] + } + }, + "encoded_tlvs": "01230000000000000000000000000000000000000000000000000000000000000000000000020800000000000002310a060090000000fa0c06000b699105dc0e00", + "ephemeral_privkey": "0101010101010101010101010101010101010101010101010101010101010101", + "ephemeral_pubkey": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + "shared_secret": "dc46f3d1d99a536300f17bc0512376cc24b9502c5d30144674bfaa4b923d9057", + "rho": "393aa55d35c9e207a8f28180b81628a31dff558c84959cdc73130f8c321d6a06", + "encrypted_data": "0fa0a72cff3b64a3d6e1e4903cf8c8b0a17144aeb249dcb86561adee1f679ee8db3e561d9c43815fd4bcebf6f58c546da0cd8a9bf5cebd0d554802f6c0255e28e4a27343f761fe518cd897463187991105", + "blinded_node_id": "036861b366f284f0a11738ffbf7eda46241a8977592878fe3175ae1d1e4754eccf" + }, + { + "comment": "Eve is the final recipient, so she included a path_id in her own payload to verify that the route is used when she expects it.", + "alias": "Eve", + "node_id": "02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145", + "tlvs": { + "padding": "0000000000000000000000000000000000000000000000000000", + "path_id": "deadbeef", + "payment_constraints": { + "max_cltv_expiry": 747777, + "htlc_minimum_msat": 1500 + }, + "allowed_features": { + "features": [113] + }, + "unknown_tag_65535": "06c1" + }, + "encoded_tlvs": "011a00000000000000000000000000000000000000000000000000000604deadbeef0c06000b690105dc0e0f020000000000000000000000000000fdffff0206c1", + "ephemeral_privkey": "62e8bcd6b5f7affe29bec4f0515aab2eebd1ce848f4746a9638aa14e3024fb1b", + "ephemeral_pubkey": "03e09038ee76e50f444b19abf0a555e8697e035f62937168b80adf0931b31ce52a", + "shared_secret": "352a706b194c2b6d0a04ba1f617383fb816dc5f8f9ac0b60dd19c9ae3b517289", + "rho": "719d0307340b1c68b79865111f0de6e97b093a30bc603cebd1beb9eef116f2d8", + "encrypted_data": "da1a7e5f7881219884beae6ae68971de73bab4c3055d9865b1afb60724a2e4d3f0489ad884f7f3f77149209f0df51efd6b276294a02e3949c7254fbc8b5cab58212d9a78983e1cf86fe218b30c4ca8f6d8", + "blinded_node_id": "021982a48086cb8984427d3727fe35a03d396b234f0701f5249daa12e8105c8dae" + } + ] + }, + "route": { + "comment": "This section contains the resulting blinded route, which can then be used inside onion messages or payments.", + "introduction_node_id": "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c", + "blinding": "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "hops": [ + { + "blinded_node_id": "03da173ad2aee2f701f17e59fbd16cb708906d69838a5f088e8123fb36e89a2c25", + "encrypted_data": "cd4100ff9c09ed28102b210ac73aa12d63e90852cebc496c49f57c49982088b49f2e70b99287fdee0aa58aa39913ab405813b999f66783aa2fe637b3cda91ffc0913c30324e2c6ce327e045183e4bffecb" + }, + { + "blinded_node_id": "02e466727716f044290abf91a14a6d90e87487da160c2a3cbd0d465d7a78eb83a7", + "encrypted_data": "cc0f16524fd7f8bb0b1d8d40ad71709ef140174c76faa574cac401bb8992fef76c4d004aa485dd599ed1cf2715f57ff62da5aaec5d7b10d59b04d8a9d77e472b9b3ecc2179334e411be22fa4c02b467c7e" + }, + { + "blinded_node_id": "036861b366f284f0a11738ffbf7eda46241a8977592878fe3175ae1d1e4754eccf", + "encrypted_data": "0fa0a72cff3b64a3d6e1e4903cf8c8b0a17144aeb249dcb86561adee1f679ee8db3e561d9c43815fd4bcebf6f58c546da0cd8a9bf5cebd0d554802f6c0255e28e4a27343f761fe518cd897463187991105" + }, + { + "blinded_node_id": "021982a48086cb8984427d3727fe35a03d396b234f0701f5249daa12e8105c8dae", + "encrypted_data": "da1a7e5f7881219884beae6ae68971de73bab4c3055d9865b1afb60724a2e4d3f0489ad884f7f3f77149209f0df51efd6b276294a02e3949c7254fbc8b5cab58212d9a78983e1cf86fe218b30c4ca8f6d8" + } + ] + }, + "unblind": { + "comment": "This section contains test data for unblinding the route at each intermediate hop.", + "hops": [ + { + "alias": "Bob", + "node_privkey": "4242424242424242424242424242424242424242424242424242424242424242", + "ephemeral_pubkey": "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "blinded_privkey": "d12fec0332c3e9d224789a17ebd93595f37d37bd8ef8bd3d2e6ce50acb9e554f", + "decrypted_data": "011a0000000000000000000000000000000000000000000000000000020800000000000006c10a0800240000009627100c06000b69e505dc0e00fd023103123456", + "next_ephemeral_pubkey": "034e09f450a80c3d252b258aba0a61215bf60dda3b0dc78ffb0736ea1259dfd8a0" + }, + { + "alias": "Carol", + "node_privkey": "4343434343434343434343434343434343434343434343434343434343434343", + "ephemeral_pubkey": "034e09f450a80c3d252b258aba0a61215bf60dda3b0dc78ffb0736ea1259dfd8a0", + "blinded_privkey": "bfa697fbbc8bbc43ca076e6dd60d306038a32af216b9dc6fc4e59e5ae28823c1", + "decrypted_data": "020800000000000004510821031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f0a0800300000006401f40c06000b69c105dc0e00", + "next_ephemeral_pubkey": "03af5ccc91851cb294e3a364ce63347709a08cdffa58c672e9a5c587ddd1bbca60", + "next_ephemeral_pubkey_override": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f" + }, + { + "alias": "Dave", + "node_privkey": "4444444444444444444444444444444444444444444444444444444444444444", + "ephemeral_pubkey": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + "blinded_privkey": "cebc115c7fce4c295dc396dea6c79115b289b8ceeceea2ed61cf31428d88fc4e", + "decrypted_data": "01230000000000000000000000000000000000000000000000000000000000000000000000020800000000000002310a060090000000fa0c06000b699105dc0e00", + "next_ephemeral_pubkey": "03e09038ee76e50f444b19abf0a555e8697e035f62937168b80adf0931b31ce52a" + }, + { + "alias": "Eve", + "node_privkey": "4545454545454545454545454545454545454545454545454545454545454545", + "ephemeral_pubkey": "03e09038ee76e50f444b19abf0a555e8697e035f62937168b80adf0931b31ce52a", + "blinded_privkey": "ff4e07da8d92838bedd019ce532eb990ed73b574e54a67862a1df81b40c0d2af", + "decrypted_data": "011a00000000000000000000000000000000000000000000000000000604deadbeef0c06000b690105dc0e0f020000000000000000000000000000fdffff0206c1", + "next_ephemeral_pubkey": "038fc6859a402b96ce4998c537c823d6ab94d1598fca02c788ba5dd79fbae83589" + } + ] + } +} \ No newline at end of file diff --git a/proposals/route-blinding.md b/proposals/route-blinding.md new file mode 100644 index 000000000..86a82d4c1 --- /dev/null +++ b/proposals/route-blinding.md @@ -0,0 +1,614 @@ +# Route Blinding + +## Table of Contents + +* [Proposal](#proposal) + * [Introduction](#introduction) + * [Overview](#overview) + * [Notations](#notations) + * [Requirements](#requirements) + * [Encrypted data](#encrypted-data) + * [Creating a blinded route](#creating-a-blinded-route) + * [Sending to a blinded route](#sending-to-a-blinded-route) + * [Receiving from a blinded route](#receiving-from-a-blinded-route) + * [Blinded payments](#blinded-payments) +* [Attacks](#attacks) + * [Unblinding channels with payment probing](#unblinding-channels-with-payment-probing) + * [Unblinding nodes after restart](#unblinding-nodes-after-restart) +* [Tips and Tricks](#tips-and-tricks) + * [Recipient pays fees](#recipient-pays-fees) + * [Dummy hops](#dummy-hops) + * [Wallets and unannounced channels](#wallets-and-unannounced-channels) + * [Blinded route selection](#blinded-route-selection) + * [Blinded trampoline route](#blinded-trampoline-route) +* [FAQ](#faq) + * [Why not use rendezvous](#why-not-use-rendezvous) + * [Why not use HORNET](#why-not-use-hornet) + +## Proposal + +### Introduction + +Route blinding is a lightweight technique to provide recipient anonymity by blinding an arbitrary +amount of hops at the end of an onion path. It's more flexible than rendezvous routing because it +simply replaces the public keys of the nodes in the route with random public keys while letting +senders choose what data they put in the onion for each hop. Blinded routes are also reusable in +some cases (e.g. onion messages). + +The downside compared to rendezvous is that senders have more leeway to probe by changing various +variables, so the scheme needs to explicitly defend against probing attacks and may provide less +privacy against some classes of attacks. + +Some use-cases where route blinding is useful include: + +* Sender and recipient anonymity for onion messages +* Recipient anonymity for Bolt 12 offers +* Recipient anonymity when receiving payments +* Using unannounced channels in invoices without revealing them +* Forcing a payment to go through a specific set of intermediaries that can witness the payment + +### Overview + +At a high level, route blinding works by having the recipient choose an _introduction point_ and a +route to itself from that introduction point. The recipient then blinds each node and channel along +that route with ECDH. The recipient sends details about the blinded route and some cryptographic +material to the sender (via a Bolt 11 invoice or Bolt 12 offer), which lets the sender build an +onion with enough information to allow nodes in the blinded route to incrementally unblind the next +node in the route. + +This scheme requires all the nodes in the blinded route and the sender to activate support for the +feature. It needs a big enough share of the network to support it to provide meaningful privacy +guarantees. + +### Notations + +* A node `N(i)`'s `node_id` is defined as: `N(i) = k(i) * G` (`k(i)` is the node's private key). +* Blinded `node_id`s are defined as: `B(i) = b(i) * G` (`b(i)` is the blinding factor). +* Sphinx ephemeral public keys are defined as: `E(i) = e(i) * G`. + +### Requirements + +A node `N(r)` wants to provide a blinded route `N(0) -> N(1) -> ... -> N(r)` that must be used +to receive onions. + +* Intermediate nodes in the blinded route MUST NOT learn the `node_id` or `scid` of other + intermediate nodes except for their immediate predecessor or successor. +* Intermediate nodes in the blinded route MUST NOT learn their distance to the recipient `N(r)`. +* Senders MUST NOT learn the real `node_id` and `scid` of the blinded intermediate hops after the + introduction point `N(0)`. +* If `N(r)` creates multiple blinded routes to itself, senders MUST NOT be able to tell that these + routes lead to the same recipient (unless of course this information is leaked by higher layers + of the protocol, such as using the same `payment_hash` or being generated for the same offer). + +### Encrypted data + +Route blinding introduces a new TLV field to the onion `tlv_payload`: the `encrypted_data`. + +This field is used to carry data coming from the builder of the route that cannot be modified by +the sender. It needs to contain enough data to let intermediate nodes locate the next node in the +route (usually a `node_id` or `scid`), and may be extended with additional data in the future. It +uses ChaCha20-Poly1305 as AEAD scheme. + +1. type: 10 (`encrypted_data`) +2. data: + * [`...*byte`:`encrypted_data`] + +Once decrypted, the content of this encrypted payload is a TLV stream. + +### Creating a blinded route + +`N(r)` performs the following steps to create a blinded route: + +```text +Initialization: + + e(0) <- {0;1}^256 + E(0) = e(0) * G + +Blinding: + + For i = 0 to r: + ss(i) = H(e(i) * N(i)) = H(k(i) * E(i)) // shared secret known only by N(r) and N(i) + B(i) = HMAC256("blinded_node_id", ss(i)) * N(i) // Blinded node_id for N(i), private key known only by N(i) + rho(i) = HMAC256("rho", ss(i)) // Key used to encrypt payload for N(i) by N(r) + e(i+1) = H(E(i) || ss(i)) * e(i) // Ephemeral private key, only known by N(r) + E(i+1) = H(E(i) || ss(i)) * E(i) // NB: N(i) must not learn e(i) +``` + +Note that this is exactly the same construction as Sphinx, but at each hop we use the shared secret +to derive a blinded `node_id` for `N(i)` for which the private key will only be known by `N(i)`. + +The recipient then creates `encrypted_data(i)` by encrypting application-specific data with +ChaCha20-Poly1305 using the `rho(i)` key. + +To use the blinded route, senders need the following data: + +* The real `node_id` of the introduction point `N(0)` (to locate the beginning of the route) +* The list of blinded `node_id`s: `[B(1),...,B(r)]` +* The encrypted data for each node: `[encrypted_data(0),...,encrypted_data(r)]` +* The first blinding ephemeral key: `E(0)` + +### Sending to a blinded route + +The sender finds a route to the introduction point `N(0)`, and extends it with the blinded route. +It then creates an onion for that whole route, and includes `E(0)` and `encrypted_data(0)` in the +onion payload for `N(0)`. It includes `encrypted_data(i)` in the onion payload for `B(i)`. + +When `N(0)` receives the onion and decrypts it, it finds `E(0)` in the payload and is able to +compute the following: + +```text + ss(0) = H(k(0) * E(0)) + rho(0) = HMAC256("rho", ss(0)) + E(1) = H(E(0) || ss(0)) * E(0) +``` + +It uses `rho(0)` to decrypt the `encrypted_data(0)` and discovers that `B(1)` is actually `N(1)`. +It forwards the onion to `N(1)` and includes `E(1)` in a TLV field in the lightning message +(e.g. in the extension field of an `update_add_htlc` message). + +All the following intermediate nodes `N(i)` do the following steps: + +```text + E(i) <- extracted from the lightning message's fields + ss(i) = H(k(i) * E(i)) + b(i) = HMAC256("blinded_node_id", ss(i)) * k(i) + Use b(i) instead of k(i) to decrypt the incoming onion using sphinx + rho(i) = HMAC256("rho", ss(i)) + Use rho(i) to decrypt the `encrypted_data` inside the onion and discover the next node + E(i+1) = H(E(i) || ss(i)) * E(i) + Forward the onion to the next node and include E(i+1) in a TLV field in the message +``` + +### Receiving from a blinded route + +When `N(r)` receives the onion message and `E(r)`, they do the same unwrapping as intermediate +nodes. The difference is that the onion will be a final onion. + +`N(r)` must also validate that the blinded route was used in the context it was created for, and is +a route that they created. It's important to note than anyone can create valid blinded routes to +anyone else. Alice for example is able to create a blinded route `Bob -> Carol -> Dave`. In most +cases, Dave wants to ignore messages that come through routes that were created by someone else. + +The details of this validation step depends on the actual application using route blinding. For +example, when using a blinded route for payments, the recipient must verify that the route was +used in conjunction with the right `payment_hash`. It can do so by storing the `payment_preimage` +in the `encrypted_data` payload to itself and verifying it when receiving the payment: malicious +senders don't know the preimage beforehand, so they won't be able to create a satisfying route. + +Without this validation step, the recipient exposes itself to malicious probing, which could let +attackers deanonymize the route. + +### Blinded payments + +This section provides more details on how route blinding can be used for payments. + +In order to protect against malicious probing (detailed in the [Attacks](#attacks) section), it is +the recipient who chooses what payment relay parameters will be used inside the route (e.g. fees) +and encodes them in the `encrypted_data` payload for each blinded node. The sender will not set the +`amt_to_forward` and `outgoing_cltv_value` fields in the onion payloads for blinded intermediate +nodes: these nodes will instead follow the instructions found in their `encrypted_data`. + +The `encrypted_data` for each intermediate node will contain the following fields: + +* `short_channel_id`: outgoing channel that should be used to route the payment +* `fee_base_msat`: base fee that must be applied before relaying the payment +* `fee_proportional_millionths`: proportional fee that must be applied before relaying the payment +* `cltv_expiry_delta`: cltv expiry delta that must be applied before relaying the payment +* `max_cltv_expiry`: maximum expiry allowed for this payment +* `htlc_minimum_msat`: minimum htlc amount that should be accepted +* `allowed_features`: features related to payment relay that the sender is allowed to use + +The recipient must use values that provide a good enough anonymity set, by looking at nearby +channels and selecting values that would work for a large enough number of those channels. +Otherwise it could be easy for a malicious sender to figure out which channels are hidden inside +the blinded route if for example the selected fees are lower than most other candidates. + +The recipient also includes the `payment_preimage` (or another private unique identifier for the +payment) in the `path_id` field of the `encrypted_data` payload for itself: this will let the +recipient verify that the route is only used for that specific payment and was generated by them. + +If a node inside the blinded route receives a payment that doesn't use the parameters provided in +the `encrypted_data`, it must reject the payment and respond with an unparsable error onion. That +ensures the payer won't know which node failed and for what reason (otherwise that would provide +data that the payer could use to probe nodes inside the route). + +Note that we are also providing a `max_cltv_expiry` field: this ensures that the blinded route +expires after some time, restricting future probing attempts. + +If we assume that all nodes support `var_onion_option`, we don't need to include the +`allowed_features` field for now as there are no other features that affect payment relay and +could be used as a probing vector. However, future updates may add such features (e.g. PTLC +support), in which case the `allowed_features` field must not be empty. + +Let's go through an example to clarify those requirements. + +Alice creates an invoice with the following blinded route: `Carol -> Bob -> Alice`. +The channels along that route have the following settings: + +* `Carol -> Bob` + * `fee_base_msat`: 10 + * `fee_proportional_millionths`: 250 + * `cltv_expiry_delta`: 144 + * `htlc_minimum_msat`: 1 +* `Bob -> Alice` + * `fee_base_msat`: 50 + * `fee_proportional_millionths`: 100 + * `cltv_expiry_delta`: 48 + * `htlc_minimum_msat`: 1000 + +Alice chooses the following parameters for the blinded route, that satisfy the requirements of the +channels described above and adds a safety margin in case nodes update their relay parameters: + +* `fee_base_msat`: 100 +* `fee_proportional_millionths`: 500 +* `htlc_minimum_msat`: 1000 +* `cltv_expiry_delta`: 144 + +Alice uses the same values for both channels for simplicity's sake. Alice can now compute aggregate +values for the complete route (iteratively starting from the end of the route), using integer +arithmetric to compute `ceil(a/b)` as `(a+b-1)/b` (we round values up, otherwise the sender may +receive slightly less than intended): + +* `route_fee_base_msat(n+1) = (fee_base_msat(n+1) * 1000000 + route_fee_base_msat(n) * (1000000 + fee_proportional_millionths(n+1)) + 1000000 - 1) / 1000000` +* `route_fee_proportional_millionths(n+1) = ((route_fee_proportional_millionths(n) + fee_proportional_millionths(n+1)) * 1000000 + route_fee_proportional_millionths(n) * fee_proportional_millionths(n+1) + 1000000 - 1) / 1000000` + +This yields the following values: + +* `route_fee_base_msat`: 201 +* `route_fee_proportional_millionths`: 1001 +* `route_cltv_expiry_delta`: 288 + +Let's assume the current block height is 1000. Alice wants the route to be used in the next 200 +blocks, so she sets `max_cltv_expiry = 1200` and adds `cltv_expiry_delta` for each hop. Alice then +transmits the following information to the sender (most likely via an invoice): + +* Blinded route: `[N(carol), B(bob), B(alice)]` +* First blinding ephemeral key: `E(carol)` +* Aggregated route relay parameters and constraints: + * `fee_base_msat`: 201 + * `fee_proportional_millionths`: 1001 + * `htlc_minimum_msat`: 1000 + * `cltv_expiry_delta`: 288 + * `max_cltv_expiry`: 1200 + * `allowed_features`: empty +* Encrypted data for blinded nodes: + * `encrypted_payload(alice)`: + * `path_id`: `payment_preimage` + * `max_cltv_expiry`: 1200 + * `encrypted_payload(bob)`: + * `outgoing_channel_id`: `scid_bob_alice` + * `fee_base_msat`: 100 + * `fee_proportional_millionths`: 500 + * `htlc_minimum_msat`: 1000 + * `max_cltv_expiry`: 1344 + * `encrypted_payload(carol)`: + * `outgoing_channel_id`: `scid_carol_bob` + * `fee_base_msat`: 100 + * `fee_proportional_millionths`: 500 + * `htlc_minimum_msat`: 1000 + * `max_cltv_expiry`: 1488 + +Note that the introduction point (Carol) uses the real `node_id`, not the blinded one, because the +sender needs to be able to locate this introduction point and find a route to it. The sender will +send the first blinding ephemeral key `E(carol)` in the onion `hop_payload` for Carol, which will +allow Carol to compute the blinding shared secret and correctly forward. We put this blinding +ephemeral key in the onion instead of using a tlv in `update_add_htlc` because intermediate nodes +added before the blinded route may not support route blinding and wouldn't know how to relay it. + +Erin wants to send 100 000 msat to this blinded route. +She can reach Carol via Dave: `Erin -> Dave -> Carol`, where the channel between Dave and Carol uses +the following relay parameters: + +* `fee_base_msat`: 10 +* `fee_proportional_millionths`: 100 +* `cltv_expiry_delta`: 24 + +Erin uses the aggregated route relay parameters to compute how much should be sent to Carol: + +* `amount = 100000 + 201 + (1001 * 100000 + 1000000 - 1) / 1000000 = 100302 msat` + +Erin chooses a final expiry of 1100, which is below Alice's `max_cltv_expiry`, and computes the +expiry that should be sent to Carol: + +* `expiry = 1100 + 288 = 1388` + +When a node in the blinded route receives an htlc, the onion will not contain the `amt_to_forward` +or `outgoing_cltv_value`. They will have to compute them based on the fields contained in their +`encrypted_data` (`fee_base_msat`, `fee_proportional_millionths` and `cltv_expiry_delta`). + +For example, here is how Carol will compute the values for the htlc she relays to Bob: + +* `amount = ((100302 - fee_base_msat) * 1000000 + 1000000 + fee_proportional_millionths - 1) / (1000000 + fee_proportional_millionths) = 100152 msat` +* `expiry = 1388 - cltv_expiry_delta = 1244` + +And here is how Bob computes the values for the htlc he relays to Alice: + +* `amount = ((100152 - fee_base_msat) * 1000000 + 1000000 + fee_proportional_millionths - 1) / (1000000 + fee_proportional_millionths) = 100002 msat` +* `expiry = 1244 - cltv_expiry_delta = 1100` + +Note that as the rounding errors aggregate, the recipient will receive slightly more than what was +expected. The sender includes `amt_to_forward` in the onion payload for the recipient to let them +verify that the received amount is (slightly) greater than what the sender intended to send (which +protects against intermediate nodes that would try to relay a lower amount). + +The messages exchanged will contain the following values: + +```text + Erin Dave Carol Bob Alice + | update_add_htlc | update_add_htlc | update_add_htlc | update_add_htlc | + | +--------------------------------+ | +------------------------------------------+ | +------------------------------------------+ | +--------------------------------+ | + | | amount: 100322 msat | | | amount: 100302 msat | | | amount: 100152 msat | | | amount: 100002 msat | | + | | expiry: 1412 | | | expiry: 1388 | | | expiry: 1244 | | | expiry: 1100 | | + | | onion_routing_packet: | | | onion_routing_packet: | | | onion_routing_packet: | | | onion_routing_packet: | | + | | +----------------------------+ | | | +--------------------------------------+ | | | +--------------------------------------+ | | | +----------------------------+ | | + | --> | | amount_fwd: 100302 msat | | --> | --> | | blinding_eph_key: E(carol) | | --> | --> | | encrypted_data: | | --> | --> | | amount_fwd: 100000 msat | | --> | + | | | outgoing_expiry: 1388 | | | | | encrypted_data: | | | | | +----------------------------------+ | | | | | outgoing_expiry: 1100 | | | + | | | scid: scid_dave_to_carol | | | | | +----------------------------------+ | | | | | | scid: scid_bob_to_alice | | | | | | encrypted_data: | | | + | | +----------------------------+ | | | | | scid: scid_carol_to_bob | | | | | | | fee_base_msat: 100 | | | | | | +-----------------------+ | | | + | | | blinding_eph_key: E(carol) | | | | | | fee_base_msat: 100 | | | | | | | fee_proportional_millionths: 500 | | | | | | | path_id: preimage | | | | + | | | encrypted_data(carol) | | | | | | fee_proportional_millionths: 500 | | | | | | | htlc_minimum_msat: 1000 | | | | | | | max_cltv_expiry: 1200 | | | | + | | +----------------------------+ | | | | | htlc_minimum_msat: 1000 | | | | | | | cltv_expiry_delta: 144 | | | | | | +-----------------------+ | | | + | | | encrypted_data(bob) | | | | | | cltv_expiry_delta: 144 | | | | | | | max_cltv_expiry: 1344 | | | | | +----------------------------+ | | + | | +----------------------------+ | | | | | max_cltv_expiry: 1488 | | | | | | +----------------------------------+ | | | | tlv_extension | | + | | | amount_fwd: 100000 msat | | | | | +----------------------------------+ | | | | +--------------------------------------+ | | | +----------------------------+ | | + | | | outgoing_expiry: 1100 | | | | +--------------------------------------+ | | | | amount_fwd: 100000 msat | | | | | blinding_eph_key: E(alice) | | | + | | | encrypted_data(alice) | | | | | encrypted_data(bob) | | | | | outgoing_expiry: 1100 | | | | +----------------------------+ | | + | | +----------------------------+ | | | +--------------------------------------+ | | | | encrypted_data(alice) | | | +--------------------------------+ | + | +--------------------------------+ | | | amount_fwd: 100000 msat | | | | +--------------------------------------+ | | | + | | | | outgoing_expiry: 1100 | | | | tlv_extension | | | + | | | | encrypted_data(alice) | | | | +--------------------------------------+ | | | + | | | +--------------------------------------+ | | | | blinding_eph_key: E(bob) | | | | + | | +------------------------------------------+ | | +--------------------------------------+ | | | + | | | +------------------------------------------+ | | + | | | | | +``` + +Note that all onion payloads are described in each `update_add_htlc` for clarity, but only the +first one can be decrypted by the intermediate node that receives the message (standard Bolt 4 +onion encryption). + +## Attacks + +### Unblinding channels with payment probing + +Recipients must be careful when using route blinding for payments to avoid letting attackers +guess which nodes are hidden inside of the route. Let's walk through an attack to understand +why. + +Let's assume that our routing graph looks like this: + +```text + +-------+ +-------+ + | X | | X | + +-------+ +-------+ + | | + | | ++-------+ +-------+ +-------+ +-------+ +| X |------| Carol |------| Bob |------| Alice | ++-------+ +-------+ +-------+ +-------+ + | | + | | + +-------+ +-------+ + | X | | X | + +-------+ +-------+ +``` + +Alice creates a blinded route `Carol -> Bob -> Alice`. +Alice has chosen what fee settings will be used inside the blinded route. +Let's assume she has chosen `fee_base_msat = 10` and `fee_proportional_millionths = 100`. + +The attacker knows that the recipient is at most two hops away from Carol. Instead of making the +payment, the attacker watches for new `channel_update`s for every channel in a two-hops radius +around Carol. At some point, the attacker sees a `channel_update` for the channel `Bob -> Alice` +that sets `fee_proportional_millionths = 150`, which exceeds what Alice has chosen for the blinded +route. The attacker then tries to make the payment. + +When Bob receives the payment, the fees are below its current settings, so it should reject it. +The attacker would then receive a failure, and be able to infer that it's very likely that Alice +is the final recipient. + +If the attackers are able to frequently request invoices from the recipient (e.g. from a Bolt 12 +offer), they don't even have to attempt the payment to detect this. They can simply periodically +request invoices from the recipient and detect when the recipient raises the fees or cltv of the +blinded route, and match that with recent `channel_update`s that they received. + +Similarly, feature bits that apply to payment relaying behavior can be used to fingerprint nodes +inside the blinded route: this is why `allowed_features` are committed inside the `encrypted_data`. + +If nodes across the network use different values for `htlc_minimum_msat`, it can also be used to +fingerprint nodes: that's why it is also committed inside the `encrypted_data`. + +This type of attack is the reason why all parameters that affect payment relaying behavior (fees, +cltv, features, etc) are chosen by the recipient. The recipient should add a large enough margin +to the current values actually used by nodes inside the route to protect against future raises. +This is also why blinded routes used for payments have a `max_cltv_expiry` set by the recipient, +even though that doesn't fully address the issue if the attackers are able to frequently request +new blinded routes. + +Altruistic relaying nodes inside a blinded route could choose to relay payments with fees below +their current settings, which would break this heuristic: however their economic incentive is to +reject them, so we cannot rely on them to protect recipient privacy. + +Similarly, we mandate relaying nodes to only accept payments using exactly the fees provided in +the `encrypted_data` payload. Otherwise, when observing a `channel_update` that raises a specific +channel's fees, the attackers could try to use these new fees in a payment attempt: if the payment +goes through, they would have even more confidence about the channel used in the blinded route. +The incentives for relaying nodes aren't great, because we're asking them to reject payments that +give them the right amount of fees to protect recipient privacy. + +### Unblinding nodes after restart + +The attacks described in the previous section only applied to scenarios that use route blinding +for payments. However, a variation of the same technique can be used for any scenario relying on +route blinding to relay messages. + +If attackers suspect that a given node `N` may be part of a blinded route, they can wait for that +node to go offline, and try using the blinded route while the node is offline. If the blinded +route fails, it's likely that this node was indeed part of the blinded route. By repeating this +sampling regularly, attackers can increase the confidence in their unblinding. + +To address this, recipients should choose nodes with high uptime for their blinded routes and +periodically refresh them. + +## Tips and Tricks + +### Recipient pays fees + +It may be unfair to make payers pay more fees to accomodate the recipient's wish for anonymity. +It should instead be the recipient that pays the fees of the blinded hops (and the payer pays the +fees to reach the introduction point). + +If a merchant is selling an item for `N` satoshis, it should create an invoice for `N-f` satoshis, +where `f` is the fee of the blinded part of the route. + +### Dummy hops + +The sender knows an upper bound on the distance between the recipient and `N(0)`. If the recipient +is close to `N(0)`, this might not be ideal. In such cases, the recipient may add any number of +dummy hops at the end of the blinded route by using `N(j) = N(r)`. The sender will not be able to +distinguish those from normal blinded hops. + +NB: + +* the recipient needs to fully validate each dummy hop's onion payload to detect tampering (and + must ensure that these hops have been used and not truncated) +* the recipient must use padding to ensure all `encrypted_data` payloads have the same length, + otherwise the payer will be able to guess which hop is actually the recipient + +### Wallets and unannounced channels + +Route blinding is particularly useful for wallets that are connected to nodes via unannounced +channels. Such wallets could use a single blinded hop, which effectively hides their `node_id` +and `scid` from the sender. It obviously reveals to the blinded node that the next node is the +final recipient, but a wallet that's not online all the time with a stable IP will never be able +to hide that information from the nodes it connects to anyway (even with rendezvous). + +### Blinded route selection + +There is a wide array of strategies that a recipient may use when creating a blinded route to +ensure good privacy while maintaining good payment reliability. We will walk through some of +these strategies below. Note that these are only examples, implementations should find strategies +that suit their users' needs. + +If the recipient is not a public node and has a small number of peers, then it's very simple: +they can include one path per peer. A mobile wallet's topology for example will typically look +like this: + +```text + +-------+ +-------+ + +----------| Carol | | X | + | +-------+ +-------+ + | | | + | | | ++-------+ +-------+ +-------+ +-------+ +| Alice |------| Bob |------| X |------| X | ++-------+ +-------+ +-------+ +-------+ + | | + | | + | +-------+ + +-------------------------| Dave | + +-------+ +``` + +Alice could provide a blinded route containing one blinded path per peer and dummy hops: + +* Bob -> Blinded(Alice) -> Blinded(Alice) -> Blinded(Alice) +* Carol -> Blinded(Alice) -> Blinded(Alice) -> Blinded(Alice) +* Dave -> Blinded(Alice) -> Blinded(Alice) -> Blinded(Alice) + +Alice is able to use all of her inbound liquidity while benefiting from a large anonymity set: she +could be any node at most three hops away from Bob, Carol and Dave. + +If the recipient is a public node, its strategy will be different. It should use introduction nodes +that have many peers to obtain a good anonymity set. Let's assume that Alice's neighbourhood has +the following topology: + +```text ++-------+ +-------+ +| X | | X | ++-------+ +-------+ + | | + | | ++-------+ +-------+ +-------+ +| N1 |------| N2 |------| X | ++-------+ +-------+ +-------+ + | | | + | | | ++-------+ +-------+ +-------+ +-------+ +| Alice |------| N3 |------| N4 |------| X | ++-------+ +-------+ +-------+ +-------+ +``` + +Alice can run a BFS of depth 2 to identify that N2 and N4 are good introduction nodes that provide +a large anonymity set. She can then provide the following blinded paths: + +* N2 -> Blinded(N1) -> Blinded(Alice) -> Blinded(Alice) +* N4 -> Blinded(N3) -> Blinded(Alice) -> Blinded(Alice) + +Alice should analyze the payment relay parameters of all channels in her anonymity set and choose +fees/cltv that would work for a large enough subset of them. + +Note that Alice chose non-overlapping paths: otherwise these paths may not have enough liquidity +to relay the payment she expects to receive, unless the path capacity is much larger than the +expected payment. + +When the receiver expects to receive large payments, liquidity may become an issue if it is +scattered among too many peers. The receiver may be forced to use introduction nodes that are +direct peers to ensure that enough liquidity is available (in which case it's particularly useful +to include dummy hops in the blinded paths). + +### Blinded trampoline route + +Route blinding can also be used with trampoline very easily. Instead of providing the +`outgoing_channel_id` in `encrypted_data`, we simply need to provide the `outgoing_node_id`. + +Each trampoline node can then decrypt the `node_id` of the next node and compute `E(i)` for the +next trampoline node. That `E(i)` can then be sent in the outer onion payload instead of using the +lightning message's fields, which is even cleaner and doesn't require nodes between trampoline +nodes to understand route blinding. + +Using a blinded trampoline route is a good solution for public nodes that have many peers and +run into liquidity issues affecting payment reliability. Such recipients can choose trampoline +nodes that will be able to find many paths towards them: + +```text + +-------+ +-------+ + +----------| X |--------+ +--------| X |----------+ + | +-------+ | | +-------+ | + | | | | + | | | | ++-------+ +-------+ +-------+ +-------+ +-------+ +| T1 |------| X |------| Alice |------| X |------| T2 | ++-------+ +-------+ +-------+ +-------+ +-------+ + | | | | + | | | | + | +-------+ | | +-------+ | + +----------| X |--------+ +--------| X |----------+ + +-------+ +-------+ +``` + +Alice can provide the following blinded trampoline paths: + +* T1 -> Blinded(Alice) +* T2 -> Blinded(Alice) + +T1 and T2 will be able to find many paths towards Alice and retry whenever some paths fail, +working around the potential liquidity constraints. + +## FAQ + +### Why not use rendezvous + +While rendezvous is more private, it's also less flexible: senders cannot add data to the partial +onion nor reuse it. When used for payments, the amount must be fixed ahead of time in the partial +onion, which doesn't combine well with multi-part payments or temporary liquidity issues. + +Route blinding lets senders choose most of the data they put in the onion payloads, which makes +it much more flexible, at the expense of introducing more probing surface for attackers. + +### Why not use HORNET + +HORNET requires a slow session setup before it can provide useful speedups. In cases where you +expect to send a single message per session (which is the case for payments and onion messages), +HORNET actually performs worse than Sphinx in latency, bandwidth and privacy.