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

Add API for constructing blinded payment paths #2412

Conversation

valentinewallace
Copy link
Contributor

@valentinewallace valentinewallace commented Jul 13, 2023

Lays some groundwork for route blinding support, helping address #1970. Lets us build blinded payment paths from the TLV payloads contained within them. A lot of the diff is code moves so we can separate out onion message-specific code from blinded payment-specific code.

We don't pad any values at the moment, which would increase privacy.

More testing is added in #2413.

@valentinewallace valentinewallace added this to the 0.0.117 milestone Jul 13, 2023
@valentinewallace valentinewallace mentioned this pull request Jul 13, 2023
1 task
Copy link
Contributor

@alecchendev alecchendev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/util/ser_macros.rs Outdated Show resolved Hide resolved
@codecov-commenter
Copy link

codecov-commenter commented Jul 20, 2023

Codecov Report

Patch coverage: 84.57% and project coverage change: -0.13% ⚠️

Comparison is base (b149279) 91.07% compared to head (9d481d1) 90.94%.
Report is 16 commits behind head on main.

❗ Current head 9d481d1 differs from pull request most recent head 63b60e2. Consider uploading reports for the commit 63b60e2 to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2412      +/-   ##
==========================================
- Coverage   91.07%   90.94%   -0.13%     
==========================================
  Files         106      108       +2     
  Lines       63310    62914     -396     
  Branches    63310    62914     -396     
==========================================
- Hits        57657    57220     -437     
- Misses       5653     5694      +41     
Files Changed Coverage Δ
lightning/src/events/mod.rs 44.54% <0.00%> (-3.42%) ⬇️
lightning/src/blinded_path/mod.rs 85.10% <50.00%> (-9.15%) ⬇️
lightning/src/blinded_path/payment.rs 83.15% <83.15%> (ø)
lightning/src/blinded_path/message.rs 88.57% <88.57%> (ø)
lightning/src/blinded_path/utils.rs 94.73% <95.65%> (+0.98%) ⬆️
lightning/src/ln/chan_utils.rs 94.62% <100.00%> (ø)
lightning/src/ln/channelmanager.rs 89.05% <100.00%> (-0.60%) ⬇️
lightning/src/offers/invoice_error.rs 82.35% <100.00%> (ø)
lightning/src/onion_message/messenger.rs 86.75% <100.00%> (+0.06%) ⬆️
lightning/src/onion_message/packet.rs 95.19% <100.00%> (-0.10%) ⬇️
... and 3 more

... and 17 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together.
payment_secret: PaymentSecret,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for reviewers: it's a bit LDK-specific and not generic that we take a PaymentSecret here. But as discussed previously with @TheBlueMatt, the spec should not be prescribing anything for the final payload at all because it's constructed for the receiver, by the receiver, so I don't see an issue with doing this instead of calling this field path_id and taking a Vec<u8> (which is an unnecessary allocation as well). But I get that this might be a bit confusing coming from the spec so thoughts welcome here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this encoded in the BlindedPath?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understood the question but the payment_secret is written in the Writeable implementation for BlindedPaymentTlvs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. It's encoded in the BlindedPath when utils::encrypt_payload is called.

@valentinewallace valentinewallace force-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from fd88452 to 1fa4ecd Compare August 1, 2023 18:41
@valentinewallace
Copy link
Contributor Author

Rebased due to conflicts and squashed minor fixups.

lightning/src/blinded_path/utils.rs Outdated Show resolved Hide resolved
lightning/src/onion_message/messenger.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together.
payment_secret: PaymentSecret,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this encoded in the BlindedPath?

lightning/src/blinded_path/mod.rs Outdated Show resolved Hide resolved
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together.
payment_secret: PaymentSecret,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. It's encoded in the BlindedPath when utils::encrypt_payload is called.

lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
@valentinewallace valentinewallace force-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from 7f8cec6 to 4bb7ea6 Compare August 9, 2023 21:43
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically lg


// Advance the blinded onion message path by one hop, so make the second hop into the new
// introduction node.
pub(crate) fn advance_path_by_one<NS: Deref, T: secp256k1::Signing + secp256k1::Verification>(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need the same utility for blinded payment paths (and do they have the same control tlvs)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was planning to do this as a follow-up to #2413, is your preference to get it out sooner? The control TLVs aren't the same.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that's alright, I just wanted to make sure that the move made sense - I guess the follow-up will mean basically copying this and writing some new code to do the same thing for blinded payment paths?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that's alright, I just wanted to make sure that the move made sense - I guess the follow-up will mean basically copying this and writing some new code to do the same thing for blinded payment paths?

Yep, that's the thinking

lightning/src/util/ser_macros.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/utils.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
cltv_expiry_delta: path.iter().map(|(_, tlvs)| tlvs.cltv_expiry_delta())
.try_fold(0u16, |acc, delta| acc.checked_add(delta)).ok_or(())?,
htlc_minimum_msat: path.iter().map(|(_, tlvs)| tlvs.htlc_minimum_msat()).max().unwrap_or(0),
// TODO: this field isn't present in route blinding encrypted data
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this TODO? Get the spec updated, or...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the spec needs an update here, I commented on the route blinding PR lightning/bolts#765 (comment) and t-bast is supposed to get back to me soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ended up adding this field as a separate parameter to BlindedPath::new_for_payment. See linked thread but it shouldn't be part of the blinded payment TLVs themselves.

lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
@valentinewallace valentinewallace force-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from bed22b0 to a52d43e Compare August 15, 2023 16:10
@valentinewallace
Copy link
Contributor Author

valentinewallace commented Aug 15, 2023

Rebased because the new spec test vector failed with the new code, fixed now.

lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/mod.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
.map(|f| f / 1_000_000)
.ok_or(())?;
}
let htlc_minimum_msat = path.iter().map(|(_, tlvs)| tlvs.htlc_minimum_msat()).max().unwrap_or(0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to consider the fees charged earlier - if the second node in the path wants at least 1 sat, and the previous node charges 1 sat in fee, the min should be 2 sats.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Digging into this a bit, it looks like eclair/CLN don't do this. Are we sure the htlc_minimum_msat field isn't the minimum final receive amount to the blinded path, i.e. the min amount prior to the aggregated fees being added? At first glance looks like get_route will treat the min to send to the blinded path as BlindedPayInfo::htlc_minimum_msat + aggregated_fees.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, we should ask them, then, cause that doesn't make much sense to me - if we have a blinded path along A -> B -> C, and A charges a 10% fee and B has a min_htlc of 100 sats, then the min HTLC for the full path needs to be 110 sats. The total min depends on where the max-min is in the path.

@valentinewallace valentinewallace force-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from 3b75164 to 74f728f Compare August 21, 2023 17:59
@TheBlueMatt TheBlueMatt linked an issue Aug 21, 2023 that may be closed by this pull request
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/payment.rs Outdated Show resolved Hide resolved
This way it can be more easily reused for blinded payment paths.
We'll similarly separate blinded path payments code into its own module.
Useful for blinded payment path construction.
We want a similar macro for reading TLV streams without a length prefix, so
rename this one to disambiguate.
@valentinewallace
Copy link
Contributor Author

Rebased due to conflicts and squashed.

jkczyz
jkczyz previously approved these changes Aug 22, 2023
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically all LGTM. Only real issue is the 8 byte restirction on the padding cause we didn't tell rustc what type we meant (which is maybe the most obvious rustc bug I've ever come across that they insist is definitely a Feature 🤦 )

lightning/src/util/ser_macros.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/utils.rs Outdated Show resolved Hide resolved
lightning/src/blinded_path/mod.rs Outdated Show resolved Hide resolved
impl Readable for BlindedPaymentTlvs {
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
_init_and_read_tlv_stream!(r, {
(1, _padding, option),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By not defining a type here, I believe rustc magically assumed you wanted an i64 🎉 , because this crate uses i64s a ton, all over the place, its definitely what we wanted.....and also we'll fail to read if the padding isn't either empty or exactly 8 bytes :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the trick used in ControlTlvs work?

let _padding: Option<Padding> = _padding;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that should work. I think I'll add some docs to impl_writeable* saying that you can't have unused read values. It would be nice if there were a way to enforce that programmatically, haven't looked into it though.

Useful for when you want to use _init_and_read_len_prefixed_tlv_fields but there is no
length byte at the start of the TLV stream.
Also adds a util for general blinded hop creation to be reused for blinded
payment paths.
The previous name can be confused for the shared secret that the rho is derived
from.
@TheBlueMatt TheBlueMatt merged commit 0211daa into lightningdevkit:main Aug 23, 2023
14 checks passed
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 this pull request may close these issues.

5 participants