-
Notifications
You must be signed in to change notification settings - Fork 407
Compact blinded path creation #3011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d792afb
e553a71
4956ade
0a6886e
e8354b2
e4661fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ | |
//! Creating blinded paths and related utilities live here. | ||
|
||
pub mod payment; | ||
pub(crate) mod message; | ||
pub mod message; | ||
pub(crate) mod utils; | ||
|
||
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; | ||
|
@@ -21,6 +21,7 @@ use crate::offers::invoice::BlindedPayInfo; | |
use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph}; | ||
use crate::sign::EntropySource; | ||
use crate::util::ser::{Readable, Writeable, Writer}; | ||
use crate::util::scid_utils; | ||
jkczyz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
use crate::io; | ||
use crate::prelude::*; | ||
|
@@ -124,7 +125,7 @@ impl BlindedPath { | |
pub fn one_hop_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>( | ||
recipient_node_id: PublicKey, entropy_source: ES, secp_ctx: &Secp256k1<T> | ||
) -> Result<Self, ()> where ES::Target: EntropySource { | ||
Self::new_for_message(&[recipient_node_id], entropy_source, secp_ctx) | ||
Self::new_for_message(&[], recipient_node_id, entropy_source, secp_ctx) | ||
} | ||
|
||
/// Create a blinded path for an onion message, to be forwarded along `node_pks`. The last node | ||
|
@@ -133,17 +134,21 @@ impl BlindedPath { | |
/// Errors if no hops are provided or if `node_pk`(s) are invalid. | ||
// TODO: make all payloads the same size with padding + add dummy hops | ||
pub fn new_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>( | ||
node_pks: &[PublicKey], entropy_source: ES, secp_ctx: &Secp256k1<T> | ||
intermediate_nodes: &[message::ForwardNode], recipient_node_id: PublicKey, | ||
entropy_source: ES, secp_ctx: &Secp256k1<T> | ||
) -> Result<Self, ()> where ES::Target: EntropySource { | ||
if node_pks.is_empty() { return Err(()) } | ||
let introduction_node = IntroductionNode::NodeId( | ||
intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id) | ||
); | ||
let blinding_secret_bytes = entropy_source.get_secure_random_bytes(); | ||
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); | ||
let introduction_node = IntroductionNode::NodeId(node_pks[0]); | ||
|
||
Ok(BlindedPath { | ||
introduction_node, | ||
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), | ||
blinded_hops: message::blinded_hops(secp_ctx, node_pks, &blinding_secret).map_err(|_| ())?, | ||
blinded_hops: message::blinded_hops( | ||
secp_ctx, intermediate_nodes, recipient_node_id, &blinding_secret, | ||
).map_err(|_| ())?, | ||
}) | ||
} | ||
|
||
|
@@ -213,6 +218,35 @@ impl BlindedPath { | |
}, | ||
} | ||
} | ||
|
||
/// 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
/// | ||
/// While this may result in a smaller encoding, there is a trade off in that the path may | ||
/// become invalid if the channel is closed or hasn't been propagated via gossip. Therefore, | ||
/// calling this may not be suitable for long-lived blinded paths. | ||
pub fn use_compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) { | ||
if let IntroductionNode::NodeId(pubkey) = &self.introduction_node { | ||
let node_id = NodeId::from_pubkey(pubkey); | ||
if let Some(node_info) = network_graph.node(&node_id) { | ||
if let Some((scid, channel_info)) = node_info | ||
.channels | ||
.iter() | ||
.filter_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info))) | ||
.min_by_key(|(scid, _)| scid_utils::block_from_scid(*scid)) | ||
{ | ||
let direction = if node_id == channel_info.node_one { | ||
Direction::NodeOne | ||
} else { | ||
debug_assert_eq!(node_id, channel_info.node_two); | ||
Direction::NodeTwo | ||
}; | ||
self.introduction_node = | ||
IntroductionNode::DirectedShortChannelId(direction, scid); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl Writeable for BlindedPath { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ use bitcoin::secp256k1::Secp256k1; | |
use bitcoin::{secp256k1, Sequence}; | ||
|
||
use crate::blinded_path::{BlindedPath, NodeIdLookUp}; | ||
use crate::blinded_path::message::ForwardNode; | ||
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs}; | ||
use crate::chain; | ||
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock}; | ||
|
@@ -8996,8 +8997,16 @@ where | |
|
||
let peers = self.per_peer_state.read().unwrap() | ||
.iter() | ||
.filter(|(_, peer)| peer.lock().unwrap().latest_features.supports_onion_messages()) | ||
.map(|(node_id, _)| *node_id) | ||
.map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap())) | ||
.filter(|(_, peer)| peer.latest_features.supports_onion_messages()) | ||
.map(|(node_id, peer)| ForwardNode { | ||
node_id: *node_id, | ||
short_channel_id: peer.channel_by_id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 So right now it's partly an implementation concern given you need a There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened #3080 with separate As for how this is exposed in Alternatives would be:
Any preferences other alternatives? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm good with whichever of those options you think is best! |
||
.iter() | ||
.filter(|(_, channel)| channel.context().is_usable()) | ||
.min_by_key(|(_, channel)| channel.context().channel_creation_height) | ||
.and_then(|(_, channel)| channel.context().get_short_channel_id()), | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
self.router | ||
|
Uh oh!
There was an error while loading. Please reload this page.