Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: some confusion re blinded path max_cltv #1174

Closed
ellemouton opened this issue Jun 25, 2024 · 2 comments · Fixed by #1176
Closed

Discussion: some confusion re blinded path max_cltv #1174

ellemouton opened this issue Jun 25, 2024 · 2 comments · Fixed by #1176

Comments

@ellemouton
Copy link
Contributor

ellemouton commented Jun 25, 2024

Going through the example outlines in the route blinding proposal doc
And I'm just a bit confused about the values used for CLTVs.

To recap the example a bit:

  • current block height is 1000
  • Alice, the receiver, wants the path to expire in 200 blocks. Meaning that that the maximum absolute incoming CLTV for the final hop can be 1200. She encodes this value in the payment_constraints.max_cltv to herself.
  • She also chooses a min_final_cltv_expiry of 12 which iiuc, she does not explicitly communicate to the recipient. Instead, she will add this to the accumulated route CLTV delta.
  • She chooses a blinded route to herself: C -> B -> A. She rounds up their advertised CLTV deltas to 144 each. She now calculates the total blinded path CLTV delta to be: 12 + 144 + 144 = 300.
  • For the encoded payloads she creates for C and B, she also indicates what they should each consider the max_expiry so that they can fail the payment early. The example shows that she sets this value to 1356 for B which seems to indicate that this was calculated by taking the maximum cltv: 1200, and adding Alice's min_final_cltv_expiry of 12 and finally adding B's cltv delta of 144 to get a final value of 1356. Then for C, she takes the previous value (1356) and adds C's delta of 144 to get 1500.
  • She communicates to the receiver: the total route CLTV delta of 300, and the final max_cltv of 1200.

The rest of the example, where Erin pays via the route, because Erin chooses a final CLTV that is significantly below Alice's given maximum.

But let's say that Erin wants to play on the edge and instead chooses a final CLTV value of 1200. Erin would then add the total blinded route delta of 300 to get the CLTV value to use on C's incoming link: 1500. Ok so let's say C get's this incoming CLTV of 1300, then C will check it's encoded max_cltv from Alice, see that it is 1500 so the incoming value is ok. C then subtracts the 144 delta and sends B a CLTV of 1356. This is also ok given C's encoded max_cltv so he subtracts 144 and sends Alice a CLTV of 1212. But this then violates Alice's initial chosen max_cltv value of 1200.

My first thought was perhaps the max_cltv value for B should not have included A's min_final_cltv_expiry but all this would mean is that C's max_cltv will end up being 1488 which is then lower than the max_cltv+total_blinded_path_cltv value of 1500. Meaning we can have the same issue just earlier in the path.

This makes me wonder if either:

  1. the recipient A should not be too strict about the max_cltv or should always account for the fact that it might be min_final_cltv_expiry less than they originally intended.
  2. Or: we still need to communicate min_final_cltv_expiry to the recipient and hence not include it in the total blinded cltv calc

EDIT: apologies if this is the wrong spot for a question like this 🙏 lemme know where a better spot would be if so

@ellemouton
Copy link
Contributor Author

ellemouton commented Jun 25, 2024

I also think that perhaps some clarification is needed in BOLT 4 to make the answer to the above more clear as currently it is explicit about how the total_fee_base_msat and total_fee_proportional_millionths is calculated but not explicit about the total CLTV (if the CLTV should in fact include the min_final_cltv_delta as is done in the proposal doc, then we should add that to bolt 4.

One other place I think could use some clarity is around if we still expect the sender to add the extra blocks for the "shadow route" or if we can now just leave that up to the receiver since they now have the ability to easily create shadow hops. This was mentioned in this thread in the offers proposal but I think this suggestion should possibly be added to the current spec as it stands today.

Once there is some clarity here, im happy to open a PR 😊

@t-bast
Copy link
Collaborator

t-bast commented Jun 26, 2024

I agree this is currently a bit unclear, because there is currently no way in the spec to communicate a blinded route to a potential payer: that is introduced by the Bolt 12 PR, which is why I previously said that it was the responsibility of that PR (or any other PR that uses blinded paths) to detail how max_cltv should be computed. But maybe it's clearer to do it right now, directly in Bolt 4, and let protocols that use blinded paths simply refer to this default construction. If you feel like giving this a shot, I'll gladly review that PR!

But this then violates Alice's initial chosen max_cltv value of 1200.

You are completely correct, and that's a mistake in the example! And when implementing it in eclair, we actually got it right. The mistake is that in the encrypted_data for herself, Alice takes into account the min_final_cltv_expiry and sets max_cltv_expiry to 1212. Everything else remains the same, which works correctly:

  • Alice wants the path to expire at block 1200
  • She allocates 12 blocks for the min_final_cltv_expiry and 144 blocks for each hop's cltv_expiry_delta, resulting in a final_expiry_delta for the whole path of 300
  • The encrypted payload contain:
    • Alice: 1212
    • Bob: 1356
    • Carol: 1500
  • Alice communicates to payers that the path's cltv_expiry_delta is 300 and that the path expires at block 1200 (which currently isn't explicitly communicated in Bolt 12, but rather uses the invoice expiry as a proxy for the path expiry - which in practice is fine)
  • Erin uses a final CLTV of 1200:
    • Carol receives 1500
    • Carol forwards 1356 to Bob
    • Bob forwards 1212 to Alice
    • And everything should be fine!

This needs to be fixed in proposal doc, probably in the same PR that details how this should be computed!

ellemouton added a commit to ellemouton/bolts that referenced this issue Jun 26, 2024
More info
[here](lightning#1174 (comment))
outlining why the example needed to be updated.
t-bast pushed a commit that referenced this issue Jul 15, 2024
* 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](#1174 (comment))
outlining why the example needed to be updated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants