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

Add the ability to hold HTLCs before forwarding (FEAT 52/53) #989

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 51 additions & 0 deletions 02-peer-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,25 @@ is destined, is described in [BOLT #4](04-onion-routing.md).
* [`sha256`:`payment_hash`]
* [`u32`:`cltv_expiry`]
* [`1366*byte`:`onion_routing_packet`]
* [`update_add_htlc_tlvs`:`tlvs`]

1. `tlv_stream`: `update_add_htlc_tlvs`
2. types:
1. type: 0 (`hold_htlc`)
2. data:
* [`32*bytes`:`payment_release_secret`]
Comment on lines +931 to +935

Choose a reason for hiding this comment

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

This conflicts with payments to blinded routes (https://github.com/lightning/bolts/pull/765/files), you can use 2.


#### TLV fields for `held_htlc_available`
Copy link
Contributor

Choose a reason for hiding this comment

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

Given release_held_htlc may be sent hours later, it seems weird that the sender has no way of knowing that held_htlc_available arrived successfully (I get that it's supposed to be sent over two different paths, but still). Should there be a held_htlc_available_msg_received reply?

1. `tlv_stream`: `held_htlc_available`
2. types:

#### TLV fields for `release_held_htlc`

1. `tlv_stream`: `release_held_htlc`
2. types:
1. type: 0 (`payment_release_secret`)
2. data:
* [`32*bytes`:`payment_release_secret`]
Comment on lines +937 to +947

Choose a reason for hiding this comment

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

From the next section I get that these are onion messages. They should go in the onionmsg_payload in 04-onion-routing.md

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I kinda disagree? I mean not super strongly, I'm happy to put them anywhere, but generally I don't think we should be shoving every onion message into 04-onion-routing, that makes no sense, IMO. The BOLT 12 (somewhat obviously) PR puts its onion messages into BOLT 12, so I shoved these into the relevant place. We could also define a more general "13-onion-messages` BOLT and shove all the messages there, but I don't think that's super useful either - we generally group things by functionality, not type.

Choose a reason for hiding this comment

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

I didn't mean that everything should go into 04-onion-routing but they need to be mentioned there as possible onion messages. Just like for BOLT 12, the details of the bolt 12 types are in there own file but they are referenced from 04-onion-routing. I'm saying this because for release_held_htlc, it's not a standard onion message TLV and it would be good to make it clear exactly where it needs to go.


#### Requirements

Expand Down Expand Up @@ -962,6 +981,19 @@ 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.
- MUST NOT include a `hold_htlc` TLV unless the sending node expects the
final recipient of the HTLC to be offline at the time the HTLC would arrive
Comment on lines +984 to +985
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be useful for the recipient to signal that they want the sender to make use of hold_htlc in their invoice, since the sender may not know they're paying to a mostly-offline user?

Downside of course being that it's bad for privacy and you generally don't want to tell people you're offline in LN. But without some indication, your options as a sender are:

  1. Use hold_htlc by default
    -> Unnescesary overhead for online destinations
    -> Won't work for offline users without LSPs (onion message fails quietly at offline node?)
  2. Try without first, fail and then retry with hold_htlc
    -> Bad UX / possible stuck payment

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Would it be useful for the recipient to signal that they want the sender to make use of hold_htlc in their invoice, since the sender may not know they're paying to a mostly-offline user?

Yep! This isn't a fully-usable protocol on its own, its one of 3 or 4 parts you'd need to use this - invoice signaling being one part.

- MUST NOT include a `hold_htlc` TLV unless the sending node expects to be
offline for an extended duration starting soon.
- If the `hold_htlc` TLV is present:
- MUST immediately send at least two onion messages across at least two

Choose a reason for hiding this comment

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

Why 2? It seems like it should be an implementation decision.
Anyway, sending an onion message to a node that we expect to be offline is pointless, the message will never be delivered.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See PR text - this assumes store-and-forward mailbox support at the recipient's LSP.

different paths to the final HTLC recipient.
- Each onion message MUST contain a `held_htlc_available` TLV.
- Each onion message MUST contain a unique `reply_path`s which terminates
at the reciever of the `update_add_htlc` message.
- Each `reply_path` MUST contain a `release_held_htlc` TLV for the
`update_add_htlc` recipient in the `encrypted_data_tlvs` with a
`payment_release_secret` matching that in the `hold_htlc` TLV.

`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 +1018,12 @@ 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 the `hold_htlc` TLV is present:
- MUST NOT forward the HTLC until a corresponding `release_held_htlc` onion
message is received with a matching `payment_release_secret`.
- Upon receipt of a `release_held_htlc` onion message with a matching
`payment_release_secret` the HTLC SHOULD be treated as any HTLC without
the `hold_htlc` TLV and forwarded as usual.

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 Expand Up @@ -1021,6 +1059,19 @@ maintaining its channel reserve (because of the increased weight of the
commitment transaction), resulting in a degraded channel. See [#728](https://github.com/lightningnetwork/lightning-rfc/issues/728)
for more details.

For often-offline recipients, e.g. mobile clients, nodes can use the
`hold_htlc` TLV to prevent further forwarding of an HTLC until the recipient
comes online. As long as the final recipients' counterparty is online and
storing onion messages for the recipient, the recipient can reply to the onion
message when they come online, unblock the HTLC, and expect to receive it
quickly thereafter.

Note that if the sender expects to be online when the recipient comes online,
they can utilize the `release_held_htlc` onion message without utilizing the
`hold_htlc` TLV - they can simply send a `held_htlc_available` onion message
to the final recipient and wait to send any HTLC at all until they receive a
`release_held_htlc` message back.

### Removing an HTLC: `update_fulfill_htlc`, `update_fail_htlc`, and `update_fail_malformed_htlc`

For simplicity, a node can only remove HTLCs added by the other node.
Expand Down
1 change: 1 addition & 0 deletions 09-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ The Context column decodes as follows:
| 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) |
| 48/49 | `option_payment_metadata` | Payment metadata in tlv record | 9 | | [BOLT #11](11-payment-encoding.md#tagged-fields)
| 52/53 | `option_htlc_hold` | Hold HTLCs and forward on receipt of an onion message | IN | `option_onion_messages` |

Choose a reason for hiding this comment

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

Do we want to advertise this option to everyone? I can imagine that we would only accept to hold HTLCs for our customers but not for other nodes. I think it should be per channel.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't see why you'd want such a restriction? The hold option can only be set by your counterparty, never a rando node, and if your counterparty wants to not use some of their channel balance...they can always do that?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe we do want to advertise this to everyone, because it's a good selling point for people to open channels with you: by just looking at your node_announcement they know that you offer this feature that will be useful to them if they want to receive payments and expect to be offline sometimes.


## Definitions

Expand Down