Skip to content

Instantly share code, notes, and snippets.

@remyers
Last active December 18, 2023 02:35
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remyers/e0d2bedb7bc87371d1bdbbb6fff2edd1 to your computer and use it in GitHub Desktop.
Save remyers/e0d2bedb7bc87371d1bdbbb6fff2edd1 to your computer and use it in GitHub Desktop.
async-payments user story: donation QR code

The async-payment user story I'm interested in exploring is a mobile user (not always connected) who wants to receive donations (no PoP) via a static invoice from another mobile user.

My understanding of how this could work:

  1. The static invoice should contain a blinded route to the payment receiver via their LSP and an ephemeral public key that the payment sender will use to encrypt the last hop of a payment onion containing a keysend TLV. The LSP of the payment receiver must support store-and-forward of onion messages.

  2. A payment sender builds a payment onion where the first hop is their LSP that supports trampoline payments, onion messages and async-payments. The first hop of the onion includes a TLV to indicate the payment should be held until triggered (with a async-payment nonce) and gives the blinded route to the payment receiver. The last hop of the onion is encrypted to the payment receiver's ephemeral public key and includes:

  • the keysend TLV payment secret
  • the amount being sent
  1. After the payment sender updates their channel for the payment with their LSP, they send an onion message to the payment receiver using the receiver's blinded route. The onion message includes:
  • the blinded return route to the payment sender's LSP
  • the payment async-payment nonce
  1. The payment sender's LSP (first hop) holds the payment until triggered or timed out.

  2. The payment receiver's LSP (penultimate hop) queues the onion message from the payment sender until the message can be delivered.

  3. When the payment receiver reconnects to their LSP the onion message is delivered and the payment receiver sends a trigger onion message to the payment sender's LSP. This trigger message contains the payment nonce of the held payment.

  4. When the payment sender's LSP receives the trigger onion message it begins trying to forward the payment to the payment receiver via the blinded path given in the trampoline payment.

  5. The payment succeeds if the payment receiver completes the payment, or fails otherwise. The payment receiver receives the payment secret and expected amount in the keysend TLV of the onion they decrypt.

  6. The payment sender must also come online to settle the HTLC with their LSP sometime before it expires or their LSP will be forced to close the channel. The expiry timeout can be arbitrarily long to prevent unnecessary channel closes.

async-payments_donation_case (svg) async-payments_donation_case (jpg)

@remyers
Copy link
Author

remyers commented Jan 30, 2023

Note: There is also a "one-shot" version of this workflow that does not use the sender's trampoline node to generate/try multiple onions to the receiver at the time they receive a payment trigger onion message from the receiver.

In the "one-shot" version the sender builds the onion all the way to the destination. The "one-shot" onion will either succeed or fail once the receiver comes online and triggers the sender's LSP via an onion-message. No alternative onions will be tried.

The sender should use a long CLTV timeout to their LSP, but keep CLTV deltas from their LSP to the receiver within standard bounds. Otherwise the onion may be rejected by intermediate nodes.

Having a long timeout (eg. 1 week) to the sender's LSP ensures that the async-payment suceeds or fails within the standard CLTV window (~ 24 hours), but if the sender is not online for longer than that, their LSP will not be forced to close their channel.

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