Skip to content

Commit 402682e

Browse files
WIP: move BlindedPayInfo into BlindedPaymentPath.
Also removes the implementation of Writeable for BlindedPaymentPath, to ensure callsites are explicit about what they're writing.
1 parent 8fe3a56 commit 402682e

File tree

11 files changed

+152
-104
lines changed

11 files changed

+152
-104
lines changed

lightning/src/blinded_path/payment.rs

+57-30
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,27 @@ use crate::prelude::*;
3737
/// A blinded path to be used for sending or receiving a payment, hiding the identity of the
3838
/// recipient.
3939
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
40-
pub struct BlindedPaymentPath(pub(super) BlindedPath);
40+
pub struct BlindedPaymentPath {
41+
pub(super) inner_path: BlindedPath,
42+
/// The [`BlindedPayInfo`] used to pay this blinded path.
43+
pub payinfo: BlindedPayInfo,
44+
}
45+
46+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
47+
pub(crate) struct WriteableBlindedPath<'a>(&'a BlindedPath);
4148

42-
impl Writeable for BlindedPaymentPath {
49+
impl<'a> Writeable for WriteableBlindedPath<'a> {
4350
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
4451
self.0.write(w)
4552
}
4653
}
4754

48-
impl Readable for BlindedPaymentPath {
55+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
56+
pub(crate) struct ReadableBlindedPath(BlindedPath);
57+
58+
impl Readable for ReadableBlindedPath {
4959
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
50-
Ok(Self(BlindedPath::read(r)?))
60+
Ok(ReadableBlindedPath(Readable::read(r)?))
5161
}
5262
}
5363

@@ -56,7 +66,7 @@ impl BlindedPaymentPath {
5666
pub fn one_hop<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
5767
payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs, min_final_cltv_expiry_delta: u16,
5868
entropy_source: ES, secp_ctx: &Secp256k1<T>
59-
) -> Result<(BlindedPayInfo, Self), ()> where ES::Target: EntropySource {
69+
) -> Result<Self, ()> where ES::Target: EntropySource {
6070
// This value is not considered in pathfinding for 1-hop blinded paths, because it's intended to
6171
// be in relation to a specific channel.
6272
let htlc_maximum_msat = u64::max_value();
@@ -77,7 +87,7 @@ impl BlindedPaymentPath {
7787
intermediate_nodes: &[ForwardNode], payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs,
7888
htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16, entropy_source: ES,
7989
secp_ctx: &Secp256k1<T>
80-
) -> Result<(BlindedPayInfo, Self), ()> where ES::Target: EntropySource {
90+
) -> Result<Self, ()> where ES::Target: EntropySource {
8191
let introduction_node = IntroductionNode::NodeId(
8292
intermediate_nodes.first().map_or(payee_node_id, |n| n.node_id)
8393
);
@@ -87,38 +97,41 @@ impl BlindedPaymentPath {
8797
let blinded_payinfo = compute_payinfo(
8898
intermediate_nodes, &payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta
8999
)?;
90-
Ok((blinded_payinfo, Self(BlindedPath {
91-
introduction_node,
92-
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
93-
blinded_hops: blinded_hops(
94-
secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret
95-
).map_err(|_| ())?,
96-
})))
100+
Ok(Self {
101+
inner_path: BlindedPath {
102+
introduction_node,
103+
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
104+
blinded_hops: blinded_hops(
105+
secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret
106+
).map_err(|_| ())?,
107+
},
108+
payinfo: blinded_payinfo
109+
})
97110
}
98111

99112
/// Returns the introduction [`NodeId`] of the blinded path, if it is publicly reachable (i.e.,
100113
/// it is found in the network graph).
101114
pub fn public_introduction_node_id<'a>(
102115
&self, network_graph: &'a ReadOnlyNetworkGraph
103116
) -> Option<&'a NodeId> {
104-
self.0.public_introduction_node_id(network_graph)
117+
self.inner_path.public_introduction_node_id(network_graph)
105118
}
106119

107120
/// The [`IntroductionNode`] of the blinded path.
108121
pub fn introduction_node(&self) -> &IntroductionNode {
109-
&self.0.introduction_node
122+
&self.inner_path.introduction_node
110123
}
111124

112125
/// Used by the [`IntroductionNode`] to decrypt its [`encrypted_payload`] to forward the payment.
113126
///
114127
/// [`encrypted_payload`]: BlindedHop::encrypted_payload
115128
pub fn blinding_point(&self) -> PublicKey {
116-
self.0.blinding_point
129+
self.inner_path.blinding_point
117130
}
118131

119132
/// The [`BlindedHop`]s within the blinded path.
120133
pub fn blinded_hops(&self) -> &[BlindedHop] {
121-
&self.0.blinded_hops
134+
&self.inner_path.blinded_hops
122135
}
123136

124137
/// Advance the blinded onion payment path by one hop, making the second hop into the new
@@ -133,9 +146,9 @@ impl BlindedPaymentPath {
133146
NL::Target: NodeIdLookUp,
134147
T: secp256k1::Signing + secp256k1::Verification,
135148
{
136-
let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &self.0.blinding_point, None)?;
149+
let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &self.inner_path.blinding_point, None)?;
137150
let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
138-
let encrypted_control_tlvs = &self.0.blinded_hops.get(0).ok_or(())?.encrypted_payload;
151+
let encrypted_control_tlvs = &self.inner_path.blinded_hops.get(0).ok_or(())?.encrypted_payload;
139152
let mut s = Cursor::new(encrypted_control_tlvs);
140153
let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64);
141154
match ChaChaPolyReadAdapter::read(&mut reader, rho) {
@@ -147,31 +160,45 @@ impl BlindedPaymentPath {
147160
None => return Err(()),
148161
};
149162
let mut new_blinding_point = onion_utils::next_hop_pubkey(
150-
secp_ctx, self.0.blinding_point, control_tlvs_ss.as_ref()
163+
secp_ctx, self.inner_path.blinding_point, control_tlvs_ss.as_ref()
151164
).map_err(|_| ())?;
152-
mem::swap(&mut self.0.blinding_point, &mut new_blinding_point);
153-
self.0.introduction_node = IntroductionNode::NodeId(next_node_id);
154-
self.0.blinded_hops.remove(0);
165+
mem::swap(&mut self.inner_path.blinding_point, &mut new_blinding_point);
166+
self.inner_path.introduction_node = IntroductionNode::NodeId(next_node_id);
167+
self.inner_path.blinded_hops.remove(0);
155168
Ok(())
156169
},
157170
_ => Err(())
158171
}
159172
}
160173

174+
pub(crate) fn writeable_path(&self) -> WriteableBlindedPath {
175+
WriteableBlindedPath(&self.inner_path)
176+
}
177+
178+
pub(crate) fn from_readable_blinded_path(
179+
inner_path: ReadableBlindedPath, payinfo: BlindedPayInfo
180+
) -> Self {
181+
Self { inner_path: inner_path.0, payinfo }
182+
}
183+
161184
#[cfg(any(test, fuzzing))]
162185
pub fn from_raw(
163-
introduction_node_id: PublicKey, blinding_point: PublicKey, blinded_hops: Vec<BlindedHop>
186+
introduction_node_id: PublicKey, blinding_point: PublicKey, blinded_hops: Vec<BlindedHop>,
187+
payinfo: BlindedPayInfo
164188
) -> Self {
165-
Self(BlindedPath {
166-
introduction_node: IntroductionNode::NodeId(introduction_node_id),
167-
blinding_point,
168-
blinded_hops,
169-
})
189+
Self {
190+
inner_path: BlindedPath {
191+
introduction_node: IntroductionNode::NodeId(introduction_node_id),
192+
blinding_point,
193+
blinded_hops,
194+
},
195+
payinfo
196+
}
170197
}
171198

172199
#[cfg(test)]
173200
pub fn clear_blinded_hops(&mut self) {
174-
self.0.blinded_hops.clear()
201+
self.inner_path.blinded_hops.clear()
175202
}
176203
}
177204

lightning/src/ln/channelmanager.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
6161
use crate::ln::outbound_payment;
6262
use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration};
6363
use crate::ln::wire::Encode;
64-
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
64+
use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
6565
use crate::offers::invoice_error::InvoiceError;
6666
use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder};
6767
use crate::offers::nonce::Nonce;
@@ -9350,7 +9350,7 @@ where
93509350
/// [`Router::create_blinded_payment_paths`].
93519351
fn create_blinded_payment_paths(
93529352
&self, amount_msats: u64, payment_secret: PaymentSecret, payment_context: PaymentContext
9353-
) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, ()> {
9353+
) -> Result<Vec<BlindedPaymentPath>, ()> {
93549354
let secp_ctx = &self.secp_ctx;
93559355

93569356
let first_hops = self.list_usable_channels();

lightning/src/ln/onion_utils.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,7 @@ pub(crate) fn set_max_path_length(
337337
.payee
338338
.blinded_route_hints()
339339
.iter()
340-
.map(|(_, path)| path)
341-
.max_by_key(|path| path.serialized_length())
340+
.max_by_key(|path| path.writeable_path().serialized_length())
342341
.map(|largest_path| BlindedTailHopIter {
343342
hops: largest_path.blinded_hops().iter(),
344343
blinding_point: largest_path.blinding_point(),

lightning/src/ln/outbound_payment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ impl OutboundPayments {
833833

834834
// Advance any blinded path where the introduction node is our node.
835835
if let Ok(our_node_id) = node_signer.get_node_id(Recipient::Node) {
836-
for (_, path) in payment_params.payee.blinded_route_hints_mut().iter_mut() {
836+
for path in payment_params.payee.blinded_route_hints_mut().iter_mut() {
837837
let introduction_node_id = match path.introduction_node() {
838838
IntroductionNode::NodeId(pubkey) => *pubkey,
839839
IntroductionNode::DirectedShortChannelId(direction, scid) => {

lightning/src/offers/invoice.rs

+26-21
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
//! # use lightning::offers::invoice::{BlindedPayInfo, ExplicitSigningPubkey, InvoiceBuilder};
3333
//! # use lightning::blinded_path::payment::BlindedPaymentPath;
3434
//! #
35-
//! # fn create_payment_paths() -> Vec<(BlindedPayInfo, BlindedPaymentPath)> { unimplemented!() }
35+
//! # fn create_payment_paths() -> Vec<BlindedPaymentPath> { unimplemented!() }
3636
//! # fn create_payment_hash() -> PaymentHash { unimplemented!() }
3737
//! #
3838
//! # fn parse_invoice_request(bytes: Vec<u8>) -> Result<(), lightning::offers::parse::Bolt12ParseError> {
@@ -111,7 +111,7 @@ use core::time::Duration;
111111
use core::hash::{Hash, Hasher};
112112
use crate::io;
113113
use crate::blinded_path::message::BlindedMessagePath;
114-
use crate::blinded_path::payment::BlindedPaymentPath;
114+
use crate::blinded_path::payment::{WriteableBlindedPath, ReadableBlindedPath, BlindedPaymentPath};
115115
use crate::ln::types::PaymentHash;
116116
use crate::ln::channelmanager::PaymentId;
117117
use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures};
@@ -128,7 +128,7 @@ use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage}
128128
use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef};
129129
use crate::offers::refund::{IV_BYTES_WITH_METADATA as REFUND_IV_BYTES_WITH_METADATA, IV_BYTES_WITHOUT_METADATA as REFUND_IV_BYTES_WITHOUT_METADATA, Refund, RefundContents};
130130
use crate::offers::signer::{Metadata, self};
131-
use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, Readable, SeekReadable, WithoutLength, Writeable, Writer};
131+
use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, IterableOwned, Readable, SeekReadable, WithoutLength, Writeable, Writer};
132132
use crate::util::string::PrintableString;
133133

134134
#[allow(unused_imports)]
@@ -212,7 +212,7 @@ impl SigningPubkeyStrategy for DerivedSigningPubkey {}
212212
macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => {
213213
#[cfg_attr(c_bindings, allow(dead_code))]
214214
pub(super) fn for_offer(
215-
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
215+
invoice_request: &'a InvoiceRequest, payment_paths: Vec<BlindedPaymentPath>,
216216
created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey
217217
) -> Result<Self, Bolt12SemanticError> {
218218
let amount_msats = Self::amount_msats(invoice_request)?;
@@ -228,7 +228,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $s
228228

229229
#[cfg_attr(c_bindings, allow(dead_code))]
230230
pub(super) fn for_refund(
231-
refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, created_at: Duration,
231+
refund: &'a Refund, payment_paths: Vec<BlindedPaymentPath>, created_at: Duration,
232232
payment_hash: PaymentHash, signing_pubkey: PublicKey
233233
) -> Result<Self, Bolt12SemanticError> {
234234
let amount_msats = refund.amount_msats();
@@ -270,7 +270,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $s
270270
macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => {
271271
#[cfg_attr(c_bindings, allow(dead_code))]
272272
pub(super) fn for_offer_using_keys(
273-
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
273+
invoice_request: &'a InvoiceRequest, payment_paths: Vec<BlindedPaymentPath>,
274274
created_at: Duration, payment_hash: PaymentHash, keys: Keypair
275275
) -> Result<Self, Bolt12SemanticError> {
276276
let amount_msats = Self::amount_msats(invoice_request)?;
@@ -287,7 +287,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $se
287287

288288
#[cfg_attr(c_bindings, allow(dead_code))]
289289
pub(super) fn for_refund_using_keys(
290-
refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, created_at: Duration,
290+
refund: &'a Refund, payment_paths: Vec<BlindedPaymentPath>, created_at: Duration,
291291
payment_hash: PaymentHash, keys: Keypair,
292292
) -> Result<Self, Bolt12SemanticError> {
293293
let amount_msats = refund.amount_msats();
@@ -356,8 +356,8 @@ macro_rules! invoice_builder_methods { (
356356

357357
#[cfg_attr(c_bindings, allow(dead_code))]
358358
fn fields(
359-
payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, created_at: Duration,
360-
payment_hash: PaymentHash, amount_msats: u64, signing_pubkey: PublicKey
359+
payment_paths: Vec<BlindedPaymentPath>, created_at: Duration, payment_hash: PaymentHash,
360+
amount_msats: u64, signing_pubkey: PublicKey
361361
) -> InvoiceFields {
362362
InvoiceFields {
363363
payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats,
@@ -603,7 +603,7 @@ enum InvoiceContents {
603603
/// Invoice-specific fields for an `invoice` message.
604604
#[derive(Clone, Debug, PartialEq)]
605605
struct InvoiceFields {
606-
payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
606+
payment_paths: Vec<BlindedPaymentPath>,
607607
created_at: Duration,
608608
relative_expiry: Option<Duration>,
609609
payment_hash: PaymentHash,
@@ -988,7 +988,7 @@ impl InvoiceContents {
988988
}
989989
}
990990

991-
fn payment_paths(&self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
991+
fn payment_paths(&self) -> &[BlindedPaymentPath] {
992992
&self.fields().payment_paths[..]
993993
}
994994

@@ -1125,8 +1125,8 @@ impl InvoiceFields {
11251125
};
11261126

11271127
InvoiceTlvStreamRef {
1128-
paths: Some(Iterable(self.payment_paths.iter().map(|(_, path)| path))),
1129-
blindedpay: Some(Iterable(self.payment_paths.iter().map(|(payinfo, _)| payinfo))),
1128+
paths: Some(IterableOwned(self.payment_paths.iter().map(|path| path.writeable_path()))),
1129+
blindedpay: Some(Iterable(self.payment_paths.iter().map(|path| &path.payinfo))),
11301130
created_at: Some(self.created_at.as_secs()),
11311131
relative_expiry: self.relative_expiry.map(|duration| duration.as_secs() as u32),
11321132
payment_hash: Some(&self.payment_hash),
@@ -1193,7 +1193,7 @@ impl TryFrom<Vec<u8>> for Bolt12Invoice {
11931193
}
11941194

11951195
tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
1196-
(160, paths: (Vec<BlindedPaymentPath>, WithoutLength, Iterable<'a, BlindedPathIter<'a>, BlindedPaymentPath>)),
1196+
(160, paths: (Vec<ReadableBlindedPath>, WithoutLength, IterableOwned<BlindedPathIter<'a>, WriteableBlindedPath<'a>>)),
11971197
(162, blindedpay: (Vec<BlindedPayInfo>, WithoutLength, Iterable<'a, BlindedPayInfoIter<'a>, BlindedPayInfo>)),
11981198
(164, created_at: (u64, HighZeroBytesDroppedBigSize)),
11991199
(166, relative_expiry: (u32, HighZeroBytesDroppedBigSize)),
@@ -1207,13 +1207,13 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
12071207
});
12081208

12091209
pub(super) type BlindedPathIter<'a> = core::iter::Map<
1210-
core::slice::Iter<'a, (BlindedPayInfo, BlindedPaymentPath)>,
1211-
for<'r> fn(&'r (BlindedPayInfo, BlindedPaymentPath)) -> &'r BlindedPaymentPath,
1210+
core::slice::Iter<'a, BlindedPaymentPath>,
1211+
for<'r> fn(&'r BlindedPaymentPath) -> WriteableBlindedPath<'r>,
12121212
>;
12131213

12141214
pub(super) type BlindedPayInfoIter<'a> = core::iter::Map<
1215-
core::slice::Iter<'a, (BlindedPayInfo, BlindedPaymentPath)>,
1216-
for<'r> fn(&'r (BlindedPayInfo, BlindedPaymentPath)) -> &'r BlindedPayInfo,
1215+
core::slice::Iter<'a, BlindedPaymentPath>,
1216+
for<'r> fn(&'r BlindedPaymentPath) -> &'r BlindedPayInfo,
12171217
>;
12181218

12191219
/// Information needed to route a payment across a [`BlindedPaymentPath`].
@@ -1388,8 +1388,8 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
13881388
}
13891389

13901390
pub(super) fn construct_payment_paths(
1391-
blinded_payinfos: Option<Vec<BlindedPayInfo>>, blinded_paths: Option<Vec<BlindedPaymentPath>>
1392-
) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, Bolt12SemanticError> {
1391+
blinded_payinfos: Option<Vec<BlindedPayInfo>>, blinded_paths: Option<Vec<ReadableBlindedPath>>
1392+
) -> Result<Vec<BlindedPaymentPath>, Bolt12SemanticError> {
13931393
match (blinded_payinfos, blinded_paths) {
13941394
(_, None) => Err(Bolt12SemanticError::MissingPaths),
13951395
(None, _) => Err(Bolt12SemanticError::InvalidPayInfo),
@@ -1398,7 +1398,12 @@ pub(super) fn construct_payment_paths(
13981398
Err(Bolt12SemanticError::InvalidPayInfo)
13991399
},
14001400
(Some(blindedpay), Some(paths)) => {
1401-
Ok(blindedpay.into_iter().zip(paths.into_iter()).collect::<Vec<_>>())
1401+
Ok(blindedpay
1402+
.into_iter()
1403+
.zip(paths.into_iter())
1404+
.map(|(payinfo, path)| BlindedPaymentPath::from_readable_blinded_path(path, payinfo))
1405+
.collect::<Vec<_>>()
1406+
)
14021407
},
14031408
}
14041409
}

lightning/src/offers/invoice_macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ macro_rules! invoice_accessors_common { ($self: ident, $contents: expr, $invoice
107107
///
108108
/// This is not exported to bindings users as slices with non-reference types cannot be ABI
109109
/// matched in another language.
110-
pub fn payment_paths(&$self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
110+
pub fn payment_paths(&$self) -> &[BlindedPaymentPath] {
111111
$contents.payment_paths()
112112
}
113113

0 commit comments

Comments
 (0)