Skip to content

Trampoline onion format (Feature 56/57) - #836

Open
t-bast wants to merge 9 commits into
masterfrom
trampoline-onion
Open

Trampoline onion format (Feature 56/57)#836
t-bast wants to merge 9 commits into
masterfrom
trampoline-onion

Conversation

@t-bast

@t-bast t-bast commented Jan 25, 2021

Copy link
Copy Markdown
Collaborator

Trampoline routing uses layered onions to trustlessly and privately offload the calculation of parts of a payment route to remote trampoline nodes.

A normal onion contains a smaller onion for the last hop of the route, and that smaller onion contains routing information about the next trampoline hop.

Intermediate trampoline nodes "fill the gap" by finding a route to the next trampoline node, and sending it the peeled trampoline onion, until that reaches the final destination.

This PR details the onion construction and requirements for supporting nodes. I advise readers to also have a look at #829 which gives a more high-level view of the different components, how they interact, and provides nice diagrams that help understand the low-level details.

@rustyrussell rustyrussell left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it, but I'm not sure I understand the purpose of the payment_secret except inside the internal onion for the final node?

Comment thread 04-onion-routing.md Outdated
Comment thread 04-onion-routing.md Outdated
Comment thread 04-onion-routing.md Outdated
Comment thread 04-onion-routing.md Outdated
@rustyrussell rustyrussell changed the title Trampoline onion format Trampoline onion format (Feature 24/25) Mar 1, 2021

@lightning-developer lightning-developer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the spec should make a recommendation for CLTV and fee budgets that senders of trampoline onions should use for each trampoline to reduce the usage of temporary_trampoline_failure.

Also it seems reasonable to just reply with a single fee_budget_msat instead of * [u32:fee_base_msat] and [u32:fee_proportional_millionths] as those fields seem not to make sense in the context of trampolines.

Trampolines could announce the fee_budget_msat and cltv_budget (in case you like the new name) that they believe to be sufficient in their node announcements?

Comment thread 04-onion-routing.md Outdated
Comment thread 04-onion-routing.md
t-bast added a commit to ACINQ/eclair that referenced this pull request May 19, 2026
We add support for the official version of trampoline payments, as
specified in lightning/bolts#836.

We keep supporting trampoline payments that use the legacy protocol
to allow a smooth transition. We hardcode the legacy feature bit 149
in a few places to make this work, which is a bit hacky but simple
and should be removed 6 months after releasing the official version.

We also keep supporting payments from trampoline wallets to nodes that
don't support trampoline: this is bad from a privacy standpoint, but
will be fixed when recipients start supporting Bolt 12.
t-bast added a commit to ACINQ/eclair that referenced this pull request May 20, 2026
We add support for the official version of trampoline payments, as
specified in lightning/bolts#836.

We keep supporting trampoline payments that use the legacy protocol
to allow a smooth transition. We hardcode the legacy feature bit 149
in a few places to make this work, which is a bit hacky but simple
and should be removed 6 months after releasing the official version.

We also keep supporting payments from trampoline wallets to nodes that
don't support trampoline: this is bad from a privacy standpoint, but
will be fixed when recipients start supporting Bolt 12.
t-bast added a commit to ACINQ/eclair that referenced this pull request May 20, 2026
We add support for the official version of trampoline payments, as
specified in lightning/bolts#836.

We keep supporting trampoline payments that use the legacy protocol
to allow a smooth transition. We hardcode the legacy feature bit 149
in a few places to make this work, which is a bit hacky but simple
and should be removed 6 months after releasing the official version.

We also keep supporting payments from trampoline wallets to nodes that
don't support trampoline: this is bad from a privacy standpoint, but
will be fixed when recipients start supporting Bolt 12.
t-bast added a commit to ACINQ/eclair that referenced this pull request Jun 18, 2026
We add support for the official version of trampoline payments, as
specified in lightning/bolts#836.

We keep supporting trampoline payments that use the legacy protocol
to allow a smooth transition. We hardcode the legacy feature bit 149
in a few places to make this work, which is a bit hacky but simple
and should be removed 6 months after releasing the official version.

We also keep supporting payments from trampoline wallets to nodes that
don't support trampoline: this is bad from a privacy standpoint, but
will be fixed when recipients start supporting Bolt 12.
t-bast added a commit to ACINQ/eclair that referenced this pull request Jun 19, 2026
We add support for the official version of trampoline payments, as
specified in lightning/bolts#836.

We keep supporting trampoline payments that use the legacy protocol
to allow a smooth transition. We hardcode the legacy feature bit 149
in a few places to make this work, which is a bit hacky but simple
and should be removed 6 months after releasing the official version.

We also keep supporting payments from trampoline wallets to nodes that
don't support trampoline: this is bad from a privacy standpoint, but
will be fixed when recipients start supporting Bolt 12.
Comment thread 04-onion-routing.md Outdated
t-bast added a commit to ACINQ/eclair that referenced this pull request Aug 28, 2026
We add support for the official version of trampoline payments, as
specified in lightning/bolts#836.

We keep supporting trampoline payments that use the legacy protocol
to allow a smooth transition. We hardcode the legacy feature bit 149
in a few places to make this work, which is a bit hacky but simple
and should be removed 6 months after releasing the official version.

We also keep supporting payments from trampoline wallets to nodes that
don't support trampoline: this is bad from a privacy standpoint, but
will be fixed when recipients start supporting Bolt 12.
t-bast added a commit to ACINQ/lightning-kmp that referenced this pull request Aug 28, 2026
We update the trampoline feature to match the official specification
from lightning/bolts#836.

We remove support for the previous version of trampoline, which means
that when paying nodes that use the experimental version, we will use
the trampoline-to-non-trampoline flow instead. Similarly, when older
nodes pay updated nodes, they won't understand the new trampoline
feature bit and will use the trampoline-to-non-trampoline flow.

We update the trampoline-to-non-trampoline flow to remove the unused
trampoline payload in the onion, which saves some space. Note that we
don't want to officially specify this scenario, as it leaks some data
about the recipient to the trampoline node. We rather wait for nodes
to either support trampoline or blinded paths, which fixes this issue.
t-bast added a commit to ACINQ/lightning-kmp that referenced this pull request Aug 28, 2026
We update our trampoline payments to blinded paths to match the official
specification from lightning/bolts#836.

The blinded paths and recipient features are included in the trampoline
onion, which potentially allows using multiple trampoline hops.

That was already what we were doing with experimental TLVs, so we simply
update the TLV values to match the spec values.
t-bast added a commit to ACINQ/lightning-kmp that referenced this pull request Aug 28, 2026
We add the ability to pay recipients that support trampoline *and*
blinded paths. We include the blinded path data in the trampoline
payloads for each node inside the blinded path. This doesn't reveal
unnecessary information to the trampoline node: this is specified in
details in lightning/bolts#836.
t-bast and others added 8 commits August 28, 2026 15:55
Trampoline routing uses layered onions to trustlessly and privately offload
the calculation of parts of a payment route to remote trampoline nodes.

A normal onion contains a smaller onion for the last hop of the route, and
that smaller onion contains routing information about the next trampoline hop.

Intermediate trampoline nodes "fill the gap" by finding a route to the next
trampoline node, and sending it the peeled trampoline onion, until that
reaches the final destination.
When paying a Bolt 12 invoice, the payer may use a trampoline node to
relay that payment. If the recipient doesn't support trampoline, the
payer simply includes some of the blinded paths in the onion payload
for the trampoline node, who will relay to those blinded paths. The
trampoline node doesn't learn anything about the final recipient, it
only learns the blinded paths they use, which should protect their
privacy (unless using empty blinded paths).

If the recipient supports trampoline and the `invoice_request` contains
the trampoline feature bit, the recipient may set it in its invoice. In
that case, the sender can use every node in the blinded path as a
trampoline node and include the encrypted blinded path data in the
trampoline onion. This also provides the opportunity for the sender
to include additional TLVs for the recipient.
Add a test vector detailing how trampoline failures are encrypted and
decrypted until they reach the sender.
We don't actually need to use MPP between trampoline nodes: a single
part payment could work. We're thus removing the requirement to always
provide the MPP field in the outer onion.

Always using MPP (even for single-part payments) simplified our eclair
implementation, but other implementations may work differently, so it
shouldn't impact the spec.
When a trampoline node inside a trampoline blinded path wants to fail an
incoming payment, it must use `update_fail_malformed_htlc` to avoid
leaking blinded path information. The introduction node will translate
that into a real `temporary_trampoline_failure` that it then encrypts to
the payer. We add a test vector that showcases this behavior.
There is no identified scenario where intermediate trampoline nodes use
a blinded path to reach the next trampoline node, since they know the
identity of that next node. We thus disallow this case by specifying
that the `current_path_key` can only be set in either the outer onion
or the trampoline onion (for the introduction node).
We clarify that trampoline nodes can either apply a double error
obfuscation when they want to encrypt for the original sender or
only obfuscate with outer onion secrets to encrypt for the previous
trampoline node.

Suggested by @a-mpch
When using trampoline blinded paths, we don't require trampoline nodes
to use `update_fail_malformed_htlc`. We simply use `update_fail_htlc`
with `invalid_onion_blinding` inside the blinded path, or any error
message at the introduction node.

Suggested by @carlaKC
@t-bast

t-bast commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased to fix conflicts (BOLT 4 had seen quite a lot of changes with attribution data and fulfillment payload).

Comment thread 04-onion-routing.md Outdated
Comment on lines +538 to +546
- If it is not the final node:
- If the incoming payment is a multi-part payment:
- MUST wait to receive all the payment parts before forwarding.
- If the outer onion's `outgoing_cltv_value` is smaller than the trampoline onion's `outgoing_cltv_value`:
- MUST reject the payment.
- If the outer onion's `total_msat` is smaller than the trampoline onion's `amt_to_forward`:
- MUST reject the payment.
- If the outer onion's `amt_to_forward` is smaller than the trampoline onion's `amt_to_forward`:
- MUST reject the payment.

@SomberNight SomberNight Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last check is incorrect. In case of MPP, the outer onion's amt_to_forward can be smaller than the inner's. See

| amount_fwd: 1500 msat |

The check should be:

    - If the outer onion's `total_msat` is smaller than the trampoline onion's `amt_to_forward`:
      - MUST reject the payment.

This is hard to get right.

(EDIT: same for the final node)

@SomberNight SomberNight Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, you have my suggested check on the line above.
Well, soooo, I think the (amount) checks should be:

assert outer_onion.total_msat >= outer_onion.amt_to_forward
assert outer_onion.total_msat >= inner_onion.amt_to_forward

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, actually removing the "if" by assuming #1355 was incorrect. I just removed one of the branches, which actually becomes obsolete afte #1355 (I've amended the last commit for that).

We make it explicit that intermediate trampoline nodes must validate
that the outgoing amount and expiry (from the inner onion) are smaller
than the incoming values from the outer onion, otherwise they would
be relaying payments where they lose funds or don't benefit from
HTLC-timeout security.

Suggested by @ghost43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.