Skip to content

Commit e741a9a

Browse files
Add BlindedMessagePath type to disambiguate from blinded payment paths.
1 parent caa836e commit e741a9a

22 files changed

+284
-264
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
3333
use bitcoin::hashes::Hash as TraitImport;
3434
use bitcoin::WPubkeyHash;
3535

36-
use lightning::blinded_path::message::MessageContext;
36+
use lightning::blinded_path::message::{BlindedMessagePath, MessageContext};
3737
use lightning::blinded_path::payment::{BlindedPaymentPath, ReceiveTlvs};
38-
use lightning::blinded_path::BlindedPath;
3938
use lightning::chain;
4039
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
4140
use lightning::chain::channelmonitor::{ChannelMonitor, MonitorEvent};
@@ -142,7 +141,7 @@ impl MessageRouter for FuzzRouter {
142141
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
143142
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
144143
_secp_ctx: &Secp256k1<T>,
145-
) -> Result<Vec<BlindedPath>, ()> {
144+
) -> Result<Vec<BlindedMessagePath>, ()> {
146145
unreachable!()
147146
}
148147
}

fuzz/src/full_stack.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ use bitcoin::hashes::Hash as _;
3030
use bitcoin::hex::FromHex;
3131
use bitcoin::WPubkeyHash;
3232

33-
use lightning::blinded_path::message::MessageContext;
33+
use lightning::blinded_path::message::{BlindedMessagePath, MessageContext};
3434
use lightning::blinded_path::payment::{BlindedPaymentPath, ReceiveTlvs};
35-
use lightning::blinded_path::BlindedPath;
3635
use lightning::chain;
3736
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
3837
use lightning::chain::chainmonitor;
@@ -179,7 +178,7 @@ impl MessageRouter for FuzzRouter {
179178
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
180179
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
181180
_secp_ctx: &Secp256k1<T>,
182-
) -> Result<Vec<BlindedPath>, ()> {
181+
) -> Result<Vec<BlindedMessagePath>, ()> {
183182
unreachable!()
184183
}
185184
}

fuzz/src/onion_message.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use bitcoin::secp256k1::ecdsa::RecoverableSignature;
55
use bitcoin::secp256k1::schnorr;
66
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
77

8-
use lightning::blinded_path::message::{MessageContext, OffersContext};
9-
use lightning::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
8+
use lightning::blinded_path::message::{BlindedMessagePath, MessageContext, OffersContext};
9+
use lightning::blinded_path::EmptyNodeIdLookUp;
1010
use lightning::ln::features::InitFeatures;
1111
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
1212
use lightning::ln::script::ShutdownScript;
@@ -98,7 +98,7 @@ impl MessageRouter for TestMessageRouter {
9898
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
9999
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
100100
_secp_ctx: &Secp256k1<T>,
101-
) -> Result<Vec<BlindedPath>, ()> {
101+
) -> Result<Vec<BlindedMessagePath>, ()> {
102102
unreachable!()
103103
}
104104
}

lightning/src/blinded_path/message.rs

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
// You may not use this file except in accordance with one or both of these
88
// licenses.
99

10-
//! Data structures and methods for constructing [`BlindedPath`]s to send a message over.
11-
//!
12-
//! [`BlindedPath`]: crate::blinded_path::BlindedPath
10+
//! Data structures and methods for constructing [`BlindedMessagePath`]s to send a message over.
1311
1412
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
1513

@@ -23,16 +21,68 @@ use crate::blinded_path::utils;
2321
use crate::io;
2422
use crate::io::Cursor;
2523
use crate::ln::channelmanager::PaymentId;
24+
use crate::ln::msgs::DecodeError;
2625
use crate::ln::{PaymentHash, onion_utils};
2726
use crate::offers::nonce::Nonce;
2827
use crate::onion_message::packet::ControlTlvs;
29-
use crate::sign::{NodeSigner, Recipient};
28+
use crate::sign::{EntropySource, NodeSigner, Recipient};
3029
use crate::crypto::streams::ChaChaPolyReadAdapter;
31-
use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
30+
use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Readable, Writeable, Writer};
3231

3332
use core::mem;
3433
use core::ops::Deref;
3534

35+
/// A [`BlindedPath`] to be used for sending or receiving a message, hiding the identity of the
36+
/// recipient.
37+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
38+
pub struct BlindedMessagePath(pub BlindedPath);
39+
40+
impl Writeable for BlindedMessagePath {
41+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
42+
self.0.write(w)
43+
}
44+
}
45+
46+
impl Readable for BlindedMessagePath {
47+
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
48+
Ok(Self(BlindedPath::read(r)?))
49+
}
50+
}
51+
52+
impl BlindedMessagePath {
53+
/// Create a one-hop blinded path for a message.
54+
pub fn one_hop<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
55+
recipient_node_id: PublicKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
56+
) -> Result<Self, ()> where ES::Target: EntropySource {
57+
Self::new(&[], recipient_node_id, context, entropy_source, secp_ctx)
58+
}
59+
60+
/// Create a path for an onion message, to be forwarded along `node_pks`. The last node
61+
/// pubkey in `node_pks` will be the destination node.
62+
///
63+
/// Errors if no hops are provided or if `node_pk`(s) are invalid.
64+
// TODO: make all payloads the same size with padding + add dummy hops
65+
pub fn new<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
66+
intermediate_nodes: &[ForwardNode], recipient_node_id: PublicKey, context: MessageContext,
67+
entropy_source: ES, secp_ctx: &Secp256k1<T>
68+
) -> Result<Self, ()> where ES::Target: EntropySource {
69+
let introduction_node = IntroductionNode::NodeId(
70+
intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id)
71+
);
72+
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
73+
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
74+
75+
Ok(Self(BlindedPath {
76+
introduction_node,
77+
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
78+
blinded_hops: blinded_hops(
79+
secp_ctx, intermediate_nodes, recipient_node_id,
80+
context, &blinding_secret,
81+
).map_err(|_| ())?,
82+
}))
83+
}
84+
}
85+
3686
/// An intermediate node, and possibly a short channel id leading to the next node.
3787
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
3888
pub struct ForwardNode {
@@ -88,10 +138,10 @@ impl Writeable for ReceiveTlvs {
88138
}
89139
}
90140

91-
/// Additional data included by the recipient in a [`BlindedPath`].
141+
/// Additional data included by the recipient in a [`BlindedMessagePath`].
92142
///
93143
/// This data is encrypted by the recipient and will be given to the corresponding message handler
94-
/// when handling a message sent over the [`BlindedPath`]. The recipient can use this data to
144+
/// when handling a message sent over the [`BlindedMessagePath`]. The recipient can use this data to
95145
/// authenticate the message or for further processing if needed.
96146
#[derive(Clone, Debug)]
97147
pub enum MessageContext {
@@ -110,7 +160,7 @@ pub enum MessageContext {
110160
/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
111161
#[derive(Clone, Debug, Eq, PartialEq)]
112162
pub enum OffersContext {
113-
/// Context used by a [`BlindedPath`] within an [`Offer`].
163+
/// Context used by a [`BlindedMessagePath`] within an [`Offer`].
114164
///
115165
/// This variant is intended to be received when handling an [`InvoiceRequest`].
116166
///
@@ -124,7 +174,7 @@ pub enum OffersContext {
124174
/// [`Offer`]: crate::offers::offer::Offer
125175
nonce: Nonce,
126176
},
127-
/// Context used by a [`BlindedPath`] within a [`Refund`] or as a reply path for an
177+
/// Context used by a [`BlindedMessagePath`] within a [`Refund`] or as a reply path for an
128178
/// [`InvoiceRequest`].
129179
///
130180
/// This variant is intended to be received when handling a [`Bolt12Invoice`] or an
@@ -155,7 +205,7 @@ pub enum OffersContext {
155205
/// [`InvoiceError`]: crate::offers::invoice_error::InvoiceError
156206
hmac: Option<Hmac<Sha256>>,
157207
},
158-
/// Context used by a [`BlindedPath`] as a reply path for a [`Bolt12Invoice`].
208+
/// Context used by a [`BlindedMessagePath`] as a reply path for a [`Bolt12Invoice`].
159209
///
160210
/// This variant is intended to be received when handling an [`InvoiceError`].
161211
///
@@ -213,16 +263,16 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
213263
//
214264
// Will only modify `path` when returning `Ok`.
215265
pub(crate) fn advance_path_by_one<NS: Deref, NL: Deref, T>(
216-
path: &mut BlindedPath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>
266+
path: &mut BlindedMessagePath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>
217267
) -> Result<(), ()>
218268
where
219269
NS::Target: NodeSigner,
220270
NL::Target: NodeIdLookUp,
221271
T: secp256k1::Signing + secp256k1::Verification,
222272
{
223-
let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?;
273+
let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.0.blinding_point, None)?;
224274
let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
225-
let encrypted_control_tlvs = &path.blinded_hops.get(0).ok_or(())?.encrypted_payload;
275+
let encrypted_control_tlvs = &path.0.blinded_hops.get(0).ok_or(())?.encrypted_payload;
226276
let mut s = Cursor::new(encrypted_control_tlvs);
227277
let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64);
228278
match ChaChaPolyReadAdapter::read(&mut reader, rho) {
@@ -239,13 +289,13 @@ where
239289
let mut new_blinding_point = match next_blinding_override {
240290
Some(blinding_point) => blinding_point,
241291
None => {
242-
onion_utils::next_hop_pubkey(secp_ctx, path.blinding_point,
292+
onion_utils::next_hop_pubkey(secp_ctx, path.0.blinding_point,
243293
control_tlvs_ss.as_ref()).map_err(|_| ())?
244294
}
245295
};
246-
mem::swap(&mut path.blinding_point, &mut new_blinding_point);
247-
path.introduction_node = IntroductionNode::NodeId(next_node_id);
248-
path.blinded_hops.remove(0);
296+
mem::swap(&mut path.0.blinding_point, &mut new_blinding_point);
297+
path.0.introduction_node = IntroductionNode::NodeId(next_node_id);
298+
path.0.blinded_hops.remove(0);
249299
Ok(())
250300
},
251301
_ => Err(())

lightning/src/blinded_path/mod.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@ pub mod payment;
1313
pub mod message;
1414
pub(crate) mod utils;
1515

16-
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
17-
use message::MessageContext;
16+
use bitcoin::secp256k1::PublicKey;
1817
use core::ops::Deref;
1918

2019
use crate::ln::msgs::DecodeError;
2120
use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph};
22-
use crate::sign::EntropySource;
2321
use crate::util::ser::{Readable, Writeable, Writer};
2422
use crate::util::scid_utils;
2523

@@ -121,38 +119,6 @@ pub struct BlindedHop {
121119
}
122120

123121
impl BlindedPath {
124-
/// Create a one-hop blinded path for a message.
125-
pub fn one_hop_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
126-
recipient_node_id: PublicKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
127-
) -> Result<Self, ()> where ES::Target: EntropySource {
128-
Self::new_for_message(&[], recipient_node_id, context, entropy_source, secp_ctx)
129-
}
130-
131-
/// Create a blinded path for an onion message, to be forwarded along `node_pks`. The last node
132-
/// pubkey in `node_pks` will be the destination node.
133-
///
134-
/// Errors if no hops are provided or if `node_pk`(s) are invalid.
135-
// TODO: make all payloads the same size with padding + add dummy hops
136-
pub fn new_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
137-
intermediate_nodes: &[message::ForwardNode], recipient_node_id: PublicKey,
138-
context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
139-
) -> Result<Self, ()> where ES::Target: EntropySource {
140-
let introduction_node = IntroductionNode::NodeId(
141-
intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id)
142-
);
143-
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
144-
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
145-
146-
Ok(BlindedPath {
147-
introduction_node,
148-
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
149-
blinded_hops: message::blinded_hops(
150-
secp_ctx, intermediate_nodes, recipient_node_id,
151-
context, &blinding_secret,
152-
).map_err(|_| ())?,
153-
})
154-
}
155-
156122
/// Returns the introduction [`NodeId`] of the blinded path, if it is publicly reachable (i.e.,
157123
/// it is found in the network graph).
158124
pub fn public_introduction_node_id<'a>(

lightning/src/blinded_path/utils.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey, Scalar};
1616
use bitcoin::secp256k1::ecdh::SharedSecret;
1717

1818
use super::{BlindedHop, BlindedPath};
19+
use super::message::BlindedMessagePath;
1920
use crate::ln::msgs::DecodeError;
2021
use crate::ln::onion_utils;
2122
use crate::onion_message::messenger::Destination;
@@ -97,7 +98,7 @@ where
9798
Destination::Node(pk) => {
9899
build_keys!(pk, false, None);
99100
},
100-
Destination::BlindedPath(BlindedPath { blinded_hops, .. }) => {
101+
Destination::BlindedPath(BlindedMessagePath(BlindedPath { blinded_hops, .. })) => {
101102
for hop in blinded_hops {
102103
build_keys_in_loop!(hop.blinded_node_id, true, Some(hop.encrypted_payload));
103104
}

lightning/src/events/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,9 +811,9 @@ pub enum Event {
811811
payment_id: PaymentId,
812812
/// The invoice to pay.
813813
invoice: Bolt12Invoice,
814-
/// The context of the [`BlindedPath`] used to send the invoice.
814+
/// The context of the [`BlindedMessagePath`] used to send the invoice.
815815
///
816-
/// [`BlindedPath`]: crate::blinded_path::BlindedPath
816+
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath
817817
context: Option<OffersContext>,
818818
/// A responder for replying with an [`InvoiceError`] if needed.
819819
///

lightning/src/ln/channelmanager.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use bitcoin::secp256k1::Secp256k1;
3232
use bitcoin::{secp256k1, Sequence};
3333

3434
use crate::blinded_path::message::{MessageContext, OffersContext};
35-
use crate::blinded_path::{BlindedPath, NodeIdLookUp};
36-
use crate::blinded_path::message::ForwardNode;
35+
use crate::blinded_path::NodeIdLookUp;
36+
use crate::blinded_path::message::{BlindedMessagePath, ForwardNode};
3737
use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
3838
use crate::chain;
3939
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
@@ -2472,11 +2472,11 @@ const MAX_NO_CHANNEL_PEERS: usize = 250;
24722472
/// short-lived, while anything with a greater expiration is considered long-lived.
24732473
///
24742474
/// Using [`ChannelManager::create_offer_builder`] or [`ChannelManager::create_refund_builder`],
2475-
/// will included a [`BlindedPath`] created using:
2475+
/// will included a [`BlindedMessagePath`] created using:
24762476
/// - [`MessageRouter::create_compact_blinded_paths`] when short-lived, and
24772477
/// - [`MessageRouter::create_blinded_paths`] when long-lived.
24782478
///
2479-
/// Using compact [`BlindedPath`]s may provide better privacy as the [`MessageRouter`] could select
2479+
/// Using compact [`BlindedMessagePath`]s may provide better privacy as the [`MessageRouter`] could select
24802480
/// more hops. However, since they use short channel ids instead of pubkeys, they are more likely to
24812481
/// become invalid over time as channels are closed. Thus, they are only suitable for short-term use.
24822482
pub const MAX_SHORT_LIVED_RELATIVE_EXPIRY: Duration = Duration::from_secs(60 * 60 * 24);
@@ -8789,7 +8789,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
87898789
///
87908790
/// # Privacy
87918791
///
8792-
/// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the offer based on the given
8792+
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the offer based on the given
87938793
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
87948794
/// privacy implications as well as those of the parameterized [`Router`], which implements
87958795
/// [`MessageRouter`].
@@ -8856,7 +8856,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
88568856
///
88578857
/// # Privacy
88588858
///
8859-
/// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the refund based on the given
8859+
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the refund based on the given
88608860
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
88618861
/// privacy implications as well as those of the parameterized [`Router`], which implements
88628862
/// [`MessageRouter`].
@@ -8970,7 +8970,7 @@ where
89708970
/// # Privacy
89718971
///
89728972
/// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`]
8973-
/// to construct a [`BlindedPath`] for the reply path. For further privacy implications, see the
8973+
/// to construct a [`BlindedMessagePath`] for the reply path. For further privacy implications, see the
89748974
/// docs of the parameterized [`Router`], which implements [`MessageRouter`].
89758975
///
89768976
/// # Limitations
@@ -9273,7 +9273,7 @@ where
92739273
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
92749274
fn create_blinded_paths_using_absolute_expiry(
92759275
&self, context: OffersContext, absolute_expiry: Option<Duration>,
9276-
) -> Result<Vec<BlindedPath>, ()> {
9276+
) -> Result<Vec<BlindedMessagePath>, ()> {
92779277
let now = self.duration_since_epoch();
92789278
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
92799279

@@ -9301,7 +9301,7 @@ where
93019301
/// [`MessageRouter::create_blinded_paths`].
93029302
///
93039303
/// Errors if the `MessageRouter` errors.
9304-
fn create_blinded_paths(&self, context: OffersContext) -> Result<Vec<BlindedPath>, ()> {
9304+
fn create_blinded_paths(&self, context: OffersContext) -> Result<Vec<BlindedMessagePath>, ()> {
93059305
let recipient = self.get_our_node_id();
93069306
let secp_ctx = &self.secp_ctx;
93079307

@@ -9322,7 +9322,7 @@ where
93229322
/// [`MessageRouter::create_compact_blinded_paths`].
93239323
///
93249324
/// Errors if the `MessageRouter` errors.
9325-
fn create_compact_blinded_paths(&self, context: OffersContext) -> Result<Vec<BlindedPath>, ()> {
9325+
fn create_compact_blinded_paths(&self, context: OffersContext) -> Result<Vec<BlindedMessagePath>, ()> {
93269326
let recipient = self.get_our_node_id();
93279327
let secp_ctx = &self.secp_ctx;
93289328

0 commit comments

Comments
 (0)