From dc5fa39cfb5b280d7c537665b6a03744c1127238 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 23 Sep 2025 10:38:30 +0930 Subject: [PATCH 1/4] BOLT 4: add minitramp support. We use the same "encrypted blob inside onion" trick as blinded paths, but using TLV 1, so it's ignored for backward compatibility. In this case, we need to tell the trampoline the `payment_secret` (and optional `payment_metadata`) to put in the onion, which gives it the possibility of probing, or even underpaying amountless invoices. However, if the final hop *does* support TLV 1, it can detect interference and refuse attempts to pay that same invoice (since there's a dishonest trampoline), providing *some* honesty incentive. Signed-off-by: Rusty Russell --- 04-onion-routing.md | 125 ++++++++++++++++++++++++++++++++++++++++++++ 09-features.md | 2 + 2 files changed, 127 insertions(+) diff --git a/04-onion-routing.md b/04-onion-routing.md index d61542c6f..c230dcab5 100644 --- a/04-onion-routing.md +++ b/04-onion-routing.md @@ -189,6 +189,10 @@ This is formatted according to the Type-Length-Value format defined in [BOLT #1] 1. `tlv_stream`: `payload` 2. types: + 1. type: 1 (`minitramp`) + 2. data: + * [`pubkey`:`trampkey`] + * [`...*byte`:`encrypted_trampinfo`] 1. type: 2 (`amt_to_forward`) 2. data: * [`tu64`:`amt_to_forward`] @@ -635,6 +639,127 @@ sender, containing instructions for the node on how to handle the message (it ca in both payment onions and onion messages onions. See [Route Blinding](#route-blinding). +# Minitrampoline Support + +This allows outsourcing routing, with limited privacy protections. The destination notes the `encrypted_trampinfo` field in the onion payload, and decrypts it to find `trampinfo` tlv stream, which indicates the next recipient, and a `encrypted_trampinfo` for that recipient (which may be the final recipient). + +We share the encryption scheme used by the onion, except the key is explicitly given in the `trampkey` tlv field. + +The `trampinfo` can contain another `encrypted_trampinfo` to allow for chaining minitrampolines. It is odd, so if the final recipient does not support `option_minitrampoline` it will ignore it: in this case the `payment_secret` and `payment_metadata` fields must be the correct ones for the payment, thus trusting the final minitrampoline node in the case of amountless bolt11 invoices. + +Encryption is done using the same scheme as `encrypted_recipient_data`, with `trampkey` as `E`: + - $`ss = SHA256(k * E)`$ (standard ECDH) + - $`rho = HMAC256(\text{"rho"}, ss)`$ + - Use $`rho`$ as a key with ChaCha20-Poly1305 and an all-zero nonce key. + +If the final destination does not support `encrypted_trampinfo` it will ignore the `minitramp` field, so in this case the `payment_secret` and `payment_metadata` have to be correct for the payment: if the payment is not for a specified amount, this may allow the final trampoline to try forwarding less than the full amount. However, if the final destination does understand `encrypted_trampinfo` then it will ensure the amounts, `payment_secret` and `payment_metadata` are correct, and it will never accept future attempts to pay this invoice if it detects a discrepancy. This unknown helps keep the trampoline nodes honest while the network transitions. + + +1. `tlv_stream`: `minitramp_payload` +2. types: + 1. type: 1 (`minitramp`) + 2. data: + * [`pubkey`:`trampkey`] + * [`...*byte`:`encrypted_trampinfo`] + 1. type: 2 (`amount_to_send`) + 2. data: + * [`tu64`:`amount`] + 1. type: 4 (`next_cltv_value`) + 2. data: + * [`tu32`:`next_cltv_value`] + 1. type: 6 (`next_node`) + 2. data: + * [`publey`:`next`] + 1. type: 8 (`incoming_payment_secret`) + 2. data: + * [`32*byte`:`payment_secret`] + 1. type: 10 (`incoming_payment_metadata`) + 2. data: + * [`...*byte`:`payment_metadata`] + 1. type: 12 (`incoming_amount_msat`) + 2. data: + * [`tu64`:`msat`] + 1. type: 14 (`incoming_ctlv`) + 2. data: + * [`tu32`:`ctlv`] + 1. type: 16 (`outgoing_payment_secret`) + 2. data: + * [`32*byte`:`payment_secret`] + 1. type: 18 (`outgoing_payment_metadata`) + 2. data: + * [`...*byte`:`payment_metadata`] + 1. type: 20 (`blinded_paths`) + 2. data: + * [`...*blinded_path`:`paths`] + 1. type: 22 (`blinded_payinfo`) + 2. data: + * [`...*blinded_payinfo`:`payinfo`] + +## Requirements + +The initial sender of a "minitramp" payment builds it backwards from final destination: +- MUST create a `trampinfo` (#1) for the payment destination: + - MUST NOT set `amount_to_send`, `next_cltv_value`, `next_node`, `blinded_paths`, `blinded_payinfo` or `minitramp`. + - MUST set `outgoing_payment_secret`, `outgoing_payment_metadata`, `total_amount_msat` to the values which would normally set in the final `payload`. + - If the payment destination is known to support `option_minitrampoline`: + - SHOULD set `incoming_payment_secret` and `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). + - Otherwise: + - MUST set `incoming_payment_secret` and `incoming_payment_metadata` to `outgoing_payment_secret` and `outgoing_payment_metadata`. + - MAY use `padding` to disguise that this is the final destination. +- MUST create a `trampinfo` (#2) for the previous trampoline: + - MUST set `minitramp`.`trampkey` to the public key of a random secret. + - MUST set `minitramp`.`encrypted_trampinfo` to the encrypted `trampinfo` created for the payment destination. + - MUST set `outgoing_payment_secret` to `incoming_payment_secret` in `trampinfo` #1. + - MUST set `outgoing_payment_metadata` to `incoming_payment_metadata` in `trampinfo` #1. + - MUST set `amount_to_send` and `next_cltv_value` to the values expected by the payment destination. + - MUST set `blinded_paths` and `blinded_payinfo` as supplied by the invoice. + - If it sets `blinded_paths`: + - MUST NOT set `next_node`. + - Otherwise: + - MUST set `next_node` to the node id of the payment destination. + - MUST set `incoming_amount_msat` and `incoming_ctlv` to the values expected at this destination. + - MUST set `total_amount_msat` to the `incoming_amount_msat` of `trampinfo` #1 + - MUST set `next_cltv_value` to the `incoming_ctlv` of `trampinfo` #1 + - SHOULD set `incoming_payment_secret` and `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). +- If it creates another `trampinfo` (#3 onwards); + - MUST set `minitramp`.`trampkey` to the public key of a random secret. + - MUST set `minitramp`.`encrypted_trampinfo` to the encrypted previous `trampinfo` + - MUST set `outgoing_payment_secret` to `incoming_payment_secret` in the previous `trampinfo`. + - MUST set `outgoing_payment_metadata` to `incoming_payment_metadata` in the previous `trampinfo`. + - SHOULD set `incoming_payment_secret` and `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). + - MUST set `total_amount_msat` to the `incoming_amount_msat` of the previous `trampinfo` + - MUST set `next_cltv_value` to the `incoming_ctlv` of the previous `trampinfo` + - MUST set `next_node` to the node id of the next trampoline +- MUST create a payment to the first trampoline node: + - MUST put the last-produced `minitramp` into the final `payload` for each payment part. + - MUST set `payment_secret` and `payment_metadata` to the `incoming_payment_secret` and `incoming_payment_metadata` of the last-produced `trampinfo`. + +The recipient: +- MUST process all parts of the payment as normal. +- If this is the final node (no more onion to unwrap), and `minitramp` is present: + - If `encrypted_trampinfo` does not decrypt into a valid `trampinfo`: + - Return an error (FIXME) + - If `trampinfo`.`incoming_amount_msat` or `trampinfo`.`incoming_ctlv` are not equal to the incoming HTLC + - Reject payment + - If neither `node_id` nor `blinded_paths` are present (we are the final destination): + - If `payment_secret` in `payload` is not equal to `trampinfo`.`incoming_payment_secret`: + - Don't ever accept payment of this invoice + - Reject payment + - If `payment_metadata` in `payload` is not equal to `trampinfo`.`incoming_payment_metadata`: + - Don't ever accept payment of this invoice + - Reject payment + - Otherwise: (forwarding): + - If both `next_node` and `blinded_paths` are present: + - Reject + - Determine a route to `next_node` or `blinded_paths` for `amount_to_send` using `next_cltv_value`. + - If the incoming amount or cltv is insufficient: + - Don't ever accept payment of this invoice + - Reject payment + - If the number of `blinded_paths` and `blinded_payinfo` do not match: + - Reject + - MUST include `trampinfo`.`minitramp`, `outgoing_payment_secret` (as `payment_secret`) and `outgoing_payment_info` (as `payment_metadata`) in the inner `payload` of the payment onion. + + # 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. diff --git a/09-features.md b/09-features.md index e7a8cbed6..43293d51b 100644 --- a/09-features.md +++ b/09-features.md @@ -54,6 +54,7 @@ The Context column decodes as follows: | 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 | INT | `option_scid_alias` | [BOLT #2][bolt02-channel-ready] | | 60/61 | `option_simple_close` | Simplified closing negotiation | IN | `option_shutdown_anysegwit` | [BOLT #2][bolt02-simple-close] | +| 58/59 | `option_minitrampoline` | Will forward payments via encrypted instructions | IN | | [BOLT #4][bolt04-minitramp] | ## Requirements @@ -107,5 +108,6 @@ 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-minitramp]: 04-onion-routing.md#minitrampoline-support [bolt04-route-blinding]: 04-onion-routing.md#route-blinding [ml-sighash-single-harmful]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-September/002796.html From ab5ebd75f2181bc22fcdfbeaf37dd490aeb5606b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 23 Sep 2025 10:38:38 +0930 Subject: [PATCH 2/4] minitramp: protect the case where the malicious tramp *omits* the minitramp field. We use the trick that the payload `payment_secret` we tell the final trampoline is actually the hash of the real payment secret. This means the final node (if it understands minitramp) *knows* that minitramp is being used, and can penalize that case too. Signed-off-by: Rusty Russell --- 04-onion-routing.md | 58 +++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/04-onion-routing.md b/04-onion-routing.md index c230dcab5..ea1f4640d 100644 --- a/04-onion-routing.md +++ b/04-onion-routing.md @@ -702,7 +702,8 @@ The initial sender of a "minitramp" payment builds it backwards from final desti - MUST NOT set `amount_to_send`, `next_cltv_value`, `next_node`, `blinded_paths`, `blinded_payinfo` or `minitramp`. - MUST set `outgoing_payment_secret`, `outgoing_payment_metadata`, `total_amount_msat` to the values which would normally set in the final `payload`. - If the payment destination is known to support `option_minitrampoline`: - - SHOULD set `incoming_payment_secret` and `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). + - SHOULD set `incoming_payment_secret` to the SHA256 hash of `outgoing_payment_secret`. + - SHOULD set `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). - Otherwise: - MUST set `incoming_payment_secret` and `incoming_payment_metadata` to `outgoing_payment_secret` and `outgoing_payment_metadata`. - MAY use `padding` to disguise that this is the final destination. @@ -736,29 +737,40 @@ The initial sender of a "minitramp" payment builds it backwards from final desti The recipient: - MUST process all parts of the payment as normal. -- If this is the final node (no more onion to unwrap), and `minitramp` is present: - - If `encrypted_trampinfo` does not decrypt into a valid `trampinfo`: - - Return an error (FIXME) - - If `trampinfo`.`incoming_amount_msat` or `trampinfo`.`incoming_ctlv` are not equal to the incoming HTLC - - Reject payment - - If neither `node_id` nor `blinded_paths` are present (we are the final destination): - - If `payment_secret` in `payload` is not equal to `trampinfo`.`incoming_payment_secret`: - - Don't ever accept payment of this invoice - - Reject payment - - If `payment_metadata` in `payload` is not equal to `trampinfo`.`incoming_payment_metadata`: - - Don't ever accept payment of this invoice - - Reject payment - - Otherwise: (forwarding): - - If both `next_node` and `blinded_paths` are present: - - Reject - - Determine a route to `next_node` or `blinded_paths` for `amount_to_send` using `next_cltv_value`. - - If the incoming amount or cltv is insufficient: - - Don't ever accept payment of this invoice - - Reject payment - - If the number of `blinded_paths` and `blinded_payinfo` do not match: - - Reject - - MUST include `trampinfo`.`minitramp`, `outgoing_payment_secret` (as `payment_secret`) and `outgoing_payment_info` (as `payment_metadata`) in the inner `payload` of the payment onion. +- If this is the final node (no more onion to unwrap): + - If `minitramp` is present: + - If `encrypted_trampinfo` does not decrypt into a valid `trampinfo`: + - Fail all HTLCs with `incorrect_or_unknown_payment_details`. + - Check for trampoline misbehaviour (below) + - If `trampinfo`.`incoming_amount_msat` or `trampinfo`.`incoming_ctlv` are not equal to the incoming HTLC + - Fail all HTLCs with `incorrect_or_unknown_payment_details`. + - If neither `node_id` nor `blinded_paths` are present (we are the final destination): + - If `payment_secret` in `payload` is not equal to `trampinfo`.`incoming_payment_secret`: + - Reject payment + - Check for trampoline misbehaviour (below) + - If `payment_metadata` in `payload` is not equal to `trampinfo`.`incoming_payment_metadata`: + - Reject payment + - Otherwise: (forwarding): + - If both `next_node` and `blinded_paths` are present: + - Reject payment + - Determine a route to `next_node` or `blinded_paths` for `amount_to_send` using `next_cltv_value`. + - If the incoming amount or cltv is insufficient: + - Reject payment + - If the number of `blinded_paths` and `blinded_payinfo` do not match: + - Reject payment + - MUST include `trampinfo`.`minitramp`, `outgoing_payment_secret` (as `payment_secret`) and `outgoing_payment_info` (as `payment_metadata`) in the inner `payload` of the payment onion. + - Otherwise (`minitramp` is NOT present): + - Check for trampoline misbehaviour (below) + +Checking for trampoline misbehaviour: + - If `payload`.`payment_secret` is the SHA256 of the expected `payment_secret` for this payment: + - SHOULD NOT accept any future payment for this invoice (e.g. expire invoice immediately). +## Rationale + +If the recipient supports minitrampoline, then the `payment_secret` and amount are secure: a trampoline cannot interfere with these and still have the payment work. However, if the recipient does not support it, then interference is possible: a malicious trampoline can try to make a payment using the `payment_hash` and `payment_secret`, and if it succeeds it knows that the next hop is the final destination, and if the amount of the invoice is variable, can extract an arbitrary fee. + +To steal from a non-minitramp final node, a malicious trampoline attempts this, would have to set the `payment_secret` in the payload to the `outgoing_payment_secret` it is given. But then it has to replace or omit the `trampinfo`, which will cause a minitramp node to fail the payment and any future attempts, denying it the fee it would otherwise gain (and possibly causing the payer to try another, more reliable trampoline). # Accepting and Forwarding a Payment From 9f25ae7a621e3a16add975fc38975aa71eaf0692 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 23 Sep 2025 10:38:38 +0930 Subject: [PATCH 3/4] minitramp: don't hide payment_metadata. It doesn't seem anyone actually uses this, so specify it more simply. Signed-off-by: Rusty Russell --- 04-onion-routing.md | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/04-onion-routing.md b/04-onion-routing.md index ea1f4640d..c2ff24e0b 100644 --- a/04-onion-routing.md +++ b/04-onion-routing.md @@ -673,7 +673,7 @@ If the final destination does not support `encrypted_trampinfo` it will ignore t 1. type: 8 (`incoming_payment_secret`) 2. data: * [`32*byte`:`payment_secret`] - 1. type: 10 (`incoming_payment_metadata`) + 1. type: 10 (`payment_metadata`) 2. data: * [`...*byte`:`payment_metadata`] 1. type: 12 (`incoming_amount_msat`) @@ -685,9 +685,6 @@ If the final destination does not support `encrypted_trampinfo` it will ignore t 1. type: 16 (`outgoing_payment_secret`) 2. data: * [`32*byte`:`payment_secret`] - 1. type: 18 (`outgoing_payment_metadata`) - 2. data: - * [`...*byte`:`payment_metadata`] 1. type: 20 (`blinded_paths`) 2. data: * [`...*blinded_path`:`paths`] @@ -697,21 +694,20 @@ If the final destination does not support `encrypted_trampinfo` it will ignore t ## Requirements -The initial sender of a "minitramp" payment builds it backwards from final destination: +The initial sender of a "minitramp" payment builds it *backwards* from final destination: - MUST create a `trampinfo` (#1) for the payment destination: - MUST NOT set `amount_to_send`, `next_cltv_value`, `next_node`, `blinded_paths`, `blinded_payinfo` or `minitramp`. - - MUST set `outgoing_payment_secret`, `outgoing_payment_metadata`, `total_amount_msat` to the values which would normally set in the final `payload`. + - MUST set `outgoing_payment_secret`, `payment_metadata`, `total_amount_msat` to the values which would normally set in the final `payload`. - If the payment destination is known to support `option_minitrampoline`: - SHOULD set `incoming_payment_secret` to the SHA256 hash of `outgoing_payment_secret`. - - SHOULD set `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). - Otherwise: - - MUST set `incoming_payment_secret` and `incoming_payment_metadata` to `outgoing_payment_secret` and `outgoing_payment_metadata`. + - MUST set `incoming_payment_secret` to `outgoing_payment_secret`. - MAY use `padding` to disguise that this is the final destination. - MUST create a `trampinfo` (#2) for the previous trampoline: - MUST set `minitramp`.`trampkey` to the public key of a random secret. - MUST set `minitramp`.`encrypted_trampinfo` to the encrypted `trampinfo` created for the payment destination. - MUST set `outgoing_payment_secret` to `incoming_payment_secret` in `trampinfo` #1. - - MUST set `outgoing_payment_metadata` to `incoming_payment_metadata` in `trampinfo` #1. + - MAY set `payment_metadata` to a random value. - MUST set `amount_to_send` and `next_cltv_value` to the values expected by the payment destination. - MUST set `blinded_paths` and `blinded_payinfo` as supplied by the invoice. - If it sets `blinded_paths`: @@ -721,19 +717,19 @@ The initial sender of a "minitramp" payment builds it backwards from final desti - MUST set `incoming_amount_msat` and `incoming_ctlv` to the values expected at this destination. - MUST set `total_amount_msat` to the `incoming_amount_msat` of `trampinfo` #1 - MUST set `next_cltv_value` to the `incoming_ctlv` of `trampinfo` #1 - - SHOULD set `incoming_payment_secret` and `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). + - SHOULD set `incoming_payment_secret` and to random data. - If it creates another `trampinfo` (#3 onwards); - MUST set `minitramp`.`trampkey` to the public key of a random secret. - MUST set `minitramp`.`encrypted_trampinfo` to the encrypted previous `trampinfo` - MUST set `outgoing_payment_secret` to `incoming_payment_secret` in the previous `trampinfo`. - - MUST set `outgoing_payment_metadata` to `incoming_payment_metadata` in the previous `trampinfo`. - - SHOULD set `incoming_payment_secret` and `incoming_payment_metadata` to random data (16 bytes in the case of `incoming_payment_metadata`). + - MAY set `payment_metadata` to a random value. + - SHOULD set `incoming_payment_secret` to random data. - MUST set `total_amount_msat` to the `incoming_amount_msat` of the previous `trampinfo` - MUST set `next_cltv_value` to the `incoming_ctlv` of the previous `trampinfo` - MUST set `next_node` to the node id of the next trampoline - MUST create a payment to the first trampoline node: - MUST put the last-produced `minitramp` into the final `payload` for each payment part. - - MUST set `payment_secret` and `payment_metadata` to the `incoming_payment_secret` and `incoming_payment_metadata` of the last-produced `trampinfo`. + - MUST set `payment_secret` to the `incoming_payment_secret` of the last-produced `trampinfo`. The recipient: - MUST process all parts of the payment as normal. @@ -742,14 +738,13 @@ The recipient: - If `encrypted_trampinfo` does not decrypt into a valid `trampinfo`: - Fail all HTLCs with `incorrect_or_unknown_payment_details`. - Check for trampoline misbehaviour (below) - - If `trampinfo`.`incoming_amount_msat` or `trampinfo`.`incoming_ctlv` are not equal to the incoming HTLC + - If `trampinfo`.`incoming_amount_msat` or `trampinfo`.`incoming_ctlv` are less than the incoming HTLC - Fail all HTLCs with `incorrect_or_unknown_payment_details`. - If neither `node_id` nor `blinded_paths` are present (we are the final destination): - If `payment_secret` in `payload` is not equal to `trampinfo`.`incoming_payment_secret`: - Reject payment - Check for trampoline misbehaviour (below) - - If `payment_metadata` in `payload` is not equal to `trampinfo`.`incoming_payment_metadata`: - - Reject payment + - SHOULD process the payment as if the `payload` contained the `minitramp` `payment_secret` and `payment_metadata`. - Otherwise: (forwarding): - If both `next_node` and `blinded_paths` are present: - Reject payment From c5d5219e8471a3eaa768db56758cee6b56bb316a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 23 Sep 2025 10:47:26 +0930 Subject: [PATCH 4/4] minitramp: specify errors in more detail And steal @t-bast's trampoline error codes. Signed-off-by: Rusty Russell --- 04-onion-routing.md | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/04-onion-routing.md b/04-onion-routing.md index c2ff24e0b..14cf0e3d4 100644 --- a/04-onion-routing.md +++ b/04-onion-routing.md @@ -742,18 +742,24 @@ The recipient: - Fail all HTLCs with `incorrect_or_unknown_payment_details`. - If neither `node_id` nor `blinded_paths` are present (we are the final destination): - If `payment_secret` in `payload` is not equal to `trampinfo`.`incoming_payment_secret`: - - Reject payment + - Fail all HTLCs with `incorrect_or_unknown_payment_details`. - Check for trampoline misbehaviour (below) - SHOULD process the payment as if the `payload` contained the `minitramp` `payment_secret` and `payment_metadata`. - Otherwise: (forwarding): - If both `next_node` and `blinded_paths` are present: - - Reject payment + - Fail all HTLCs with `incorrect_or_unknown_payment_details`. + - If the number of `blinded_paths` and `blinded_payinfo` do not match: + - Fail all HTLCs with `incorrect_or_unknown_payment_details`. - Determine a route to `next_node` or `blinded_paths` for `amount_to_send` using `next_cltv_value`. + - If no route can be found: + - Fail all HTLCs with `unknown_next_trampoline`. - If the incoming amount or cltv is insufficient: - - Reject payment - - If the number of `blinded_paths` and `blinded_payinfo` do not match: - - Reject payment + - Fail all HTLCs with `trampoline_fee_or_expiry_insufficient`. - MUST include `trampinfo`.`minitramp`, `outgoing_payment_secret` (as `payment_secret`) and `outgoing_payment_info` (as `payment_metadata`) in the inner `payload` of the payment onion. + - If the payment fails: + - Fail all HTLCs with `temporary_trampoline_failure`. + - Otherwise: + - Use the preimage to succeed all HTLCs. - Otherwise (`minitramp` is NOT present): - Check for trampoline misbehaviour (below) @@ -1427,6 +1433,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_: