Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trampoline onion format (Feature 56/57) #836

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 177 additions & 6 deletions 04-onion-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ A node:
* [Payload Format](#payload-format)
* [Basic Multi-Part Payments](#basic-multi-part-payments)
* [Route Blinding](#route-blinding)
* [Trampoline Payments](#trampoline-payments)
* [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)
Expand Down Expand Up @@ -207,12 +208,32 @@ This is formatted according to the Type-Length-Value format defined in [BOLT #1]
1. type: 12 (`current_blinding_point`)
2. data:
* [`point`:`blinding`]
1. type: 14 (`outgoing_node_id`)
2. data:
* [`point`:`outgoing_node_id`]
1. type: 16 (`payment_metadata`)
2. data:
* [`...*byte`:`payment_metadata`]
1. type: 18 (`total_amount_msat`)
2. data:
* [`tu64`:`total_msat`]
1. type: 20 (`trampoline_onion_packet`)
2. data:
* [`byte`:`version`]
* [`point`:`public_key`]
* [`...*byte`:`hop_payloads`]
* [`32*byte`:`hmac`]
1. type: 21 (`recipient_features`)
2. data:
* [`...*byte`:`features`]
1. type: 22 (`recipient_blinded_paths`)
2. data:
* [`...*payment_blinded_path`:`paths`]

1. subtype: `payment_blinded_path`
2. data:
* [`path`:`blinded_path`]
* [`blinded_payinfo`:`payment_info`]

`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.
Expand Down Expand Up @@ -264,6 +285,7 @@ The writer of the TLV `payload`:
- 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`.
- MAY include `trampoline_onion_packet`.
- The value set for `outgoing_cltv_value`:
- MUST use the current block height as a baseline value.
- if a [random offset](07-routing-gossip.md#recommendations-for-routing) was added to improve privacy:
Expand All @@ -272,10 +294,10 @@ The writer of the TLV `payload`:
- 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 include `short_channel_id` or `outgoing_node_id`
- MUST NOT include `payment_data`
- For the final node:
- MUST NOT include `short_channel_id`
- MUST NOT include `short_channel_id` nor `outgoing_node_id`
- if the recipient provided `payment_secret`:
- MUST include `payment_data`
- MUST set `payment_secret` to the one provided
Expand Down Expand Up @@ -421,7 +443,8 @@ constrained in which paths they can take when retrying payments along specific
paths. However, no individual HTLC may be for less than the difference between
the total paid and `total_msat`.

The restriction on sending an HTLC once the set is over the agreed total prevents the preimage being released before all
The restriction on sending an HTLC once the set is over the agreed
total prevents the preimage being released before all
the partial payments have arrived: that would allow any intermediate
node to immediately claim any outstanding partial payments.

Expand Down Expand Up @@ -594,9 +617,118 @@ 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).

### Trampoline Payments

Trampoline payments allow nodes with an incomplete view of the network to
delegate the construction of parts of the route to trampoline nodes.

The origin node only needs to select a set of trampoline nodes and to know a
route to the first trampoline node. Each trampoline node is responsible for
finding its own route to the next trampoline node. The last trampoline node
must be the final recipient, or it must receive a list of blinded paths to
which it should relay the payment.

The `trampoline_onion_packet` has a variable size to allow implementations to
choose their own trade-off between flexibility and privacy. It's recommended to
add trailing filler data to the `trampoline_onion_packet` when using a small
number of hops. It uses the same onion construction as the `onion_packet` and
is embedded inside an `onion_packet`.

Trampoline nodes are free to use as many hops as they want between themselves
as long as they are able to create a route that satisfies the `cltv` and `fees`
requirements contained in the onion.

#### Requirements

A sending node:

- MUST ensure that each hop in the `trampoline_onion_packet` supports `trampoline_routing`.
- MUST encrypt the `trampoline_onion_packet` with the same construction as `onion_packet`.
- MAY add trailing filler data similar to what is done in the `onion_packet`.
- MUST use a different `session_key` for the `trampoline_onion_packet` and the `onion_packet`.
- MUST include the `trampoline_onion_packet` tlv in the _last_ hop's payload of the `onion_packet`.
- MUST generate a random `payment_secret` to use for the `onion_packet`.
- When paying a Bolt 11 invoice:
- If the invoice doesn't support the `trampoline_routing` feature:
- MUST NOT use trampoline routing to pay that invoice.
- Otherwise:
- MUST include the invoice's `payment_secret` in the _last_ hop's payload of the `trampoline_onion_packet`.
- When paying a Bolt 12 invoice:
- MUST use a single trampoline hop.
- SHOULD include the `trampoline_routing` feature in the `invoice_request`.
- If the Bolt 12 invoice supports the `trampoline_routing` feature:
- In the _last_ hop's payload of the `trampoline_onion_packet` (for the final recipient):
- MUST include `amt_to_forward` with the amount that the recipient should receive.
- MUST include `outgoing_cltv_value` with the minimum expiry that the recipient should receive.
- MAY include `total_amount_msat` if the payment is split across multiple `trampoline_onion_packet`s.
- MAY include additional tlv fields.
- In the _next-to-last_ hop's payload of the `trampoline_onion_packet` (for the trampoline node):
- MUST include `amt_to_forward` with the amount that should be forwarded to the recipient.
- MUST include `outgoing_cltv_value` with the minimum expiry that should be received by the recipient.
- When encrypting the `trampoline_onion_packet`:
- When creating the onion packet for the _final_ recipient:
- MUST derive an `invreq_ss` as `ECDH(invoice_request.payer_privkey, invoice_node_id)`.
- MUST use $`SHA256(\text{"blinded\_trampoline\_payment"} || payment\_hash || invreq\_ss)`$ as associated data for the packet's HMAC.
- Otherwise:
- MUST NOT include a payload for the final recipient in the `trampoline_onion_packet`.
- In the _last_ hop's payload of the `trampoline_onion_packet` (for the trampoline node):
- MUST include `amt_to_forward` with the amount that should be forwarded to the recipient.
- MUST include `outgoing_cltv_value` with the minimum expiry that should be received by the recipient.
- In the _last_ hop's payload of the outer `onion_packet` (for the trampoline node):
- MUST include blinded paths from the invoice in `recipient_blinded_paths`.
- MAY include features supported by the recipient in `recipient_features`.
- If the invoice contains too many blinded paths:
- MUST include a subset of those paths without overflowing the `onion_packet`.

When processing a `trampoline_onion_packet`, a receiving node:

- If it doesn't support `trampoline_routing`:
- MUST report a route failure to the origin node.
- Otherwise, if it supports `trampoline_routing`:
- MUST process the `trampoline_onion_packet` as an `onion_packet`.
- If the incoming payment is a blinded payment matching an invoice it created:
- MUST derive an `invreq_ss` as `ECDH(invoice_privkey, invoice_request.payer_id)`.
- MUST use $`SHA256(\text{"blinded\_trampoline\_payment"} || payment\_hash || invreq\_ss)`$ as associated data for the packet's HMAC.
- If the `trampoline_routing` feature was set in the invoice:
- If the `hop_payload` does NOT include a `trampoline_onion_packet`:
- MUST fail the payment.
- If the incoming payment is a multi-part payment:
- MUST wait to receive all the payment parts before forwarding.
- MUST fail the HTLC if dictated by the requirements under [Failure Messages](#failure-messages).
- If the `hop_payload` from the `onion_packet` contains `recipient_blinded_paths`:
- MUST use those blinded paths to compute routes to the final recipient.
- If it is not the final hop of the `trampoline_onion_packet`:
- MUST include the peeled `trampoline_onion_packet` in the _last_ hop's payload of the outgoing `onion_packet`s.
- Otherwise:
- MUST compute a route to the next trampoline node.
- MUST include the peeled `trampoline_onion_packet` in the `hop_payload` for the next trampoline node.
- If it uses a multi-part payment to forward to the next trampoline node:
- MUST generate a new `payment_secret` to use in the outer onion.

#### Rationale

When the recipient is using using Bolt 12, its identity is protected by
blinded paths: we thus don't need to use multiple trampoline nodes to
protect the recipient's privacy. The payer simply provides the blinded
paths directly to its trampoline node, who will relay the payment through
those blinded paths. Blinded paths are included in the _outer_ onion, not
in the _trampoline_ onion, because it would otherwise unnecessarily use a
lot of space in the outgoing onion from the trampoline node.

When the recipient is using trampoline, the sender may include a payload
for the recipient in the trampoline onion, but the trampoline node could
replace it with a trampoline onion they created: to avoid that, we use a
shared secret based on the `invoice_request`'s `payer_id` when we encrypt
that payload, which guarantees that the node that created the trampoline
onion was the node that sent `invoice_request`.

# 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.
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.

When using trampoline routing, the next hop is not necessarily a direct peer,
but otherwise it is.

## Non-strict Forwarding

Expand All @@ -615,7 +747,7 @@ sent across.

Nodes implementing non-strict forwarding are able to make real-time assessments
of channel bandwidths with a particular peer, and use the channel that is
locally-optimal.
locally-optimal.

For example, if the channel specified by `short_channel_id` connecting A and B
does not have enough bandwidth at forwarding time, then A is able use a
Expand Down Expand Up @@ -657,8 +789,10 @@ This allows the final node to check these values and return errors if needed,
but it also eliminates the possibility of probing attacks by the second-to-last
node. Such attacks could, otherwise, attempt to discover if the receiving peer is the
last one by re-sending HTLCs with different amounts/expiries.

The final node will extract its onion payload from the HTLC it has received and
compare its values against those of the HTLC. See the
compare its values against those of the HTLC. When using trampoline payments,
the final node will extract these from the trampoline onion payload. See the
[Returning Errors](#returning-errors) section below for more details.

If not for the above, since it need not forward payments, the final node could
Expand Down Expand Up @@ -1034,6 +1168,21 @@ key, and computes the HMAC, using each hop's `um` key.
The origin node can detect the sender of the error message by matching the
`hmac` field with the computed HMAC.

For trampoline payments, the flow is the same. Intermediate trampoline nodes
first decrypt the downstream error using the `ammag` and `um` keys for their
forward path. If the error comes from an intermediate node _before_ the next
trampoline node, they may replace it with their own error for the origin node,
otherwise they must encrypt on top of the next trampoline node's error.

Intermediate trampoline hops apply the obfuscation step twice: first with the
`ammag` key derived from their trampoline shared secret, then with the `ammag`
key derived from their outer onion shared secret.

The origin node first iteratively decrypts the error message using the keys
derived from the outer onion's shared secrets. If the result does not match
the `hmac` field, it then continues decrypting using the keys derived from
the trampoline onion's shared secrets.

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.
Expand Down Expand Up @@ -1262,6 +1411,28 @@ reasonable time.

An error occurred within the blinded path.

1. type: NODE|25 (`temporary_trampoline_failure`)

The trampoline node was unable to relay the payment to the next trampoline
node, but may be able to handle it, or others, later.
This error usually indicates that routes were found but failed because of
temporary failures at intermediate hops.

1. type: NODE|26 (`trampoline_fee_or_expiry_insufficient`)
2. data:
* [`u32`:`fee_base_msat`]
* [`u32`:`fee_proportional_millionths`]
* [`u16`:`cltv_expiry_delta`]

The fee amount or cltv value was below that required by the trampoline node to
forward to the next trampoline node, but there are routes available if the
sender retries with the fees and cltv provided in the error data.

1. type: PERM|27 (`unknown_next_trampoline`)

The trampoline onion specified an `outgoing_node_id` that cannot be reached
from the processing node.

### Requirements

An _erring node_:
Expand Down
2 changes: 2 additions & 0 deletions 09-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The Context column decodes as follows:
| 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] |
| 56/57 | `trampoline_routing` | This node supports trampoline routing | IN9 | `basic_mpp` | [BOLT #4](bolt04-trampoline) |
t-bast marked this conversation as resolved.
Show resolved Hide resolved

## Definitions

Expand Down Expand Up @@ -109,4 +110,5 @@ This work is licensed under a [Creative Commons Attribution 4.0 International Li
[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
[bolt04-trampoline]: 04-onion-routing.md#trampoline-payments
[ml-sighash-single-harmful]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-September/002796.html
Loading