mirror of
https://github.com/lightning/blips.git
synced 2024-11-19 00:50:02 +01:00
blip-39: BOLT 11 Invoice Blinded Path Tagged Field
This commit is contained in:
parent
5ea2017bfe
commit
8415112010
@ -46,11 +46,12 @@ Custom feature bits used in the `I` [Bolt 11](https://github.com/lightning/bolts
|
|||||||
bLIPs may reserve feature bits by adding them to the following table:
|
bLIPs may reserve feature bits by adding them to the following table:
|
||||||
|
|
||||||
| Bits | Name | Description | Context | Dependencies | Link |
|
| Bits | Name | Description | Context | Dependencies | Link |
|
||||||
| --------- | ---------------------- | ----------------------------------------------------------- | ---------------- | -------------------------------- | -------------------------------- |
|
|---------|-----------------------|------------------------------------------------------------|---------|-------------------------|---------------------------|
|
||||||
| 54/55 | `keysend` | A form of spontaneous payment | N | `var_onion_optin` | [bLIP 3](./blip-0003.md) |
|
| 54/55 | `keysend` | A form of spontaneous payment | N | `var_onion_optin` | [bLIP 3](./blip-0003.md) |
|
||||||
| 256/257 | `hosted_channels` | This node accepts requests for hosted channels | IN | | [bLIP 17](./blip-0017.md) |
|
| 256/257 | `hosted_channels` | This node accepts requests for hosted channels | IN | | [bLIP 17](./blip-0017.md) |
|
||||||
| 258/259 | `dns_resolver` | This node accepts DNSSEC proof requests | N | | [bLIP 32](./blip-0032.md) |
|
| 258/259 | `dns_resolver` | This node accepts DNSSEC proof requests | N | | [bLIP 32](./blip-0032.md) |
|
||||||
| 260/261 | `htlc_endorsement` | This node forwards experimental htlc endorsement signals | N | | [bLIP 4](./blip-004.md) |
|
| 260/261 | `htlc_endorsement` | This node forwards experimental htlc endorsement signals | N | | [bLIP 4](./blip-004.md) |
|
||||||
|
| 262/263 | `bolt11_blinded_path` | This invoice may contain a new blinded path tagged field | I | `option_route_blinding` | [bLIP 39](./blip-0039.md) |
|
||||||
|
|
||||||
### Messages
|
### Messages
|
||||||
|
|
||||||
|
307
blip-0039.md
Normal file
307
blip-0039.md
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
```
|
||||||
|
bLIP: 39
|
||||||
|
Title: BOLT 11 Invoice Blinded Path Tagged Field
|
||||||
|
Author: Elle Mouton <elle.mouton@gmail.com>
|
||||||
|
Status: Draft
|
||||||
|
Created: 2024-07-08
|
||||||
|
* Post-History: 2024-06-26: https://delvingbitcoin.org/t/blip-bolt-11-invoice-blinded-path-tagged-field/991
|
||||||
|
License: CC0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Abstract
|
||||||
|
|
||||||
|
This bLIP defines a new [tagged field][tagged-fields] for the payment invoice
|
||||||
|
encoding described by [BOLT 11][bolt11] which can be used to communicate
|
||||||
|
encoded blinded path information to the payer of the invoice.
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
This bLIP is licensed under the CC0 license.
|
||||||
|
|
||||||
|
## Rational
|
||||||
|
|
||||||
|
Blinded paths have been included in the [BOLT 4 specification][blinded-paths]
|
||||||
|
and using them in the context of receiving payments is natively supported in
|
||||||
|
the [BOLT 12 Offers proposal][offers]. However, the Offers proposal also
|
||||||
|
includes various other dependencies such as onion messaging and various new
|
||||||
|
protocol message all of which will require a network wide upgrade before full
|
||||||
|
advantage can be taken of the new protocol. Blinded paths themselves are a
|
||||||
|
useful tool for privacy and potentially more reliable payment delivery due to
|
||||||
|
receiver being able to select paths it knows to be more reliable. This document
|
||||||
|
proposes a carve-out to the existing [BOLT 11][bolt11] invoice format so that
|
||||||
|
testing of blinded paths can be done in implementations that have not yet
|
||||||
|
implemented the full Offers specification. This will be done by adding a new
|
||||||
|
tagged-field type to the BOLT 11 invoice specification that will encode a
|
||||||
|
blinded payment path. With this bLIP, the sender and the receiver of a payment
|
||||||
|
will need to be aware of the new tagged-field and the receiver will need to
|
||||||
|
support route blinding and ideally have direct channel peers who also support
|
||||||
|
route blinding in order to start widening their anonymity set.
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
### Feature Bit
|
||||||
|
|
||||||
|
A new feature bit, `bolt11_blinded_path`, for the `I` context will be added
|
||||||
|
using bits from the experimental range. This is required because the BOLT 11
|
||||||
|
tagged-fields pre-date the TLV format and so nodes parsing the invoice will just
|
||||||
|
skip fields they don't know as there is no concept of "It's OK to be odd". This
|
||||||
|
feature bit thus allows nodes to fail fast if they do not yet understand the new
|
||||||
|
tagged field.
|
||||||
|
|
||||||
|
### Tagged Field
|
||||||
|
|
||||||
|
The proposal is to add the following new [tagged field][tagged-fields] to the
|
||||||
|
set defined in [BOLT 11][bolt11]:
|
||||||
|
|
||||||
|
- `b` (20): `data_length` variable. One or more entries each containing a
|
||||||
|
blinded payment path for a private route; there may be more than one `b`
|
||||||
|
field. The field uses the `blinded_payinfo` type described below which draws
|
||||||
|
heavily on the proposed encoding of the `blinded_payinfo` subtype defined in
|
||||||
|
the [Offers proposal][offers].
|
||||||
|
|
||||||
|
1. subtype: `blinded_payinfo`
|
||||||
|
2. data:
|
||||||
|
* [`u32`:`fee_base_msat`]
|
||||||
|
* [`u32`:`fee_proportional_millionths`]
|
||||||
|
* [`u16`:`cltv_expiry_delta`]
|
||||||
|
* [`u64`:`htlc_minimum_msat`]
|
||||||
|
* [`u64`:`htlc_maximum_msat`]
|
||||||
|
* [`u16`:`flen`]
|
||||||
|
* [`flen*byte`:`features`]
|
||||||
|
* [`33*byte`:`first_ephemeral_blinding_point`]
|
||||||
|
* [`byte`:`num_hops`]
|
||||||
|
* [`num_hops*blinded_hop`:`blinded_hops`]
|
||||||
|
|
||||||
|
1. subtype: `blinded_hop`
|
||||||
|
2. data:
|
||||||
|
* [`33*byte`:`blinded_node_pubkey`]
|
||||||
|
* [`bigsize`: `cipher_text_length`]
|
||||||
|
* [`cipher_text_length*byte`:`cipher_text`]
|
||||||
|
|
||||||
|
The `blinded_node_pubkey` of the first `blinded_hop` in a `blinded_payinfo` is
|
||||||
|
the real public key of the blinded path's introduction node. This encoding was
|
||||||
|
chosen so that `num_hops` accurately reflects the true number of hops including
|
||||||
|
the introduction node while keeping the number of bytes required for the
|
||||||
|
encoding to a minimum. The `cipher_text` is the `encrypted_recipient_data` as
|
||||||
|
defined in [BOLT 4 TLV payload][bolt4-payload].
|
||||||
|
|
||||||
|
The `fee_base_msat`, `fee_proportional_millionths` and `cltv_expiry_delta` are
|
||||||
|
the accumulated blinded route policy values as defined in [BOLT 4][bolt4-relay].
|
||||||
|
`features` is the set of features for the path, `first_ephemeral_blinding_point`
|
||||||
|
is the blinding point that must be communicated to the introduction node via the
|
||||||
|
`blinding` field of the [`payload`][bolt4-payload] type.
|
||||||
|
|
||||||
|
** Note: see discussion section for question around communicating
|
||||||
|
`max_cltv_expiry` **
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
An invoice containing the `b` field type:
|
||||||
|
- MUST not contain the `r` field type.
|
||||||
|
- MUST not contain the `s` field type since a payment address in the context of
|
||||||
|
blinded payments does not make sense since the recipient is able to use the
|
||||||
|
`path_id` in the `encrypted_recipient_data` for the same purpose.
|
||||||
|
- SHOULD sign the invoice with a private key that is not the same as their
|
||||||
|
public node ID and should not set the destination node (`n` field).
|
||||||
|
- Each `blinded_path` must fit within the `data_length` size limit. This places
|
||||||
|
an upper limit of approximately 7 `blinded_hops` on each path. See the
|
||||||
|
appendix for the estimation calculation.
|
||||||
|
- If the invoice will be displayed in QR form, then this also places an upper
|
||||||
|
limit on the number of `blinded_path` fields that can be added to the
|
||||||
|
invoice.
|
||||||
|
- The existing `c` field (`min_final_cltv_expiry_delta`) is meaningless for an
|
||||||
|
invoice containing the `b` field since this value is expected to be accounted
|
||||||
|
for in each path's accumulated `cltv_expiry_delta`.
|
||||||
|
- The existing invoice `expiry` field along with the `timestamp` field
|
||||||
|
should be used to communicate the `max_cltv_expiry` of the blinded paths in
|
||||||
|
the invoice. The reader should use the 10-minutes-per-block assumption to
|
||||||
|
calculate an estimation of the `max_cltv_exipiry` value.
|
||||||
|
|
||||||
|
## Universality
|
||||||
|
|
||||||
|
This proposal is a temporary measure that will allow users to start making use
|
||||||
|
of blinded paths in the context of payments and thereby take advantage of the
|
||||||
|
potential privacy and payment success rate benefits that they will in theory
|
||||||
|
provide. Once the Offers protocol along with its new invoice format has been
|
||||||
|
widely deployed, then there will be no use for this BOLT 11 carve-out. Due to
|
||||||
|
the forcasted temporary use of the new field, it makes sense to be in bLIP form
|
||||||
|
rather than adding this in a more temporary way to the spec via a BOLT update
|
||||||
|
proposal. The intent is that this will be used mostly for testing of blinded
|
||||||
|
paths in implementations that have not yet implemented the full Offers spec.
|
||||||
|
|
||||||
|
## Backwards Compatibility
|
||||||
|
|
||||||
|
BOLT 11 states that the reader of an invoice "MUST skip over unknown fields".
|
||||||
|
This means that an un-updated reader of an invoice that includes the new tagged
|
||||||
|
field would skip it when parsing the invoice. The proposal also adds a new
|
||||||
|
feature bit to the invoice feature bit vector and so this gives nodes an
|
||||||
|
indication that the invoice includes something they do not yet understand.
|
||||||
|
Even if un-upgraded senders did not check the feature bit vector, they would not
|
||||||
|
be able to use the invoice as, without knowledge of the blinded path field, it
|
||||||
|
does not contain enough information to attempt a payment since no routing hints
|
||||||
|
will be included and the invoice will be signed with a random ephemeral key
|
||||||
|
meaning that the derived destination node would not correspond to a real node
|
||||||
|
in the graph.
|
||||||
|
|
||||||
|
## Reference Implementations
|
||||||
|
|
||||||
|
The proposed encoding of the new BOLT 11 tagged-field is added to the LND
|
||||||
|
implementation in [this PR][impl].
|
||||||
|
|
||||||
|
## Appendix
|
||||||
|
|
||||||
|
### Test Vector
|
||||||
|
|
||||||
|
The following string is an example of a BOLT11 invoice containing 2 blinded
|
||||||
|
paths, one with 1 hop and one with 3 hops.
|
||||||
|
|
||||||
|
```
|
||||||
|
lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4js5fdqqqqq2qqqqqpgqyzqqqqqqqqqqqqyqqqqqqqqqqqvsqqqqlnxy0ffrlt2y2jgtzw89kgr3zg4dlwtlfycn3yuek8x5eucnuchqps82xf0m2u6sx5wnjw7xxgnxz5kf09quqsv5zvkgj7d5kpzttp4qz7q5qsyqcyq5pzq2feycsemrh7wvendc4kw3tsmkt25a36ev6kfehrv7ecfkrp5zs9q5zqxqspqtr4avek5quzjn427asptzews5wrczfhychr2sq6ue9phmn35tjqcrspqgpsgpgxquyqjzstpsxsu59zqqqqqpqqqqqqyqq2qqqqqqqqqqqqqqqqqqqqqqqqpgqqqqk8t6endgpc99824amqzk9japgu8synwf3wx4qp4ej2r0h8rghypsqsygpf8ynzr8vwleenxdhzke69wrwed2nk8t9n2e8xudnm8pxcvxs2q5qsyqcyq5y4rdlhtf84f8rgdj34275juwls2ftxtcfh035863q3p9k6s94hpxhdmzfn5gxpsazdznxs56j4vt3fdhe00g9v2l3szher50hp4xlggqkxf77f
|
||||||
|
```
|
||||||
|
|
||||||
|
Breakdown:
|
||||||
|
|
||||||
|
This invoice was signed with `priv_key`=`e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734`.
|
||||||
|
It does _not_ contain a payment secret.
|
||||||
|
|
||||||
|
* `lnbc`: prefix, Lightning on Bitcoin mainnet
|
||||||
|
* `20m`: amount (20 milli-bitcoin)
|
||||||
|
* `1`: Bech32 separator
|
||||||
|
* `pvjluez`: timestamp (1496314658)
|
||||||
|
* `p`: payment hash (0001020304050607080900010203040506070809000102030405060708090102)
|
||||||
|
* `d`: description: '1 cup coffee'
|
||||||
|
* `b`: blinded path:
|
||||||
|
* `fee_base_msat`: 40
|
||||||
|
* `fee_proportional_millionths`: 20
|
||||||
|
* `cltv_expiry_delta`: 130
|
||||||
|
* `htlc_minimum_msat`: 2
|
||||||
|
* `htlc_maximum_msat`: 100
|
||||||
|
* `flen`: 0
|
||||||
|
* `first_ephemeral_blinding_point`: 03f3311e948feb5115242c4e396c81c448ab7ee5fd24c4e24e66c73533cc4f98b8
|
||||||
|
* `num_hops`: 3
|
||||||
|
* `blinded_hops`:
|
||||||
|
* `blinded_node_pubkey`: 03a8c97ed5cd40d474e4ef18c899854b25e5070106504cb225e6d2c112d61a805e
|
||||||
|
* `cipher_text`: 0102030405
|
||||||
|
* `blinded_node_pubkey`: 0220293926219d8efe733336e2b674570dd96aa763acb3564e6e367b384d861a0a
|
||||||
|
* `cipher_text`: 0504030201
|
||||||
|
* `blinded_node_pubkey`: 02c75eb336a038294eaaf760158b2e851c3c0937262e35401ae64a1bee71a2e40c
|
||||||
|
* `cipher_text`: 0102030405060708090a0b0c0d0e
|
||||||
|
* `b`: blinded path:
|
||||||
|
* `fee_base_msat`: 4
|
||||||
|
* `fee_proportional_millionths`: 2
|
||||||
|
* `cltv_expiry_delta`: 10
|
||||||
|
* `htlc_minimum_msat`: 0
|
||||||
|
* `htlc_maximum_msat`: 10
|
||||||
|
* `flen`: 0
|
||||||
|
* `first_ephemeral_blinding_point`: 02c75eb336a038294eaaf760158b2e851c3c0937262e35401ae64a1bee71a2e40c
|
||||||
|
* `num_hops`: 1
|
||||||
|
* `blinded_hops`:
|
||||||
|
* `blinded_node_pubkey`: 0220293926219d8efe733336e2b674570dd96aa763acb3564e6e367b384d861a0a
|
||||||
|
* `cipher_text`: 0102030405
|
||||||
|
|
||||||
|
### Size Restrictions
|
||||||
|
|
||||||
|
#### `data_length` Limit
|
||||||
|
|
||||||
|
In order to conform to any existing BOLT 11 invoice parser, each new tagged
|
||||||
|
field must use the `data_length` encoding defined there. This means that the
|
||||||
|
maximum size of any _single_ encoded blinded path is 639 bytes.
|
||||||
|
|
||||||
|
What follows is a rough estimation of the maximum number of hops we can include
|
||||||
|
in a single blinded path. It assumes that each hop's cipher text is the same
|
||||||
|
length.
|
||||||
|
|
||||||
|
##### Cipher Text Size Estimation
|
||||||
|
|
||||||
|
First, a rough estimation of the average cipher text length is required. A
|
||||||
|
forwarding node in a blinded path will receive a cipher text payload containing
|
||||||
|
the following data:
|
||||||
|
|
||||||
|
- `padding`: optional
|
||||||
|
- `short_channel_id` of 8 bytes
|
||||||
|
- `payment_relay`:
|
||||||
|
* 2 byte `cltv_expiry_delta`
|
||||||
|
* 4 byte `fee_proportional_millionths`
|
||||||
|
* 4 byte `fee_base_msat`
|
||||||
|
- `payment_constraints`:
|
||||||
|
* 4 byte `max_cltv_expiry`
|
||||||
|
* 8 byte `htlc_minimum_msat`
|
||||||
|
- `allowed_features`: optional
|
||||||
|
|
||||||
|
If we [assume that the `allowed_features` vector is not
|
||||||
|
set][empty-allowed-features], then this comes to a total of 30 mandatory bytes.
|
||||||
|
|
||||||
|
For the recipient node, it will receive a cipher text payload containing:
|
||||||
|
|
||||||
|
- `padding`: optional
|
||||||
|
- `path_id`: let's assume that this is 32 bytes like the existing payment
|
||||||
|
address.
|
||||||
|
- `payment_constraints`:
|
||||||
|
* 4 byte `max_cltv_expiry`
|
||||||
|
* 8 byte `htlc_minimum_msat`
|
||||||
|
|
||||||
|
This comes to a total of 44 bytes for the recipient's cipher text.
|
||||||
|
|
||||||
|
The padding field should be used by recipients to pad cipher text blobs so that
|
||||||
|
all are the same size. Since the calculated recipient cipher text blob size (44)
|
||||||
|
is larger than that of the forwarding nodes (30), we can assume that all the
|
||||||
|
cipher text blobs will have a size of around 44 bytes.
|
||||||
|
|
||||||
|
##### `blinded_hop` Size Estimation
|
||||||
|
|
||||||
|
The total number of bytes required for a single `blinded_hop` is:
|
||||||
|
|
||||||
|
= 33+bigsize_len(cipher_text)+len(cipher_text)
|
||||||
|
|
||||||
|
If we use the estimated `cipher_text` size of 44 bytes, then
|
||||||
|
`bigsize_len(cipher_text)` is 1 and so this comes to 78 bytes for a single
|
||||||
|
`blinded_hop`.
|
||||||
|
|
||||||
|
##### `blinded_payinfo` Size Estimation
|
||||||
|
|
||||||
|
The total number of bytes required for the encoding of a single
|
||||||
|
`blinded_payinfo` entry is:
|
||||||
|
|
||||||
|
= 4+4+2+8+8+2+len(features)+33+1+(num_hops*len(blinded_hop))
|
||||||
|
= 68+len(features)+(num_hops*len(blinded_hop))
|
||||||
|
|
||||||
|
If we take the estimate of 78 bytes per `blinded_hop` and if we assume an empty
|
||||||
|
feature vector then this comes to:
|
||||||
|
|
||||||
|
= 68+(num_hops*78)
|
||||||
|
|
||||||
|
The maximum number of hops in a single blinded path can then be calculated to
|
||||||
|
be:
|
||||||
|
|
||||||
|
639 = 68+(num_hops*78)
|
||||||
|
num_hops = 7
|
||||||
|
|
||||||
|
#### QR code limit
|
||||||
|
|
||||||
|
Another soft maximum value to keep in mind is the maximum number of bytes that
|
||||||
|
can fit into a [QR code][qr] which is 2,953 bytes. This is a soft maximum
|
||||||
|
because this only applies if the invoice is in fact being transmitted via QR
|
||||||
|
code. This limit does not apply if the invoice is being transmitted via other
|
||||||
|
protocols such as LNURL. In the cases where the limit does apply, then two
|
||||||
|
variables will be at play:
|
||||||
|
|
||||||
|
- The number of blinded paths
|
||||||
|
- The number of blinded hops within each path (which will always also be
|
||||||
|
restricted by the `data_length` maximum).
|
||||||
|
|
||||||
|
The exact limit on the number of blinded paths that can be included depends on
|
||||||
|
the size of other fields in the invoice. It is worth noting that an invoice with
|
||||||
|
a blinded path should not contain any `r` (route hint) fields.
|
||||||
|
|
||||||
|
[tagged-fields]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md#tagged-fields
|
||||||
|
[bolt11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
|
||||||
|
[bolt4-payload]: https://github.com/lightning/bolts/blob/master/04-onion-routing.md#payload-format
|
||||||
|
[bolt4-relay]: https://github.com/lightning/bolts/blob/master/04-onion-routing.md#requirements
|
||||||
|
[blinded-paths]: https://github.com/lightning/bolts/blob/master/04-onion-routing.md#route-blinding
|
||||||
|
[offers]: https://github.com/lightning/bolts/pull/798
|
||||||
|
[impl]: https://github.com/lightningnetwork/lnd/pull/8752
|
||||||
|
[qr]: https://en.wikipedia.org/wiki/QR_code#Information_capacity
|
||||||
|
[lnurl]: https://github.com/lnurl/luds
|
||||||
|
[rb-proposal]: https://github.com/lightning/bolts/blob/c562d91ace0e95bec3c6f8758969eaf3627f23c8/proposals/route-blinding.md?plain=1#L274
|
||||||
|
[max_cltv_expiry]: https://github.com/lightning/bolts/pull/798/files#r1053000804
|
||||||
|
[empty-allowed-features]: https://github.com/lightning/bolts/blob/c562d91ace0e95bec3c6f8758969eaf3627f23c8/04-onion-routing.md?plain=1#L253
|
Loading…
Reference in New Issue
Block a user