Skip to content

Commit

Permalink
Merge pull request #39 from ellemouton/bolt11-blinded-path
Browse files Browse the repository at this point in the history
blip-0039: BOLT 11 Invoice Blinded Path Tagged Field
  • Loading branch information
Roasbeef authored Aug 14, 2024
2 parents 5ea2017 + 8415112 commit 9a1bd0a
Show file tree
Hide file tree
Showing 2 changed files with 314 additions and 6 deletions.
13 changes: 7 additions & 6 deletions blip-0002.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ 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:

| Bits | Name | Description | Context | Dependencies | Link |
| --------- | ---------------------- | ----------------------------------------------------------- | ---------------- | -------------------------------- | -------------------------------- |
| 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) |
| 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) |
| Bits | Name | Description | Context | Dependencies | Link |
|---------|-----------------------|------------------------------------------------------------|---------|-------------------------|---------------------------|
| 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) |
| 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) |
| 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

Expand Down
307 changes: 307 additions & 0 deletions blip-0039.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
```
bLIP: 39
Title: BOLT 11 Invoice Blinded Path Tagged Field
Author: Elle Mouton <[email protected]>
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

0 comments on commit 9a1bd0a

Please sign in to comment.