Skip to content

Conversation

@valentinewallace
Copy link
Contributor

@valentinewallace valentinewallace commented Mar 19, 2024

This builds on #989 by adding the ability to fetch an invoice from an
always-online node on behalf of an often-offline recipient, e.g. a mobile node.

The idea is that often-offline recipients will supply some always-online node
such as their wallet vendor with a static keysend (i.e. payment_hash-less)
invoice to return on its behalf. The recipient will then publish an offer
containing blinded paths that terminate at this always-online node, who payers
can request the invoice from if the recipient is offline at the time. After
receiving the keysend invoice, payers will commence the protocol outlined in
1 to send the HTLC asynchronously.

Some context on the top commit where we include the invoice request in the payment onion:
This definitely warrants discussion, but the idea is that this field may be useful for often-offline recipients who did not receive the invoice request when it was originally sent. Recipients may want to verify the invreq or be provided some other relevant data about the payment, while keeping the payment stateless until an HTLC is actually received. For example, future extensions have been proposed 2 that require the recipient to know a unique token for a payment, and this field would provide that to them.

Seeking conceptual feedback! I'm also working on the implementation in LDK.

Based on #798 and #989.

@valentinewallace
Copy link
Contributor Author

Changed up the feature bits, required single-chain offers, and disallowed setting invoice_amount_msat for static invoices. Also moved away from the "keysend" language for clarity. These changes were based on implementing this in LDK in lightningdevkit/rust-lightning#3082, will take this out of draft once the design solidifies a bit more in that PR.

@valentinewallace
Copy link
Contributor Author

Added a fixup requiring the invreq to be included in the payment onion per spec meeting discussion a week ago!

@valentinewallace valentinewallace force-pushed the 2024-02-async-payments branch from 5a36154 to 5b5fd7f Compare June 26, 2024 18:13
valentinewallace added a commit to valentinewallace/rust-lightning that referenced this pull request Sep 18, 2024
Per <lightning/bolts#1149>, when paying a static
invoice we need to include our original invoice request in the HTLC onion since
the recipient wouldn't have received it previously.

We use an experimental TLV type for this new onion payload field, since the
spec is still not merged in the BOLTs.
valentinewallace added a commit to valentinewallace/rust-lightning that referenced this pull request Sep 18, 2024
Add a new invoice request parameter to onion_utils::build_onion_payloads.
As of this commit it will always be passed in as None, to be updated in future
commits.

Per <lightning/bolts#1149>, when paying a static
invoice we need to include our original invoice request in the HTLC onion since
the recipient wouldn't have received it previously.
valentinewallace added a commit to valentinewallace/rust-lightning that referenced this pull request Sep 18, 2024
Add a new invoice request parameter to onion_utils::create_payment_onion. As of
this commit it will always be passed in as None, to be updated in future
commits.

Per <lightning/bolts#1149>, when paying a static
invoice we need to include our original invoice request in the HTLC onion since
the recipient wouldn't have received it previously.
valentinewallace added a commit to valentinewallace/rust-lightning that referenced this pull request Sep 18, 2024
Add a new invoice request parameter to outbound_payments and channelmanager
send-to-route internal utils. As of this commit the invreq will always be
passed in as None, to be updated in future commits.

Per <lightning/bolts#1149>, when paying a static
invoice we need to include our original invoice request in the HTLC onion since
the recipient wouldn't have received it previously.
valentinewallace added a commit to valentinewallace/rust-lightning that referenced this pull request Sep 18, 2024
When transitioning outbound payments from AwaitingInvoice to
StaticInvoiceReceived, include the invreq in the new state's outbound payment
storage for future inclusion in an async payment onion.

Per <lightning/bolts#1149>, when paying a static
invoice we need to include our original invoice request in the HTLC onion since
the recipient wouldn't have received it previously.
- Otherwise:
- MUST follow the requirements for the reader of `payload` in [Payload Format](04-onion-routing.md#payload-format)
- if the `hold_htlc` TLV is present:
- MUST NOT forward the HTLC until a corresponding `release_held_htlc` onion
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it known what value LSPs typically use for max htlcs on their channels? If the LSP is the chan initiator, they may want to keep it low to avoid a high commit tx absolute fee. This would then limit the number of outstanding async payments.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, although maybe worth noting that the HTLC slot is only taken up on the mobile sender <> LSP channel, which isn't typically being used for any other payment forwards. LSPs may indeed want to limit the number of outstanding async payments though as you say.

Copy link
Collaborator

Choose a reason for hiding this comment

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

For small tips it may not be a problem because those do not add to the commit tx weight and fee risk for the LSP. Although the risk then is that the LSP might lose the htlc values in a close event.

* [`1366*byte`:`onion_routing_packet`]
* [`update_add_htlc_tlvs`:`tlvs`]

1. `tlv_stream`: `update_add_htlc_tlvs`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Discussed offline: maybe signal hold_htlc in the onion, so that the option remains open to park htlcs at a more remote node? Potentially as a way to unburden the sender LSP from async payments.

@valentinewallace
Copy link
Contributor Author

Appreciate the feedback and discussion @joostjager!

TheBlueMatt and others added 3 commits October 20, 2025 13:01
This is an incredibly simple first start towards the protocol
sketched out at [1]. It adds the ability to have a counteraprty
hold an HTLC before forwarding it.

Specifically, the HTLC sender sets a required TLV on the
`update_add_htlc` message and sends an onion message to the final
recipient. From there, the final recipient uses the included
`reply_path` to notify the sender's counterparty that they're
online and ready to receive the HTLC.

In order to fully flesh out the protocol as sketched, we'll need
to add an onion message mailbox service (which should be as simple
as a new feature bit), add PTLCs, and extensions to BOLT 12 to
allow signaling that the final recipient is often-offline. While
we could add such signaling to BOLT 11, there's not a whole lot of
reason to - if the recipient is able to provide an invoice,
they're currently online!

[1] https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003307.html
This builds on prior commits by adding the ability to fetch an invoice from an
always-online node on behalf of an often-offline recipient, e.g. a mobile node.

The idea is that often-offline recipients will supply some always-online node
such as their wallet vendor with a static (i.e. `payment_hash`-less) invoice to
return on its behalf. The recipient will then publish an offer containing
blinded paths that terminate at this always-online node, who payers can request
the invoice from if the recipient is offline at the time. After receiving the
static invoice, payers will commence the protocol outlined in [1] to send the
HTLC asynchronously.

[1]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003307.html
This field may be useful for often-offline recipients who did not receive the
invreq when it was originally sent, due to another node providing a static
invoice on their behalf. Recipients may want to verify the invreq or be
provided some other relevant data about the payment while remaining stateless
until an HTLC is actually received.
@valentinewallace valentinewallace marked this pull request as ready for review October 20, 2025 17:06
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.

3 participants