Skip to content

Commit 3584371

Browse files
Add BlindedMessagePath type to disambiguate from blinded payment paths.
1 parent 44956bd commit 3584371

File tree

20 files changed

+262
-250
lines changed

20 files changed

+262
-250
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};
@@ -141,7 +140,7 @@ impl MessageRouter for FuzzRouter {
141140
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
142141
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
143142
_secp_ctx: &Secp256k1<T>,
144-
) -> Result<Vec<BlindedPath>, ()> {
143+
) -> Result<Vec<BlindedMessagePath>, ()> {
145144
unreachable!()
146145
}
147146
}

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::sha256d::Hash as Sha256dHash;
3030
use bitcoin::hashes::Hash as _;
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;
@@ -178,7 +177,7 @@ impl MessageRouter for FuzzRouter {
178177
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
179178
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
180179
_secp_ctx: &Secp256k1<T>,
181-
) -> Result<Vec<BlindedPath>, ()> {
180+
) -> Result<Vec<BlindedMessagePath>, ()> {
182181
unreachable!()
183182
}
184183
}

fuzz/src/onion_message.rs

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

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

lightning/src/blinded_path/message.rs

Lines changed: 60 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

@@ -21,16 +19,61 @@ use crate::blinded_path::utils;
2119
use crate::io;
2220
use crate::io::Cursor;
2321
use crate::ln::channelmanager::PaymentId;
22+
use crate::ln::msgs::DecodeError;
2423
use crate::ln::{PaymentHash, onion_utils};
2524
use crate::offers::nonce::Nonce;
2625
use crate::onion_message::packet::ControlTlvs;
27-
use crate::sign::{NodeSigner, Recipient};
26+
use crate::sign::{EntropySource, NodeSigner, Recipient};
2827
use crate::crypto::streams::ChaChaPolyReadAdapter;
29-
use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
28+
use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Readable, Writeable, Writer};
3029

3130
use core::mem;
3231
use core::ops::Deref;
3332

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

89-
/// Additional data included by the recipient in a [`BlindedPath`].
132+
/// Additional data included by the recipient in a [`BlindedMessagePath`].
90133
///
91134
/// This data is encrypted by the recipient and will be given to the corresponding message handler
92-
/// when handling a message sent over the [`BlindedPath`]. The recipient can use this data to
135+
/// when handling a message sent over the [`BlindedMessagePath`]. The recipient can use this data to
93136
/// authenticate the message or for further processing if needed.
94137
#[derive(Clone, Debug)]
95138
pub enum MessageContext {
@@ -108,7 +151,7 @@ pub enum MessageContext {
108151
/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
109152
#[derive(Clone, Debug, Eq, PartialEq)]
110153
pub enum OffersContext {
111-
/// Context used by a [`BlindedPath`] within an [`Offer`].
154+
/// Context used by a [`BlindedMessagePath`] within an [`Offer`].
112155
///
113156
/// This variant is intended to be received when handling an [`InvoiceRequest`].
114157
///
@@ -122,7 +165,7 @@ pub enum OffersContext {
122165
/// [`Offer`]: crate::offers::offer::Offer
123166
nonce: Nonce,
124167
},
125-
/// Context used by a [`BlindedPath`] within a [`Refund`] or as a reply path for an
168+
/// Context used by a [`BlindedMessagePath`] within a [`Refund`] or as a reply path for an
126169
/// [`InvoiceRequest`].
127170
///
128171
/// This variant is intended to be received when handling a [`Bolt12Invoice`] or an
@@ -147,7 +190,7 @@ pub enum OffersContext {
147190
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
148191
nonce: Nonce,
149192
},
150-
/// Context used by a [`BlindedPath`] as a reply path for a [`Bolt12Invoice`].
193+
/// Context used by a [`BlindedMessagePath`] as a reply path for a [`Bolt12Invoice`].
151194
///
152195
/// This variant is intended to be received when handling an [`InvoiceError`].
153196
///
@@ -204,16 +247,16 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
204247
//
205248
// Will only modify `path` when returning `Ok`.
206249
pub(crate) fn advance_path_by_one<NS: Deref, NL: Deref, T>(
207-
path: &mut BlindedPath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>
250+
path: &mut BlindedMessagePath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>
208251
) -> Result<(), ()>
209252
where
210253
NS::Target: NodeSigner,
211254
NL::Target: NodeIdLookUp,
212255
T: secp256k1::Signing + secp256k1::Verification,
213256
{
214-
let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?;
257+
let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.0.blinding_point, None)?;
215258
let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
216-
let encrypted_control_tlvs = &path.blinded_hops.get(0).ok_or(())?.encrypted_payload;
259+
let encrypted_control_tlvs = &path.0.blinded_hops.get(0).ok_or(())?.encrypted_payload;
217260
let mut s = Cursor::new(encrypted_control_tlvs);
218261
let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64);
219262
match ChaChaPolyReadAdapter::read(&mut reader, rho) {
@@ -230,13 +273,13 @@ where
230273
let mut new_blinding_point = match next_blinding_override {
231274
Some(blinding_point) => blinding_point,
232275
None => {
233-
onion_utils::next_hop_pubkey(secp_ctx, path.blinding_point,
276+
onion_utils::next_hop_pubkey(secp_ctx, path.0.blinding_point,
234277
control_tlvs_ss.as_ref()).map_err(|_| ())?
235278
}
236279
};
237-
mem::swap(&mut path.blinding_point, &mut new_blinding_point);
238-
path.introduction_node = IntroductionNode::NodeId(next_node_id);
239-
path.blinded_hops.remove(0);
280+
mem::swap(&mut path.0.blinding_point, &mut new_blinding_point);
281+
path.0.introduction_node = IntroductionNode::NodeId(next_node_id);
282+
path.0.blinded_hops.remove(0);
240283
Ok(())
241284
},
242285
_ => 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
@@ -807,9 +807,9 @@ pub enum Event {
807807
payment_id: PaymentId,
808808
/// The invoice to pay.
809809
invoice: Bolt12Invoice,
810-
/// The context of the [`BlindedPath`] used to send the invoice.
810+
/// The context of the [`BlindedMessagePath`] used to send the invoice.
811811
///
812-
/// [`BlindedPath`]: crate::blinded_path::BlindedPath
812+
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath
813813
context: Option<OffersContext>,
814814
/// A responder for replying with an [`InvoiceError`] if needed.
815815
///

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);
@@ -8786,7 +8786,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
87868786
///
87878787
/// # Privacy
87888788
///
8789-
/// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the offer based on the given
8789+
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the offer based on the given
87908790
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
87918791
/// privacy implications as well as those of the parameterized [`Router`], which implements
87928792
/// [`MessageRouter`].
@@ -8853,7 +8853,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
88538853
///
88548854
/// # Privacy
88558855
///
8856-
/// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the refund based on the given
8856+
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the refund based on the given
88578857
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
88588858
/// privacy implications as well as those of the parameterized [`Router`], which implements
88598859
/// [`MessageRouter`].
@@ -8967,7 +8967,7 @@ where
89678967
/// # Privacy
89688968
///
89698969
/// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`]
8970-
/// to construct a [`BlindedPath`] for the reply path. For further privacy implications, see the
8970+
/// to construct a [`BlindedMessagePath`] for the reply path. For further privacy implications, see the
89718971
/// docs of the parameterized [`Router`], which implements [`MessageRouter`].
89728972
///
89738973
/// # Limitations
@@ -9269,7 +9269,7 @@ where
92699269
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
92709270
fn create_blinded_paths_using_absolute_expiry(
92719271
&self, context: OffersContext, absolute_expiry: Option<Duration>,
9272-
) -> Result<Vec<BlindedPath>, ()> {
9272+
) -> Result<Vec<BlindedMessagePath>, ()> {
92739273
let now = self.duration_since_epoch();
92749274
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
92759275

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

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

0 commit comments

Comments
 (0)