1. Always use the term `encrypted_recipient_data` for the encrypted field:
it's confusing enough without multiple names!
2. Don't give an option for joining blinded payments, since everyone will
use an unblinded payment to the introduction node (at least, for now).
3. Avoid the term "payer" and at least note that encrypted_recipient_data
can be made by the sender themselves, pointing out that the forwarding
node cannot tell.
Thanks t-bast and gijswijs for this feedback!
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
It's a bit complex, but try to convey the idea of an introduction point,
blinded node ids and encrypted blobs. Since the requirements detail the
two ways to reach the introduction node, I handwaved on that a bit.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Writer parts:
1. Be explicit that the writer creates a route.
2. Make it clear we create shared secrets, then derive blinded points.
3. Refer explicitly to all `blinded_path` fields.
Split reader into the *two* readers:
1. The reader of the blinded path, who uses it to make an onion (which wasn't described at all!)
2. The reader of the encrypted_recipient_data, who decrypts it.
In the latter case, we don't have to discuss unblinding the onion since
that's now covered in the "Onion Decryption" section.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This spec was initially written before the `blinded_path` type
existed. Be precise (and we no longer need to say "MUST communicate"!).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
It's currently buried in the onion message section, but it applies to payments too.
We now have a separate sub-section for the encrypted_data_tlv definition.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit doesn't change the logic at all, it simply:
- removes `realm` from onion test vector
- cleans-up markdown formatting and indents
- fixes typos and missing parenthesis
- consistently uses `_` instead of `-` for field names
- fixes math formatting (including changes from #1169 and #1158)
Sure, it's used to derive a secret for blinding, but it's also used to derive the key
for encrypted_recipient_data. It's not used as a blinding factor *directly*.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This ties it together, saying what to use as associated data, blinding, and what to do on failure.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
There's currently a *description* of how to decrypt an onion, and some requirements
in forwarding. But it also applies to onion messages, so:
1. Turn the description into actual enumerated requirements.
2. Ensure the description covers both payload and messaging onions.
3. Include both methods to apply the blinding tweak.
4. Leave the actual handling of the extracted payload (payment vs messaging onion) to those specific sections (e.g. reporting failure)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
* BOLT4: include `min_final_cltv_expiry_delta` in `max_cltv_expiry` calc
Include `min_final_cltv_expiry_delta` in the `max_cltv_expiry`
calculation. Also add a note that indicates that this field may be set
for the final node too. This is useful for the final node as then it
does not need to persist the path expiry separately and can rely on just
checking the `payment_relay` field when the payment arrives.
* BOLT4: include calculation for `total_cltv_delta` of a blinded path
Include an explicit formula to use for determining the total CLTV delta
of a blinded path so that it is clear that it should include the
recipient's `min_final_cltv_expiry_delta`.
* proposals: fix `max_cltv_expiry` value for final hop in example
More info
[here](https://github.com/lightning/bolts/issues/1174#issue-2371364610)
outlining why the example needed to be updated.
As noted previously, `channel_update`s in the onion failure packets
are massive gaping fingerprintign vulnerabilities - if a node
applies them in a publicly-visible way the err'ing node can easily
identify the sender of an HTLC.
While the updates are still arguably marginally useful for nodes to
use in their pathfinding local to retires of the same payment, this
too will eventually become an issue with PTLCs. Further, we
shouldn't be letting nodes get away with delaying payments by
failing to announce the latest channel parameters or enforcing new
parameters too soon, so treating the node as having indicated
insufficient liquidity (or other general failure) is appropriate
in the general case.
Thus, here, we begin phasing out the `channel_update` field,
requiring nodes ignore it outside of the current payment and making
it formally optional (though nodes have been doing this for some
time due to various bugs).
Because some nodes may want to use update data on mobile when they
have stale gossip data, it is left optional.
To avoid timing analysis when decrypting failed payments the sender
should act as if the failure in the route came for the 27th hop.
Also changed the maximum number of hops in the route from 20 (legacy)
to 27 (tlv onion).
In this commit, we propose a purely syntactical change to the current
blinded paths specification. Rather than denote the public key of the i-th
node as `E(i)`, we propose that instead it's denoted as: `E_i`. This results
in less overall characters, and is more similar to notation customarily
used in LaTeX.
My personal preference is that the proposed notation is easier to scan at a
glance, and also less ambiguous (doesn't look like a function call).
This commit updates bolt04 to more strictly enforce that encrypted_data
that is part of a blinded payment only has short_channel_id set. On
the reader side, we disallow setting of both short_channel_id and
next_node_id (which is intended for use in the context of onion
messages), and on the writer side we specify that next_node_id should
not be included by recipients.
I always get this wrong too, so CLN actually has a source check for this, and it triggered when importing the latest spec!
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@thomash-acinq points out:
1. We absolutely can put other fields in `encrypted_data_tlv`, esp. padding, and test vectors do this.
2. Presumably it was supposed to refer to onionmsg_tlv, so fix that.
3. And of course we need to allow payload fields!
These use onion encoding for simple one-way messaging: there are no error returns.
However, every onion uses route blinding *even if it doesn't need to*.
You can prove what path was used to reach you by including `path_id` in the
encrypted_data_tlv.
Note that this doesn't actually define the payload we're transporting:
that's explictly defined to be payloads in the 64-255 range.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
When paying a blinded path, we don't have a CLTV delta at each hop
available, but rather only a total CLTV delta for the entire
blinded path.
However, the onion format currently still requires that we specify
an `outgoing_cltv_value` for the final hop. As the sender, we don't
have a sensible value to put there, as we don't know which part of
the total CLTV delta belongs to the recipient.
The sender is instructed to use the values that are known to them
when setting `outgoing_cltv_value` for the final hop:
- The current block height.
- Any additional delta added to account for block propagation and
improve privacy.
This change reflects the behavior of some implementations at the time
of writing.
Add specification requirements for using route blinding to make payments
while preserving recipient anonymity. Implementers must ensure they
understand all those requirements, there are subtle attacks that could let
malicious senders deanonymize the route if incompletely implemented.
Add specification requirements for creating and using blinded routes.
This commit contains the low-level details of the route blinding scheme,
decoupled from how it can be used by high-level components such as onion
messages or payments.
* Use onion amount in MPP set calculation
The sender chooses the amounts that are set in the onion payload
(`amt_to_forward`) but cannot predict what amounts will be set in the
HTLCs (`amount_msat`) since intermediate nodes are allowed to overpay.
* Fix error requirements for final node
These requirements were missed when integrating #1032
When nodes receive HTLCs, they verify that the contents of those HTLCs
match the intructions that the sender provided in the onion. It is
important to ensure that intermediate nodes and final nodes have similar
requirements, otherwise a malicious intermediate node could easily probe
whether the next node is the final recipient or not.
Unfortunately, the requirements for intermediate nodes were more lenient
than the requirements for final nodes. Intermediate nodes allowed overpaying
and increasing the CLTV expiry, whereas final nodes required a perfect
equality between the HTLC values and the onion values.
This provided a trivial way of probing: when relaying an HTLC, nodes could
relay 1 msat more than what the onion instructed (or increase the outgoing
expiry by 1). If the next node was an intermediate node, they would accept
this HTLC, but if the next node was the recipient, they would reject it.
We update those requirements to fix this probing attack vector.
We also clarify `min_final_cltv_expiry`: this is actually a cltv_expiry_delta,
not an absolute cltv_expiry, so the field name should reflect that.
Recipients require incoming HTLC expiry to comply with that expiry delta.
When a node retires a failed path as part of a larger MPP payment,
the node may wish to use a path which is constrained by an
`htlc_minimum_msat` value. In this case, the node is forced to
overpay, likely overshooting the `total_msat` it set in the earlier
onions for the same MPP payment.
There are two possible solutions to this - either allow the
`total_msat` value to change in later HTLCs or allow the node to
(slightly) overshoot the `total_msat` value.
Allowing `total_msat` to change across HTLCs is nontrivial to
implement - HTLCs may arrive out-of-order, causing the receiving
node to have to track all seen `total_msat` values and accept a
set of HTLCs which meet any of the seen `total_msat` values.
Instead, this commit changes the MPP logic to simply allow a sender
to overshoot the stated `total_msat`.
Sadly the backwards-compatibility story for this is not great.
There doesn't seem to be a good way to resolve this issue in a
backwards-compatible way. Instead we just bite the bullet and make
the incompatible change, hoping the overshooting is rare enough
that it's not a major issue.
My measurements a few weeks ago reveal that only 5 nodes do not
advertize this feature, of over 17000. I have a patch to
remove support from c-lightning, too.
[ 6 months later: t-bast notes that they only see 0.2% of htlcs using
legacy, and my node hasn't seen one for 2 months w/ 12000 htlcs --RR ]
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This is the only one, so I simply removed it. We'd notice if a new field
was introduced which didn't change the output these days, but this has been
here since 2017.
Here's the difference in extract-formats.py's output:
```diff
@@ -177,6 +177,9 @@
msgtype,final_incorrect_htlc_amount,19
msgdata,final_incorrect_htlc_amount,incoming_htlc_amt,u64,
msgtype,channel_disabled,UPDATE|20
+msgdata,channel_disabled,flags,u16,
+msgdata,channel_disabled,len,u16,
+msgdata,channel_disabled,channel_update,byte,len
msgtype,expiry_too_far,21
msgtype,invalid_onion_payload,PERM|22
msgdata,invalid_onion_payload,type,bigsize,
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Some ChaCha20 implementations API's support both 64- and 96-bit nonces, while
others only support a single one.
Functionally, both nonce sizes are equivalent for LN usage, since the
nonce is always zeroed. However, while evaluating spec compliance of
ChaCha20 libraries, the fact that some do not support the 8 byte nonce
variant prompted a closer investigation about the nonce requirement.
Since RFC8439 is the one linked to in the current BOLT0004 spec and that
RFC only specifies the 96-bit nonce variant, that requirement is made
more explicit by this commit.
* Rename all the 'varint' to 'bigsize'.
Having both is confusing; we chose the name bigsize, so use it
explicitly.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
* BOLT 7: use `byte` instead of `u8`.
`u8` isn't a type; see BOLT #1 "Fundamental Types".
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
* BOLT 1: promote bigsize to a Fundamental Type.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>