') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Add API for constructing blinded payment paths by valentinewallace · Pull Request #2412 · lightningdevkit/rust-lightning · GitHub
Skip to content

Add API for constructing blinded payment paths - #2412

Merged
TheBlueMatt merged 13 commits into
lightningdevkit:mainfrom
valentinewallace:2023-07-construct-blinded-paths
Aug 23, 2023
Merged

Add API for constructing blinded payment paths#2412
TheBlueMatt merged 13 commits into
lightningdevkit:mainfrom
valentinewallace:2023-07-construct-blinded-paths

Conversation

@valentinewallace

@valentinewallacevalentinewallace commented Jul 13, 2023

Copy link
Copy Markdown
Contributor

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.

@valentinewallacevalentinewallace mentioned this pull request Jul 13, 2023
60 tasks
@valentinewallacevalentinewallace added this to the 0.0.117 milestone Jul 13, 2023
@valentinewallacevalentinewallace mentioned this pull request Jul 13, 2023
1 task

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice!

Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
@valentinewallace
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch from cd8952d to a6d08feCompareJuly 20, 2023 19:27
@codecov-commenter

codecov-commenter commented Jul 20, 2023

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.34951% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.03%. Comparing base (4fb5708) to head (ea84f2a).
⚠️ Report is 5537 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/blinded_path/payment.rs0.00%5 Missing ⚠️
lightning/src/blinded_path/message.rs90.32%3 Missing ⚠️
lightning/src/events/mod.rs25.00%3 Missing ⚠️
lightning/src/blinded_path/utils.rs95.23%1 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #2412 +/- ##
==========================================
+ Coverage 90.59% 91.03% +0.43% 
==========================================
Files 106 109 +3 Lines 56577 62958 +6381 Branches 56577 62958 +6381 ==========================================
+ Hits 51258 57316 +6058 - Misses 5319 5642 +323 

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Copy link
Copy Markdown
ContributorAuthor

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
Copy Markdown
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
Copy Markdown
ContributorAuthor

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
Copy Markdown
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
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from fd88452 to 1fa4ecdCompareAugust 1, 2023 18:41
@valentinewallace

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts and squashed minor fixups.

Comment threadlightning/src/blinded_path/utils.rs Outdated
Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together.
payment_secret: PaymentSecret,

Copy link
Copy Markdown
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?

@valentinewallace
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch from 387e06e to 4b7b7e8CompareAugust 8, 2023 18:36
Comment threadlightning/src/blinded_path/mod.rs Outdated
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together.
payment_secret: PaymentSecret,

Copy link
Copy Markdown
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.

Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs
@valentinewallace
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from 7f8cec6 to 4bb7ea6CompareAugust 9, 2023 21:43

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

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
Copy Markdown
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
Copy Markdown
ContributorAuthor

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
Copy Markdown
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
Copy Markdown
ContributorAuthor

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

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/blinded_path/utils.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
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
Copy Markdown
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
Copy Markdown
ContributorAuthor

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
Copy Markdown
ContributorAuthor

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.

Comment threadlightning/src/blinded_path/payment.rs Outdated
@valentinewallace
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from bed22b0 to a52d43eCompareAugust 15, 2023 16:10
@valentinewallace

valentinewallace commented Aug 15, 2023

Copy link
Copy Markdown
ContributorAuthor

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

Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
@valentinewallace
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch from a52d43e to 9d481d1CompareAugust 16, 2023 18:51
Comment threadlightning/src/blinded_path/mod.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs Outdated
.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
Copy Markdown
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
Copy Markdown
ContributorAuthor

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
Copy Markdown
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
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch 2 times, most recently from 3b75164 to 74f728fCompareAugust 21, 2023 17:59
@TheBlueMattTheBlueMatt linked an issue Aug 21, 2023 that may be closed by this pull request
Comment threadlightning/src/blinded_path/payment.rs Outdated
Comment threadlightning/src/blinded_path/payment.rs
@valentinewallace
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch from 74f728f to c9d2968CompareAugust 22, 2023 15:16
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
valentinewallaceforce-pushed the 2023-07-construct-blinded-paths branch from c9d2968 to 63b60e2CompareAugust 22, 2023 17:26
@valentinewallace

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts and squashed.

jkczyz
jkczyz previously approved these changes Aug 22, 2023

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

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 🤦 )

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/blinded_path/utils.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
ContributorAuthor

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:mainAug 23, 2023
Sign up for freeto 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

@valentinewallace@codecov-commenter@TheBlueMatt@jkczyz@alecchendev