diff --git a/blip-0002.md b/blip-0002.md index 3018f20..3b8700e 100644 --- a/blip-0002.md +++ b/blip-0002.md @@ -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 diff --git a/blip-0039.md b/blip-0039.md new file mode 100644 index 0000000..848b0b3 --- /dev/null +++ b/blip-0039.md @@ -0,0 +1,307 @@ +``` +bLIP: 39 +Title: BOLT 11 Invoice Blinded Path Tagged Field +Author: Elle Mouton +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