1
0
Fork 0
mirror of https://github.com/lightning/bolts.git synced 2025-03-13 19:37:31 +01:00
This commit is contained in:
valentinewallace 2025-01-18 04:39:45 +11:00 committed by GitHub
commit 373e5bcc80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 151 additions and 16 deletions

View file

@ -1972,6 +1972,25 @@ is destined, is described in [BOLT #4](04-onion-routing.md).
* [`sha256`:`payment_hash`] * [`sha256`:`payment_hash`]
* [`u32`:`cltv_expiry`] * [`u32`:`cltv_expiry`]
* [`1366*byte`:`onion_routing_packet`] * [`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`]
#### TLV fields for `held_htlc_available`
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`]
1. `tlv_stream`: `update_add_htlc_tlvs` 1. `tlv_stream`: `update_add_htlc_tlvs`
2. types: 2. types:
@ -2016,6 +2035,19 @@ A sending node:
- MUST increase the value of `id` by 1 for each successive offer. - MUST increase the value of `id` by 1 for each successive offer.
- if it is relaying a payment inside a blinded route: - if it is relaying a payment inside a blinded route:
- MUST set `path_key` (see [Route Blinding](04-onion-routing.md#route-blinding)) - MUST set `path_key` (see [Route Blinding](04-onion-routing.md#route-blinding))
- 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
- 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
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 `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. been received). It MUST continue incrementing instead.
@ -2047,6 +2079,12 @@ A receiving node:
- MUST respond with an error as detailed in [Failure Messages](04-onion-routing.md#failure-messages) - MUST respond with an error as detailed in [Failure Messages](04-onion-routing.md#failure-messages)
- Otherwise: - Otherwise:
- MUST follow the requirements for the reader of `payload` in [Payload Format](04-onion-routing.md#payload-format) - 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
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. 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. It commits to the HTLC by setting the `payment_hash` as associated data, i.e. includes the `payment_hash` in the computation of HMACs.
@ -2082,6 +2120,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) commitment transaction), resulting in a degraded channel. See [#728](https://github.com/lightningnetwork/lightning-rfc/issues/728)
for more details. 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` ### 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. For simplicity, a node can only remove HTLCs added by the other node.

View file

@ -189,6 +189,9 @@ This is formatted according to the Type-Length-Value format defined in [BOLT #1]
1. `tlv_stream`: `payload` 1. `tlv_stream`: `payload`
2. types: 2. types:
1. type: 1 (`invoice_request`)
2. data:
* [`...*byte`:`invoice_request_tlv_stream`]
1. type: 2 (`amt_to_forward`) 1. type: 2 (`amt_to_forward`)
2. data: 2. data:
* [`tu64`:`amt_to_forward`] * [`tu64`:`amt_to_forward`]
@ -214,6 +217,9 @@ This is formatted according to the Type-Length-Value format defined in [BOLT #1]
1. type: 18 (`total_amount_msat`) 1. type: 18 (`total_amount_msat`)
2. data: 2. data:
* [`tu64`:`total_msat`] * [`tu64`:`total_msat`]
1. type: 5482373484 (`sender_provided_payment_preimage`)
2. data:
* [`32*byte`:`payment_preimage`]
`short_channel_id` is the ID of the outgoing channel used to route the `short_channel_id` is the ID of the outgoing channel used to route the
message; the receiving peer should operate the other end of this channel. message; the receiving peer should operate the other end of this channel.
@ -240,6 +246,11 @@ The requirements ensure consistency in responding to an unexpected
`outgoing_cltv_value`, whether it is the final node or not, to avoid `outgoing_cltv_value`, whether it is the final node or not, to avoid
leaking its position in the route. leaking its position in the route.
`sender_provided_payment_preimage` and `invoice_request` are set in the case
that the recipient is often-offline and another node provided a static BOLT 12
invoice on their behalf, where `invoice_request` is the sender's originl
invoice request corresponding to this HTLC.
### Requirements ### Requirements
The creator of `encrypted_recipient_data` (usually, the recipient of payment): The creator of `encrypted_recipient_data` (usually, the recipient of payment):
@ -273,6 +284,14 @@ The writer of the TLV `payload`:
- MUST use the current block height as a baseline value. - MUST use the current block height as a baseline value.
- if a [random offset](07-routing-gossip.md#recommendations-for-routing) was added to improve privacy: - if a [random offset](07-routing-gossip.md#recommendations-for-routing) was added to improve privacy:
- SHOULD add the offset to the baseline value. - SHOULD add the offset to the baseline value.
- if paying to a static BOLT 12 invoice:
- MUST set `sender_provided_payment_preimage` to randomly generated unique bytes.
- MUST set `update_add_htlc.payment_hash` to match the SHA256 hash of
`sender_provided_payment_preimage`.
- MUST set `invoice_request` to the BOLT 12 invoice request
corresponding to this HTLC.
- otherwise:
- MUST NOT set `sender_provided_payment_preimage`.
- MUST NOT include any other tlv field. - MUST NOT include any other tlv field.
- For every node outside of a blinded route: - For every node outside of a blinded route:
- MUST include `amt_to_forward` and `outgoing_cltv_value`. - MUST include `amt_to_forward` and `outgoing_cltv_value`.
@ -324,6 +343,7 @@ The reader:
- MUST return an error if `amt_to_forward` is below what it expects for the payment. - MUST return an error if `amt_to_forward` is below what it expects for the payment.
- MUST return an error if incoming `cltv_expiry` < `outgoing_cltv_value`. - MUST return an error if incoming `cltv_expiry` < `outgoing_cltv_value`.
- MUST return an error if incoming `cltv_expiry` < `current_block_height` + `min_final_cltv_expiry_delta`. - MUST return an error if incoming `cltv_expiry` < `current_block_height` + `min_final_cltv_expiry_delta`.
- MUST use `sender_provided_payment_preimage` when claiming the HTLC, if present
- Otherwise (it is not part of a blinded route): - Otherwise (it is not part of a blinded route):
- MUST return an error if `path_key` is set in the incoming `update_add_htlc` or `current_path_key` is present. - MUST return an error if `path_key` is set in the incoming `update_add_htlc` or `current_path_key` is present.
- MUST return an error if `amt_to_forward` or `outgoing_cltv_value` are not present. - MUST return an error if `amt_to_forward` or `outgoing_cltv_value` are not present.

View file

@ -29,6 +29,7 @@ The Context column decodes as follows:
* `C+`: presented in the `channel_announcement` message, but always even (required). * `C+`: presented in the `channel_announcement` message, but always even (required).
* `9`: presented in [BOLT 11](11-payment-encoding.md) invoices. * `9`: presented in [BOLT 11](11-payment-encoding.md) invoices.
* `B`: presented in the `allowed_features` field of a blinded path. * `B`: presented in the `allowed_features` field of a blinded path.
* `R`: presented in [BOLT 12](12-offers.md) invoice requests.
| Bits | Name | Description | Context | Dependencies | Link | | Bits | Name | Description | Context | Dependencies | Link |
|-------|-----------------------------------|-----------------------------------------------------------|----------|---------------------------|-----------------------------------------------------------------------| |-------|-----------------------------------|-----------------------------------------------------------|----------|---------------------------|-----------------------------------------------------------------------|
@ -51,8 +52,15 @@ The Context column decodes as follows:
| 46/47 | `option_scid_alias` | Supply channel aliases for routing | IN | | [BOLT #2][bolt02-channel-ready] | | 46/47 | `option_scid_alias` | Supply channel aliases for routing | IN | | [BOLT #2][bolt02-channel-ready] |
| 48/49 | `option_payment_metadata` | Payment metadata in tlv record | 9 | | [BOLT #11](11-payment-encoding.md#tagged-fields) | | 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 | IN | `option_scid_alias` | [BOLT #2][bolt02-channel-ready] | | 50/51 | `option_zeroconf` | Understands zeroconf channel types | IN | `option_scid_alias` | [BOLT #2][bolt02-channel-ready] |
| 52/53 | `option_htlc_hold` | Hold HTLCs and forward on receipt of an onion message | IN | `option_onion_messages` |
| 56/57 | `option_om_mailbox` | Store-and-forward onion messages for often-offline peers | IN | `option_onion_messages` | [BOLT #12](bolt12-offers.md) |
| 59 | `static_invoice_pay` | Supports paying BOLT 12 static invoices | R | `option_onion_messages` | [BOLT #12](bolt12-offers.md) |
We define `option_om_mailbox` as the ability to store an onion message on behalf
of an offline peer, and forward it once the peer comes online (subject to rate
limiting).
## Requirements ## Requirements
The origin node: The origin node:

View file

@ -42,7 +42,7 @@ Here we use "user" as shorthand for the individual user's lightning
node and "merchant" as the shorthand for the node of someone who is node and "merchant" as the shorthand for the node of someone who is
selling or has sold something. selling or has sold something.
There are two basic payment flows supported by BOLT 12: There are three basic payment flows supported by BOLT 12:
The general user-pays-merchant flow is: The general user-pays-merchant flow is:
1. A merchant publishes an *offer*, such as on a web page or a QR code. 1. A merchant publishes an *offer*, such as on a web page or a QR code.
@ -58,6 +58,19 @@ The merchant-pays-user flow (e.g. ATM or refund):
3. The merchant confirms the *invoice_node_id* to ensure it's about to pay the correct 3. The merchant confirms the *invoice_node_id* to ensure it's about to pay the correct
person, and makes a payment to the invoice. person, and makes a payment to the invoice.
The pay-mobile-user flow (e.g. paying a friend back to their mobile node):
1. The mobile user supplies some always-online node with a static (i.e.
`payment_hash`-less) invoice to return on its behalf. This always-online node may
be the mobile user's channel counterparty, wallet vendor, or another node on the
network that it has an out-of-band relationship with.
2. The mobile user publishes an offer that contains blinded paths that terminate
at the always-online node.
3. The payer sends an `invoice_request` to the always-online node, who replies
with the static invoice previously provided by the mobile user if the mobile user
is offline. If they are online, the `invoice_request` is forwarded to the mobile
user as usual.
4. The payer makes a payment to the mobile user as indicated by the invoice.
## Payment Proofs and Payer Proofs ## Payment Proofs and Payer Proofs
Note that the normal lightning "proof of payment" can only demonstrate that an Note that the normal lightning "proof of payment" can only demonstrate that an
@ -70,6 +83,9 @@ to request the invoice. In addition, the Merkle construction of the BOLT 12
invoice signature allows the user to reveal invoice fields in case invoice signature allows the user to reveal invoice fields in case
of a dispute selectively. of a dispute selectively.
Payers will not get proofs in the case that they received a static invoice from the
payee, see the pay-mobile-user flow above.
# Encoding # Encoding
Each of the forms documented here are in Each of the forms documented here are in
@ -261,8 +277,9 @@ A writer of an offer:
after midnight 1 January 1970, UTC that invoice_request should not be after midnight 1 January 1970, UTC that invoice_request should not be
attempted. attempted.
- if it is connected only by private channels: - if it is connected only by private channels:
- MUST include `offer_paths` containing one or more paths to the node from - MUST include `offer_paths` containing one or more paths to the node
publicly reachable nodes. that will reply to the `invoice_request`, using introduction nodes that are
publicly reachable.
- otherwise: - otherwise:
- MAY include `offer_paths`. - MAY include `offer_paths`.
- if it includes `offer_paths`: - if it includes `offer_paths`:
@ -282,6 +299,8 @@ A writer of an offer:
- MUST set `offer_quantity_max` to 0. - MUST set `offer_quantity_max` to 0.
- otherwise: - otherwise:
- MUST NOT set `offer_quantity_max`. - MUST NOT set `offer_quantity_max`.
- if it is often-offline and the invoice may be provided by another node on their behalf:
- MUST NOT include more than 1 chain in `offer_chains`.
A reader of an offer: A reader of an offer:
- if the offer contains any TLV fields outside the inclusive ranges: 1 to 79 and 1000000000 to 1999999999: - if the offer contains any TLV fields outside the inclusive ranges: 1 to 79 and 1000000000 to 1999999999:
@ -447,6 +466,20 @@ while still allowing signature validation.
2. data: 2. data:
* [`bip340sig`:`sig`] * [`bip340sig`:`sig`]
## Invoice Request Features
| Bits | Description | Name |
|------|----------------------------------|-----------------------------|
| 59 | Supports paying static invoices | static_invoice_pay/optional |
Setting `static_invoice_pay` indicates that the payer supports receiving a
`payment_hash`-less invoice in response to their `invoice_request`, and
subsequently setting `sender_provided_payment_preimage` in their payment onion.
Useful if the payee is often offline and the invoice is being returned on
their behalf by another node, to avoid trusting that other node to not reuse a
`payment_hash`.
## Requirements for Invoice Requests ## Requirements for Invoice Requests
The writer: The writer:
@ -543,7 +576,14 @@ The reader:
`0`-`9`, `a`-`z`, `A`-`Z`, `-`, `_` or `.`. `0`-`9`, `a`-`z`, `A`-`Z`, `-`, `_` or `.`.
- otherwise: - otherwise:
- MUST reject the invoice request if `invreq_chain`.`chain` is not a supported chain. - MUST reject the invoice request if `invreq_chain`.`chain` is not a supported chain.
- if receiving the `invoice_request` on behalf of an often-offline payee:
- if the payee is online:
- MUST forward the `invoice_request` to the payee
- otherwise (payee is offline):
- if `invreq_features` supports `static_invoice_pay`:
- MUST reply with the static invoice previously provided by the payee
- otherwise:
- MUST reply with `invoice_error`
## Rationale ## Rationale
@ -574,10 +614,11 @@ The requirement to use `offer_paths` if present, ensures a node does not reveal
# Invoices # Invoices
Invoices are a payment request, and when the payment is made, Invoices are a payment request. If `invoice_payment_hash` is set, then when the
the payment preimage can be combined with the invoice to form a cryptographic receipt. payment is made, the payment preimage can be combined with the invoice to form a
cryptographic receipt.
The recipient sends an `invoice` in response to an `invoice_request` using The recipient creates an `invoice` for responding to an `invoice_request` using
the `onion_message` `invoice` field. the `onion_message` `invoice` field.
1. `tlv_stream`: `invoice` 1. `tlv_stream`: `invoice`
@ -666,6 +707,9 @@ the `onion_message` `invoice` field.
1. type: 176 (`invoice_node_id`) 1. type: 176 (`invoice_node_id`)
2. data: 2. data:
* [`point`:`node_id`] * [`point`:`node_id`]
1. type: 178 (`invoice_message_paths`)
2. data:
* [`...*blinded_path`:`paths`]
1. type: 240 (`signature`) 1. type: 240 (`signature`)
2. data: 2. data:
* [`bip340sig`:`sig`] * [`bip340sig`:`sig`]
@ -704,15 +748,19 @@ may (due to capacity limits on a single channel) require it.
A writer of an invoice: A writer of an invoice:
- MUST set `invoice_created_at` to the number of seconds since Midnight 1 - MUST set `invoice_created_at` to the number of seconds since Midnight 1
January 1970, UTC when the invoice was created. January 1970, UTC when the invoice was created.
- MUST set `invoice_amount` to the minimum amount it will accept, in units of - if `invoice_payment_hash` is set and the invoice is in response to an `invoice_request`:
the minimal lightning-payable unit (e.g. milli-satoshis for bitcoin) for
`invreq_chain`.
- if the invoice is in response to an `invoice_request`:
- MUST copy all non-signature fields from the invoice request (including unknown fields). - MUST copy all non-signature fields from the invoice request (including unknown fields).
- if `invreq_amount` is present: - if `invreq_amount` is present:
- MUST set `invoice_amount` to `invreq_amount` - MUST set `invoice_amount` to `invreq_amount`
- otherwise: - otherwise:
- MUST set `invoice_amount` to the *expected amount*. - MUST set `invoice_amount` to the *expected amount*.
- if the invoice is intended to be provided by a node other than the recipient:
- MUST NOT set `invoice_payment_hash`.
- MUST NOT set `invoice_amount`.
- MUST include `invoice_message_paths` containing at least two paths to
the recipient, where the penultimate hop supports `option_om_mailbox`.
- MUST NOT set any `invoice_request` TLV fields
- otherwise:
- MUST set `invoice_payment_hash` to the SHA256 hash of the - MUST set `invoice_payment_hash` to the SHA256 hash of the
`payment_preimage` that will be given in return for payment. `payment_preimage` that will be given in return for payment.
- if `offer_issuer_id` is present: - if `offer_issuer_id` is present:
@ -740,11 +788,14 @@ A writer of an invoice:
- MUST include `invoice_blindedpay` with exactly one `blinded_payinfo` for each `blinded_path` in `paths`, in order. - MUST include `invoice_blindedpay` with exactly one `blinded_payinfo` for each `blinded_path` in `paths`, in order.
- MUST set `features` in each `blinded_payinfo` to match `encrypted_data_tlv`.`allowed_features` (or empty, if no `allowed_features`). - MUST set `features` in each `blinded_payinfo` to match `encrypted_data_tlv`.`allowed_features` (or empty, if no `allowed_features`).
- SHOULD ignore any payment which does not use one of the paths. - SHOULD ignore any payment which does not use one of the paths.
- if providing invoices on behalf of an often offline recipient:
- MAY reuse the previous invoice.
A reader of an invoice: A reader of an invoice:
- MUST reject the invoice if `invoice_amount` is not present.
- MUST reject the invoice if `invoice_created_at` is not present. - MUST reject the invoice if `invoice_created_at` is not present.
- if `static_invoice_pay` was not supported in `invreq_features`:
- MUST reject the invoice if `invoice_payment_hash` is not present. - MUST reject the invoice if `invoice_payment_hash` is not present.
- MUST reject the invoice if `invoice_amount` is not present.
- MUST reject the invoice if `invoice_node_id` is not present. - MUST reject the invoice if `invoice_node_id` is not present.
- if `invreq_chain` is not present: - if `invreq_chain` is not present:
- MUST reject the invoice if bitcoin is not a supported chain. - MUST reject the invoice if bitcoin is not a supported chain.
@ -766,6 +817,7 @@ A reader of an invoice:
- MUST NOT use the corresponding `invoice_paths`.`path` if `payinfo`.`features` has any unknown even bits set. - MUST NOT use the corresponding `invoice_paths`.`path` if `payinfo`.`features` has any unknown even bits set.
- MUST reject the invoice if this leaves no usable paths. - MUST reject the invoice if this leaves no usable paths.
- if the invoice is a response to an `invoice_request`: - if the invoice is a response to an `invoice_request`:
- if `invoice_payment_hash` is set:
- MUST reject the invoice if all fields in ranges 0 to 159 and 1000000000 to 2999999999 (inclusive) do not exactly match the invoice request. - MUST reject the invoice if all fields in ranges 0 to 159 and 1000000000 to 2999999999 (inclusive) do not exactly match the invoice request.
- if `offer_issuer_id` is present (invoice_request for an offer): - if `offer_issuer_id` is present (invoice_request for an offer):
- MUST reject the invoice if `invoice_node_id` is not equal to `offer_issuer_id` - MUST reject the invoice if `invoice_node_id` is not equal to `offer_issuer_id`
@ -795,6 +847,10 @@ A reader of an invoice:
- MUST reject the invoice if it arrived via a blinded path. - MUST reject the invoice if it arrived via a blinded path.
- otherwise (derived from an offer): - otherwise (derived from an offer):
- MUST reject the invoice if it did not arrive via invoice request `onionmsg_tlv` `reply_path`. - MUST reject the invoice if it did not arrive via invoice request `onionmsg_tlv` `reply_path`.
- if `invoice_payment_hash` is unset:
- MUST reject the invoice if `invoice_message_paths` is not present or is empty.
- MUST pay asynchronously using the `held_htlc_available` onion message
flow, where the onion message is sent over `invoice_message_paths`.
## Rationale ## Rationale