Skip to content

Commit

Permalink
Bolt 4: add blinded payments
Browse files Browse the repository at this point in the history
Add specification requirements for using route blinding to make payments
while preserving recipient anonymity. Implementers must ensure they
understand all those requirements, there are subtle attacks that could let
malicious senders deanonymize the route if incompletely implemented.
  • Loading branch information
t-bast committed Apr 11, 2022
1 parent 2fe871d commit 9ca59ac
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 19 deletions.
10 changes: 10 additions & 0 deletions 02-peer-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,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:
Expand Down Expand Up @@ -962,6 +968,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.
Expand All @@ -986,6 +994,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.
Expand Down
116 changes: 97 additions & 19 deletions 04-onion-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,39 +264,78 @@ It is formatted according to the Type-Length-Value format defined in [BOLT #1](0
2. data:
* [`32*byte`:`payment_secret`]
* [`tu64`:`total_msat`]
1. type: 10 (`encrypted_recipient_data`)
2. data:
* [`...*byte`:`encrypted_data`]
1. type: 12 (`blinding_point`)
2. data:
* [`point`:`blinding`]
1. type: 16 (`payment_metadata`)
2. data:
* [`...*byte`:`payment_metadata`]

### Requirements

The writer:

- Unless `node_announcement`, `init` message or the [BOLT #11](11-payment-encoding.md#tagged-fields) offers feature `var_onion_optin`:
- MUST use the legacy payload format instead.
- For every node:
- For every node inside a blinded route:
- MUST include the `encrypted_data` provided by the recipient
- For the first node in the blinded route:
- MUST include the `blinding_point` provided by the recipient
- If it is the final node:
- MUST include `amt_to_forward` and `outgoing_cltv_value`.
- Otherwise:
- MUST NOT include `amt_to_forward` and `outgoing_cltv_value`.
- 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 the final node:
- MUST treat `total_msat` as if it were equal to `amt_to_forward` if it
is not present.

- If `blinding_point` is set (either in the payload or the outer message):
- MUST return an error if it is set in both the payload and the outer message
- MUST return an error if `encrypted_recipient_data` is not present.
- MUST return an error if the expiry is greater than `encrypted_recipient_data.payment_constraints.max_cltv_expiry`.
- MUST return an error if the amount is below `encrypted_recipient_data.payment_constraints.htlc_minimum_msat`.
- MUST return an error if the payment uses a feature not included in `encrypted_recipient_data.payment_constraints.allowed_features`.
- If it not the final node:
- MUST return an error if `encrypted_recipient_data` does not contain `short_channel_id` or `next_node_id`.
- MUST return an error if `encrypted_recipient_data` does not contain `payment_relay`.
- If `encrypted_recipient_data.payment_relay` does not satisfy its current settings:
- MAY return an error.
- Otherwise:
- MUST use values from `encrypted_recipient_data.payment_relay` to relay the payment.
- If it is the final node:
- MUST return an error if the `path_id` in `encrypted_recipient_data` does not match the one it created.
- MUST return an error if `amt_to_forward` or `outgoing_cltv_value` are not present.
- MUST return an error if `amt_to_forward` is below what it expects for the payment.
- SHOULD add a random delay before returning errors.
- Otherwise (it is not part of a blinded route):
- MUST return an error if `amt_to_forward` or `outgoing_cltv_value` are not present.
- MUST return an error if `encrypted_recipient_data` is present.
- If it is the final node:
- MUST treat `total_msat` as if it were equal to `amt_to_forward` if it is not present.

The requirements for the contents of these fields are specified [above](#legacy-hop_data-payload-format)
and [below](#basic-multi-part-payments).

The requirements for the fields related to route blinding
(`encrypted_recipient_data` and `blinding_point`) are also specified
[below](#route-blinding).

### Basic Multi-Part Payments

An HTLC may be part of a larger "multi-part" payment: such
Expand Down Expand Up @@ -413,6 +452,16 @@ may contain the following TLV fields:
1. type: 8 (`next_blinding_override`)
2. data:
* [`point`:`blinding`]
1. type: 10 (`payment_relay`)
2. data:
* [`u32`:`fee_base_msat`]
* [`u32`:`fee_proportional_millionths`]
* [`u16`:`cltv_expiry_delta`]
1. type: 12 (`payment_constraints`)
2. data:
* [`u32`:`max_cltv_expiry`]
* [`u64`:`htlc_minimum_msat`]
* [`...*byte`:`allowed_features`]

#### Requirements

Expand All @@ -436,6 +485,14 @@ A recipient N(r) creating a blinded route `N(0) -> N(1) -> ... -> N(r)` to itsel
- MUST communicate the blinded node IDs `B(i)` and `encrypted_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
- If the blinded route will be used for payments:
- MUST set `short_channel_id` and `payment_relay` in the `encrypted_data` for intermediate nodes
- MUST NOT set `path_id` in the `encrypted_data` for intermediate nodes
- MUST compute the total fees and cltv delta of the route and communicate them to the sender
- If the blinded route will be used for messages:
- MUST set `next_node_id` in the `encrypted_data` for intermediate nodes
- MUST NOT set `payment_relay` or `payment_constraints` in the `encrypted_data` payloads
- MUST NOT set `path_id` in the `encrypted_data` for intermediate nodes

The sender:

Expand Down Expand Up @@ -519,11 +576,28 @@ 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 final recipient receives an invalid message from a blinded route,
it should add a random delay before returning an error (if it returns one).
Invalid messages 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.

When route blinding is used for payments, nodes inside the blinded route must
not return standard onion errors, because they would provide information to the
sender that could help them unblind the identity of the blinded nodes. Also,
instead of forwarding errors, nodes should replace them with garbage, in case
a downstream node was buggy and returned a valid onion error.

# 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.
Expand Down Expand Up @@ -971,11 +1045,15 @@ channel.
### Requirements

The _erring node_:

- SHOULD set `pad` such that the `failure_len` plus `pad_len` is equal to 256.
- Note: this value is 118 bytes longer than the longest currently-defined
message.
- Note: this value is 118 bytes longer than the longest currently-defined message.
- If it is part of a blinded route:
- MUST return random bytes instead of a valid onion error.
- SHOULD replace downstream errors by random bytes before forwarding them upstream.

The _origin node_:

- once the return message has been decrypted:
- SHOULD store a copy of the message.
- SHOULD continue decrypting, until the loop has been repeated 20 times.
Expand Down
Loading

0 comments on commit 9ca59ac

Please sign in to comment.