-
Notifications
You must be signed in to change notification settings - Fork 367
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
Add API for constructing blinded payment paths #2412
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
cd8952d
to
a6d08fe
Compare
Codecov ReportPatch coverage:
❗ 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
☔ View full report in Codecov by Sentry. |
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together. | ||
payment_secret: PaymentSecret, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
fd88452
to
1fa4ecd
Compare
Rebased due to conflicts and squashed minor fixups. |
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together. | ||
payment_secret: PaymentSecret, |
There was a problem hiding this comment.
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
?
387e06e
to
4b7b7e8
Compare
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together. | ||
payment_secret: PaymentSecret, |
There was a problem hiding this comment.
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.
7f8cec6
to
4bb7ea6
Compare
There was a problem hiding this 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>( |
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
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 |
There was a problem hiding this comment.
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...?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
bed22b0
to
a52d43e
Compare
Rebased because the new spec test vector failed with the new code, fixed now. |
a52d43e
to
9d481d1
Compare
.map(|f| f / 1_000_000) | ||
.ok_or(())?; | ||
} | ||
let htlc_minimum_msat = path.iter().map(|(_, tlvs)| tlvs.htlc_minimum_msat()).max().unwrap_or(0); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
3b75164
to
74f728f
Compare
74f728f
to
c9d2968
Compare
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.
c9d2968
to
63b60e2
Compare
Rebased due to conflicts and squashed. |
There was a problem hiding this 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 🤦 )
impl Readable for BlindedPaymentTlvs { | ||
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> { | ||
_init_and_read_tlv_stream!(r, { | ||
(1, _padding, option), |
There was a problem hiding this comment.
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 i64
s 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 :(
There was a problem hiding this comment.
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;
There was a problem hiding this comment.
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.
63b60e2
to
ea84f2a
Compare
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.