Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Compact blinded path creation - #3011

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation
May 29, 2024
Merged

Compact blinded path creation#3011
TheBlueMatt merged 6 commits into
lightningdevkit:mainfrom
jkczyz:2024-04-compact-blinded-path-creation

Conversation

@jkczyz

@jkczyzjkczyz commented Apr 22, 2024

Copy link
Copy Markdown
Contributor

Add support for creating a compact BlindedPath, which consists of:

  • using an SCID instead of a node id in BlindedHop::encrypted_payload
  • using IntroductionNode::DirectedShortChannelId

The first is accomplished by specifying SCIDs when calling BlindedPath::new_for_message using a new message::ForwardNode struct. The second is through calling BlindedPath::use_compact_introduction_node. Both are called by DefaultMessageRouter.

@codecov-commenter

codecov-commenter commented Apr 22, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.19858% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 90.29%. Comparing base (a95338a) to head (e4661fe).
Report is 7 commits behind head on main.

FilesPatch %Lines
lightning/src/ln/offers_tests.rs81.25%0 Missing and 6 partials ⚠️
lightning/src/blinded_path/mod.rs86.20%3 Missing and 1 partial ⚠️
lightning/src/util/test_utils.rs50.00%1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@ Coverage Diff @@## main #3011 +/- ##
==========================================
+ Coverage 89.87% 90.29% +0.42% 
==========================================
Files 117 117 Lines 96952 100069 +3117 Branches 96952 100069 +3117 ==========================================
+ Hits 87134 90357 +3223 + Misses 7273 7130 -143 - Partials 2545 2582 +37 

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

@valentinewallacevalentinewallace 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.

Basically LGTM

Comment threadlightning/src/onion_message/messenger.rs Outdated
Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Pedantic but the convention is for setters to use the set_ prefix: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis and I think it would read a bit cleaner in this case.

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.

Hmmm... this is not a setter in the normal sense, though, as we don't pass a value to set a field with. Nor is the field private, which would necessitate a setter. It also may not update the field if a value cannot be found in the network graph. Happy to go with a better name. Just not sure if a set_ prefix is appropriate here.

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

T: secp256k1::Signing + secp256k1::Verification
>(
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<PublicKey>, scid_lookup: &SL,

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.

Rather than passing a list of our peers and a trait so that create_blinded_paths can make a callback to the caller to ask for an SCID for a given peer, shouldn't we just pass in the peers as a ForwardNode or (PublicKey, u64)?

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, come to think of it that is probably cleaner. That would also allow the caller to use the compact hop representation only when desired. (e.g., in offer/refund but not in reply paths).

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from 084d070 to a74e84fCompareMay 9, 2024 22:55

@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.

Looks like this needs a rebase.

Comment threadlightning/src/ln/channelmanager.rs Outdated
node_id: *node_id,
short_channel_id: peer.channel_by_id
.iter()
.find(|(_, channel)| channel.context().is_usable())

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.

Do we want to sort by oldest or biggest or something?

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.

Good idea! Oldest is probably best as this is only for onion messages, so we just want to make sure the channel announcement has been propagated in the gossip.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 5d08b1f to f3726a7CompareMay 13, 2024 21:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Rebased

@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 LGTM, but IMO we really should make this optional somehow. It could happen in a followup if we want, cause we should also change how many hops we include based on if an offfer is long-lived.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Still, it does seem a bit strange that we're mutating the blinded path with a fn name that sounds like it could just as well be a straight getter.

}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.

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.

We should probably have some kind of discussion of how this makes paths shorter but if a channel closes will invalidate it.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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.

Similar here, should we sort by size/age?

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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.

Should we make setting this optional somehow? I feel like if I'm building a super long-term offer I may have a different preference from something being scanned right now.

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

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.

I see what you mean... if there's an obvious "default behavior" that stands out, we could have a separate method, e.g. create_long_term_blinded_paths, or have a Config struct. That way we could also have a config setting for compact offers vs offers that don't need to be QR-scanned, or privacy-oriented offers that want longer blinded 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.

Opened #3080 with separate MessageRouter methods, using compact paths for Offer::paths and Refund::paths and non-compact paths for onion message reply paths. Basically, the trait allows either for the caller to decide.

As for how this is exposed in ChannelManager utilities, I'm not sure how we should handle short- vs long-lived offers. One thought was to chose the type of path based on the expiry. But for offers, the expiry is set by the user after the builder is returned and path already set. For refunds created via ChannelManager, we require an expiration (even though the spec does not), though, so we could infer there.

Alternatives would be:

  • making a special purpose create_offer_builder for long-lived offers
  • adding a parameter to create_offer_builder indicating if short- or long-lived
  • adding a Optional absolute expiry parameter to create_offer_builder used to infer which type of path to create

Any preferences other alternatives?

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.

I'm good with whichever of those options you think is best!

},
}?;
for path in &mut paths {
path.compact_introduction_node(&network_graph);

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.

Similar here, can we make this optional on a per-offer/message basis?

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.

#3080 refactors MessageRouter to have two different methods.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f3726a7 to b295e98CompareMay 14, 2024 17:17

@jkczyzjkczyz left a comment

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.

Oops, forgot to publish these comments.

Comment threadlightning/src/blinded_path/mod.rs Outdated

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
/// short channel id from a channel in `network_graph` leading to the introduction node.
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {

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.

Ok, added a use_ prefix. I can see how the docs make it less clear that compact was a verb in the name.

Comment threadlightning/src/blinded_path/mod.rs Outdated
if let Some((scid, channel_info)) = node_info
.channels
.iter()
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))

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, good catch. Using the block height from the scid as it seems the timestamp in the update is really a counter specific to the channel.

.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
.map(|(node_id, peer)| ForwardNode {
node_id: *node_id,
short_channel_id: peer.channel_by_id

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... arguably we shouldn't bother with it for reply paths, either. Just not sure exactly how we want to convey it through the MessageRouter trait. Currently, the caller makes the decision for the penultimate hop using ForwardNode, but when adding more hops the MessageRouter makes the decision since it needs a NetworkGraph to find more hops. Similarly for the introduction node.

So right now it's partly an implementation concern given you need a NetworkGraph. I guess we can just add a bool parameter and it say it is best effort? Any other ideas?

@valentinewallacevalentinewallace 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.

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Comment threadlightning/src/blinded_path/mod.rs Outdated
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from 2dd24ed to 7d85abdCompareMay 14, 2024 22:48
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

LGTM pending maybe making the compact encoding optional. Looks like it needs another rebase as well.

Rebased now. Yeah, maybe best to do that in a follow-up as it may be a little more involved. Let me know if you have any thoughts on #3011 (comment).

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch 2 times, most recently from e7f5035 to bb5dc03CompareMay 22, 2024 22:28
@jkczyz

Copy link
Copy Markdown
ContributorAuthor

Feel free to squash and we can land this IMO. We should open an issue and block the next release on the followup.

Rebased and opened #3080. Looking for feedback on the ChannelManager API (see #3011 (comment)).

valentinewallace
valentinewallace previously approved these changes May 23, 2024
Comment threadlightning/src/blinded_path/message.rs
Comment threadlightning/src/blinded_path/mod.rs
T: secp256k1::Signing + secp256k1::Verification
> (
&self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,

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.

If we're going to split this into two methods, do we still need message::ForwardNode? Can't one method take pubkeys and the other take scids?

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.

We alwasys need the pubkeys when creating the blinded path, so we'd need to either make a new struct or use a tuple. It's kinda nice having it use an Option for short_channel_id, though. It makes it easy in ChannelManager::create_blinded_path to fallback to None if a usable channel can't be found.

@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from bb5dc03 to f0d81eaCompareMay 23, 2024 20:53
TheBlueMatt
TheBlueMatt previously approved these changes May 28, 2024
Comment threadlightning/src/blinded_path/message.rs
Jeffrey Czyz added 4 commits May 28, 2024 16:35
When sending an onion message to a blinded path, the short channel id
between hops isn't need in each hop's encrypted_payload since it is not
a payment. However, using the short channel id instead of the node id
gives a more compact representation. Update BlindedPath::new_for_message
to allow for this.
Instead of passing Vec<PublicKey> to MessageRouter::crate_blinded_path,
pass Vec<ForwardNode>. This way callers can include a short_channel_id
for a more compact BlindedPath encoding.
Add a method to BlindedPath that given a network graph will compact the
IntroductionNode as the DirectedShortChannelId variant. Call this method
from DefaultMessageRouter so that Offer paths use the compact
representation (along with reply paths). This leaves payment paths in
Bolt12Invoice using the NodeId variant, as the compact representation
isn't as useful there.
@jkczyz
jkczyzforce-pushed the 2024-04-compact-blinded-path-creation branch from f0d81ea to e4661feCompareMay 28, 2024 21:42
@jkczyz

ghost commented May 28, 2024

Copy link
Copy Markdown
ContributorAuthor

Added derives to ForwardNode.

@TheBlueMatt
TheBlueMatt merged commit df01208 into lightningdevkit:mainMay 29, 2024
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.

4 participants

@jkczyz@codecov-commenter@TheBlueMatt@valentinewallace