diff --git a/.aspell.en.pws b/.aspell.en.pws index bf7e2213a..5ff04bfea 100644 --- a/.aspell.en.pws +++ b/.aspell.en.pws @@ -367,6 +367,8 @@ fips rfc varint CompactSize +multipath +mpp tlvs snprintf GitHub diff --git a/04-onion-routing.md b/04-onion-routing.md index 17851c7a8..1b562a0ba 100644 --- a/04-onion-routing.md +++ b/04-onion-routing.md @@ -248,18 +248,111 @@ This is a more flexible format, which avoids the redundant `short_channel_id` fi 1. type: 6 (`short_channel_id`) 2. data: * [`short_channel_id`:`short_channel_id`] + 1. type: 8 (`payment_data`) + 2. data: + * [`32*byte`:`payment_secret`] + * [`tu64`:`total_msat`] ### Requirements The writer: - - MUST include `amt_to_forward` and `outgoing_cltv_value` for every node. - - MUST include `short_channel_id` for every non-final node. - - MUST NOT include `short_channel_id` for the final node. + - Unless `node_announcement`, `init` message or the [BOLT #11](11-payment-encoding.md#tagged-fields) offers feature `var_onion_optin`: + - MUST use the legacy payload format instead. + - For every node: + - MUST include `amt_to_forward` and `outgoing_cltv_value`. + - For every non-final node: + - MUST include `short_channel_id` + - MUST NOT include `payment_data` + - For the final node: + - MUST NOT include `short_channel_id` + - if the recipient provided `payment_secret`: + - MUST include `payment_data` + - MUST set `payment_secret` to the one provided + - MUST set `total_msat` to the total amount it will send The reader: - MUST return an error if `amt_to_forward` or `outgoing_cltv_value` are not present. + - if it is the final node: + - MUST treat `total_msat` as if it were equal to `amt_to_forward` if it + is not present. + +The requirements for the contents of these fields are specified [above](#legacy-hop_data-payload-format) +and [below](#basic-multi-part-payments). + +### Basic Multi-Part Payments + +An HTLC may be part of a larger "multi-part" payment: such +"base" atomic multipath payments will use the same `payment_hash` for +all paths. + +Note that `amt_to_forward` is the amount for this HTLC only: a +`total_msat` field containing a greater value is a promise by the +ultimate sender that the rest of the payment will follow in succeeding +HTLCs; we call these outstanding HTLCs which have the same preimage, +an "HTLC set". + +#### Requirements -The requirements for the contents of these fields are specified [above](#legacy-hop_data-payload-format). +The writer: + - if the invoice offers the `basic_mpp` feature: + - MAY send more than one HTLC to pay the invoice. + - MUST use the same `payment_hash` on all HTLCs in the set. + - SHOULD send all payments at approximately the same time. + - SHOULD try to use diverse paths to the recipient for each HTLC. + - SHOULD retry and/or re-divide HTLCs which fail. + - if the invoice specifies an `amount`: + - MUST set `total_msat` to at least that `amount`, and less + than or equal to twice `amount`. + - otherwise: + - MUST set `total_msat` to the amount it wishes to pay. + - MUST ensure that the total `amount_msat` of the HTLC set which arrives at the payee + is equal to `total_msat`. + - MUST NOT send another HTLC if the total `amount_msat` of the HTLC set is already greater or equal to `total_msat`. + - otherwise: + - MUST set `total_msat` equal to `amt_to_forward`. + +The final node: + - MUST fail the HTLC if dictated by Requirements under [Failure Messages](#failure-messages) + - Note: "amount paid" specified there is the `total_msat` field. + - if it does not support `basic_mpp`: + - MUST fail the HTLC if `total_msat` is not exactly equal to `amt_to_forward`. + - otherwise, if it supports `basic_mpp`: + - MUST add it to the HTLC set corresponding to that `payment_hash`. + - SHOULD fail the entire HTLC set if `total_msat` is not the same for + all HTLCs in the set. + - if the total `amount_msat` of this HTLC set equals `total_msat`: + - SHOULD fulfill all HTLCs in the HTLC set + - otherwise, if the total `amount_msat` of this HTLC set is less than + `total_msat`: + - MUST NOT fulfill any HTLCs in the HTLC set + - MUST fail all HTLCs in the HTLC set after some reasonable timeout. + - SHOULD wait for at least 60 seconds after the initial HTLC. + - SHOULD use `mpp_timeout` for the failure message. + - if it fulfills any HTLCs in the HTLC set: + - MUST fulfill the entire HTLC set. + +#### Rationale + +If `basic_mpp` is present it causes a delay to allow other partial +payments to combine. The total amount must be sufficient for the +desired payment, just as it must be for single payments. But this must +be reasonably bounded to avoid a denial-of-service. + +Because invoices do not necessarily specify an amount, and because +payers can add noise to the final amount, the total amount must be +sent explicitly. The requirements allow exceeding this slightly, as +it simplifies adding noise to the amount when splitting, as well as +scenarios in which the senders are genuinely independent (friends +splitting a bill, for example). + +The restriction on sending an HTLC once the set is over the agreed total prevents the preimage being released before all +the partial payments have arrived: that would allow any intermediate +node to immediately claim any outstanding partial payments. + +An implementation may choose not to fulfill an HTLC set which +otherwise meets the amount criterion (eg. some other failure, or +invoice timeout), however if it were to fulfill only some of them, +intermediary nodes could simply claim the remaining ones. # Accepting and Forwarding a Payment @@ -313,6 +406,8 @@ using an alternate channel. When building the route, the origin node MUST use a payload for the final node with the following values: +* `payment_secret`: set to the payment secret specified by the recipient (e.g. + `payment_secret` from a [BOLT #11](11-payment-encoding.md) payment invoice) * `outgoing_cltv_value`: set to the final expiry specified by the recipient (e.g. `min_final_cltv_expiry` from a [BOLT #11](11-payment-encoding.md) payment invoice) * `amt_to_forward`: set to the final amount specified by the recipient (e.g. `amount` @@ -827,9 +922,10 @@ handling by the processing node. * [`u64`:`htlc_msat`] * [`u32`:`height`] -The `payment_hash` is unknown to the final node, the amount for that -`payment_hash` is incorrect or the CLTV expiry of the htlc is too close to the -current block height for safe handling. +The `payment_hash` is unknown to the final node, the `payment_secret` doesn't +match the `payment_hash`, the amount for that `payment_hash` is incorrect or +the CLTV expiry of the htlc is too close to the current block height for safe +handling. The `htlc_msat` parameter is superfluous, but left in for backwards compatibility. The value of `htlc_msat` always matches the amount specified in @@ -885,6 +981,11 @@ or is incomplete. If the failure can be narrowed down to a specific tlv type in the payload, the erring node may include that `type` and its byte `offset` in the decrypted byte stream. +1. type: 23 (`mpp_timeout`) + +The complete amount of the multi-part payment was not received within a +reasonable time. + ### Requirements An _erring node_: @@ -952,6 +1053,10 @@ An _intermediate hop_ MUST NOT, but the _final node_: - if the payment hash has already been paid: - MAY treat the payment hash as unknown. - MAY succeed in accepting the HTLC. + - if the `payment_secret` doesn't match the expected value for that `payment_hash`, + or the `payment_secret` is required and is not present: + - MUST fail the HTLC. + - MUST return an `incorrect_or_unknown_payment_details` error. - if the amount paid is less than the amount expected: - MUST fail the HTLC. - MUST return an `incorrect_or_unknown_payment_details` error. diff --git a/09-features.md b/09-features.md index 8d3d025ea..b05d83557 100644 --- a/09-features.md +++ b/09-features.md @@ -35,6 +35,8 @@ The Context column decodes as follows: | 8/9 | `var_onion_optin` | Requires/supports variable-length routing onion payloads | IN | [Routing Onion Specification][bolt04] | | 10/11 | `gossip_queries_ex` | Gossip queries can include additional information | IN | [BOLT #7][bolt07-query] | | 12/13| `option_static_remotekey` | Static key for remote output | IN | [BOLT #3](03-transactions.md) | +| 14/15 | `payment_secret` | Node supports `payment_secret` field | IN9 | [Routing Onion Specification][bolt04] | +| 16/17 | `basic_mpp` | Node can receive basic multi-part payments | IN9 | [BOLT #3][bolt04-mpp] | ## Requirements @@ -67,3 +69,4 @@ This work is licensed under a [Creative Commons Attribution 4.0 International Li [bolt04]: 04-onion-routing.md [bolt07-sync]: 07-routing-gossip.md#initial-sync [bolt07-query]: 07-routing-gossip.md#query-messages +[bolt04-mpp]: 04-onion-routing.md#basic-multi-part-payments diff --git a/11-payment-encoding.md b/11-payment-encoding.md index e9a28770a..b6c16a7ea 100644 --- a/11-payment-encoding.md +++ b/11-payment-encoding.md @@ -129,6 +129,7 @@ Each Tagged Field is of the form: Currently defined tagged fields are: * `p` (1): `data_length` 52. 256-bit SHA256 payment_hash. Preimage of this provides proof of payment. +* `s` (16): `data_length` 52. This 256-bit secret prevents forwarding nodes from probing the payment recipient. * `d` (13): `data_length` variable. Short description of purpose of payment (UTF-8), e.g. '1 cup of coffee' or 'ナンセンス 1杯' * `n` (19): `data_length` 53. 33-byte public key of the payee node * `h` (23): `data_length` 52. 256-bit description of purpose of payment (SHA256). This is used to commit to an associated description that is over 639 bytes, but the transport mechanism for the description in that case is transport specific and not defined here. @@ -148,7 +149,7 @@ Currently defined tagged fields are: ### Requirements A writer: - - MUST include exactly one `p` field. + - MUST include exactly one `p` and `s` fields. - MUST set `payment_hash` to the SHA2 256-bit hash of the `payment_preimage` that will be given in return for payment. - MUST include either exactly one `d` or exactly one `h` field. @@ -191,8 +192,8 @@ A writer: - MUST specify the most-preferred field first, followed by less-preferred fields, in order. A reader: - - MUST skip over unknown fields, OR an `f` field with unknown `version`, OR `p`, `h`, or - `n` fields that do NOT have `data_length`s of 52, 52, or 53, respectively. + - MUST skip over unknown fields, OR an `f` field with unknown `version`, OR `p`, `h`, `s` or + `n` fields that do NOT have `data_length`s of 52, 52, 52 or 53, respectively. - if the `9` field contains unknown _odd_ bits that are non-zero: - MUST ignore the bit. - if the `9` field contains unknown _even_ bits that are non-zero: @@ -202,6 +203,8 @@ A reader: description. - if a valid `n` field is provided: - MUST use the `n` field to validate the signature instead of performing signature recovery. + - if there is a valid `s` field: + - MUST use that as [`payment_secret`](04-onion-routing.md#tlv_payload-payload-format) ### Rationale @@ -279,6 +282,34 @@ The field is big-endian. The least-significant bit is numbered 0, which is _even_, and the next most significant bit is numbered 1, which is _odd_. +Note that the `payment_secret` feature prevents probing attacks from nodes +along the path, but only if made compulsory: yet doing so will break +older clients which do not understand the feature. + +### Requirements + +A writer: + - if `payment_secret` feature is set: + - MUST include an `s` field. + - otherwise: + - MUST NOT include an `s` field. + - if the `payment_secret` field is required in the onion: + - MUST set the even feature `payment_secret`. + - If the final node supports [Basic multi-part payments](04-onion-routing.md#basic-multi-part-payments): + - MUST set the `basic_mpp` feature. + - Otherwise: + - MUST NOT set the `basic_mpp` feature. + - if it sets either `payment_secret` or `basic_mpp` features: + - MUST set the `var_onion_optin` feature. + - MUST set `var_onion_optin` if and only if it supports that feature. + +A reader: + - if the `basic_mpp` feature is offered in the invoice: + - MAY pay using [Basic multi-part payments](04-onion-routing.md#basic-multi-part-payments). + - otherwise: + - MUST NOT use [Basic multi-part payments](04-onion-routing.md#basic-multi-part-payments). + + # Payer / Payee Interactions These are generally defined by the rest of the Lightning BOLT series, @@ -318,7 +349,7 @@ https://github.com/rustyrussell/lightning-payencode # Examples -NB: all the following examples are signed with `priv_key`=`e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734`. +NB: all the following examples are signed with `priv_key`=`e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734`. Also, the first 9 examples are legacy: modern invoices have an `s` field. > ### Please make a donation of any amount using payment_hash 0001020304050607080900010203040506070809000102030405060708090102 to me @03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad > lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w @@ -535,8 +566,8 @@ Breakdown: * `6c6e626332306d0b25fe64570d0e496dbd9f8b0d000dbb44824f751380da37c6dba89b14f6f92047d63f576e304021a00008101820283038404800081018202830384048000810182028303840480810243500c318a1e0a628b34025e8c9019ab6d09b64c2b3c66a693d0dc63194b02481931000` hex of data for signing (prefix + data after separator up to the start of the signature) * `399a8b167029fda8564fd2e99912236b0b8017e7d17e416ae17307812c92cf42` hex of SHA256 of the preimage -> ### Please send $30 for coffee beans to the same peer, which supports features 1 and 9 -> lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdees9qzsze992adudgku8p05pstl6zh7av6rx2f297pv89gu5q93a0hf3g7lynl3xq56t23dpvah6u7y9qey9lccrdml3gaqwc6nxsl5ktzm464sq73t7cl +> ### Please send $30 for coffee beans to the same peer, which supports features 15 and 99, using secret 0x1111111111111111111111111111111111111111111111111111111111111111 +> lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqpqqq4u9s93jtgysm3mrwll70zr697y3mf902hvxwej0v7c62rsltw83ng0pu8w3j230sluc5gxkdmm9dvpy9y6ggtjd2w544mzdrcs42t7sqdkcy8h Breakdown: @@ -548,14 +579,17 @@ Breakdown: * `d`: short description * `q5`: `data_length` (`q` = 0, `5` = 20; 0 * 32 + 20 == 20) * `vdhkven9v5sxyetpdees`: 'coffee beans' +* `s`: payment secret + * `p5`: `data_length` (`p` = 1, `5` = 20; 1 * 32 + 20 == 52) + * `zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs`: 0x1111111111111111111111111111111111111111111111111111111111111111 * `9`: features - * `qz`: `data_length` (`q` = 0, `z` = 2; 0 * 32 + 2 == 2) - * `sz`: b1000000010 -* `e992adudgku8p05pstl6zh7av6rx2f297pv89gu5q93a0hf3g7lynl3xq56t23dpvah6u7y9qey9lccrdml3gaqwc6nxsl5ktzm464sq`: signature -* `73t7cl`: Bech32 checksum + * `q5`: `data_length` (`q` = 0, `5` = 20; 0 * 32 + 20 == 20) 4 + * `sqqqqqqqqqqqqqqqpqqq`: b1000....00001000000000000000 +* `pqqq4u9s93jtgysm3mrwll70zr697y3mf902hvxwej0v7c62rsltw83ng0pu8w3j230sluc5gxkdmm9dvpy9y6ggtjd2w544mzdrcs42t7sq`: signature +* `dkcy8h`: Bech32 checksum -> # Same, but using invalid unknown feature 100 -> lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdees9q4pqqqqqqqqqqqqqqqqqqszk3ed62snp73037h4py4gry05eltlp0uezm2w9ajnerhmxzhzhsu40g9mgyx5v3ad4aqwkmvyftzk4k9zenz90mhjcy9hcevc7r3lx2sphzfxz7 +> # Same, but adding invalid unknown feature 100 +> lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqpqqqqu7fz6pjqczdm3jp3qps7xntj2w2mm70e0ckhw3c5xk9p36pvk3sewn7ncaex6uzfq0vtqzy28se6pcwn790vxex7xystzumhg55p6qq9wq7td Breakdown: @@ -567,11 +601,14 @@ Breakdown: * `d`: short description * `q5`: `data_length` (`q` = 0, `5` = 20; 0 * 32 + 20 == 20) * `vdhkven9v5sxyetpdees`: 'coffee beans' +* `s`: payment secret + * `p5`: `data_length` (`p` = 1, `5` = 20; 1 * 32 + 20 == 52) + * `zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs`: 0x1111111111111111111111111111111111111111111111111111111111111111 * `9`: features * `q4`: `data_length` (`q` = 0, `4` = 21; 0 * 32 + 21 == 21) - * `pqqqqqqqqqqqqqqqqqqsz`: b00001...(90 zeroes)...1000000010 -* `k3ed62snp73037h4py4gry05eltlp0uezm2w9ajnerhmxzhzhsu40g9mgyx5v3ad4aqwkmvyftzk4k9zenz90mhjcy9hcevc7r3lx2sp`: signature -* `hzfxz7`: Bech32 checksum + * `psqqqqqqqqqqqqqqqpqqqq`: b000011000....00001000000000000000 +* `u7fz6pjqczdm3jp3qps7xntj2w2mm70e0ckhw3c5xk9p36pvk3sewn7ncaex6uzfq0vtqzy28se6pcwn790vxex7xystzumhg55p6qq`: signature +* `9wq7td`: Bech32 checksum # Authors