};
use lightning::ln::script::ShutdownScript;
use lightning::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
+use lightning::offers::invoice::UnsignedBolt12Invoice;
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath};
use lightning::routing::router::{InFlightHtlcs, Path, Route, RouteHop, RouteParameters, Router};
fn create_blinded_payment_paths<T: secp256k1::Signing + secp256k1::Verification>(
&self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
_amount_msats: u64, _secp_ctx: &Secp256k1<T>,
- ) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, ()> {
+ ) -> Result<Vec<BlindedPaymentPath>, ()> {
unreachable!()
}
}
};
use lightning::ln::script::ShutdownScript;
use lightning::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
+use lightning::offers::invoice::UnsignedBolt12Invoice;
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath};
use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
fn create_blinded_payment_paths<T: secp256k1::Signing + secp256k1::Verification>(
&self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
_amount_msats: u64, _secp_ctx: &Secp256k1<T>,
- ) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, ()> {
+ ) -> Result<Vec<BlindedPaymentPath>, ()> {
unreachable!()
}
}
let mut last_hops_unblinded = Vec::new();
last_hops!(last_hops_unblinded);
let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap();
- let last_hops: Vec<(BlindedPayInfo, BlindedPaymentPath)> = last_hops_unblinded
+ let last_hops: Vec<BlindedPaymentPath> = last_hops_unblinded
.into_iter()
.map(|hint| {
let hop = &hint.0[0];
encrypted_payload: Vec::new(),
});
}
- (
+ BlindedPaymentPath::from_raw(
+ hop.src_node_id,
+ dummy_pk,
+ blinded_hops,
payinfo,
- BlindedPaymentPath::from_raw(hop.src_node_id, dummy_pk, blinded_hops),
)
})
.collect();
/// Onion messages and payments can be sent and received to blinded paths, which serve to hide the
/// identity of the recipient.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
-struct BlindedPath {
+pub(crate) struct BlindedPath {
/// To send to a blinded path, the sender first finds a route to the unblinded
/// `introduction_node`, which can unblind its [`encrypted_payload`] to find out the onion
/// message or payment's next hop and forward it along.
/// A blinded path to be used for sending or receiving a payment, hiding the identity of the
/// recipient.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
-pub struct BlindedPaymentPath(pub(super) BlindedPath);
-
-impl Writeable for BlindedPaymentPath {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- self.0.write(w)
- }
-}
-
-impl Readable for BlindedPaymentPath {
- fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
- Ok(Self(BlindedPath::read(r)?))
- }
+pub struct BlindedPaymentPath {
+ pub(super) inner_path: BlindedPath,
+ /// The [`BlindedPayInfo`] used to pay this blinded path.
+ pub payinfo: BlindedPayInfo,
}
impl BlindedPaymentPath {
pub fn one_hop<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs, min_final_cltv_expiry_delta: u16,
entropy_source: ES, secp_ctx: &Secp256k1<T>
- ) -> Result<(BlindedPayInfo, Self), ()> where ES::Target: EntropySource {
+ ) -> Result<Self, ()> where ES::Target: EntropySource {
// This value is not considered in pathfinding for 1-hop blinded paths, because it's intended to
// be in relation to a specific channel.
let htlc_maximum_msat = u64::max_value();
intermediate_nodes: &[ForwardNode], payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs,
htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16, entropy_source: ES,
secp_ctx: &Secp256k1<T>
- ) -> Result<(BlindedPayInfo, Self), ()> where ES::Target: EntropySource {
+ ) -> Result<Self, ()> where ES::Target: EntropySource {
let introduction_node = IntroductionNode::NodeId(
intermediate_nodes.first().map_or(payee_node_id, |n| n.node_id)
);
let blinded_payinfo = compute_payinfo(
intermediate_nodes, &payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta
)?;
- Ok((blinded_payinfo, Self(BlindedPath {
- introduction_node,
- blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
- blinded_hops: blinded_hops(
- secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret
- ).map_err(|_| ())?,
- })))
+ Ok(Self {
+ inner_path: BlindedPath {
+ introduction_node,
+ blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
+ blinded_hops: blinded_hops(
+ secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret
+ ).map_err(|_| ())?,
+ },
+ payinfo: blinded_payinfo
+ })
}
/// Returns the introduction [`NodeId`] of the blinded path, if it is publicly reachable (i.e.,
pub fn public_introduction_node_id<'a>(
&self, network_graph: &'a ReadOnlyNetworkGraph
) -> Option<&'a NodeId> {
- self.0.public_introduction_node_id(network_graph)
+ self.inner_path.public_introduction_node_id(network_graph)
}
/// The [`IntroductionNode`] of the blinded path.
pub fn introduction_node(&self) -> &IntroductionNode {
- &self.0.introduction_node
+ &self.inner_path.introduction_node
}
/// Used by the [`IntroductionNode`] to decrypt its [`encrypted_payload`] to forward the payment.
///
/// [`encrypted_payload`]: BlindedHop::encrypted_payload
pub fn blinding_point(&self) -> PublicKey {
- self.0.blinding_point
+ self.inner_path.blinding_point
}
/// The [`BlindedHop`]s within the blinded path.
pub fn blinded_hops(&self) -> &[BlindedHop] {
- &self.0.blinded_hops
+ &self.inner_path.blinded_hops
}
/// Advance the blinded onion payment path by one hop, making the second hop into the new
NL::Target: NodeIdLookUp,
T: secp256k1::Signing + secp256k1::Verification,
{
- let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &self.0.blinding_point, None)?;
+ let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &self.inner_path.blinding_point, None)?;
let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
- let encrypted_control_tlvs = &self.0.blinded_hops.get(0).ok_or(())?.encrypted_payload;
+ let encrypted_control_tlvs = &self.inner_path.blinded_hops.get(0).ok_or(())?.encrypted_payload;
let mut s = Cursor::new(encrypted_control_tlvs);
let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64);
match ChaChaPolyReadAdapter::read(&mut reader, rho) {
None => return Err(()),
};
let mut new_blinding_point = onion_utils::next_hop_pubkey(
- secp_ctx, self.0.blinding_point, control_tlvs_ss.as_ref()
+ secp_ctx, self.inner_path.blinding_point, control_tlvs_ss.as_ref()
).map_err(|_| ())?;
- mem::swap(&mut self.0.blinding_point, &mut new_blinding_point);
- self.0.introduction_node = IntroductionNode::NodeId(next_node_id);
- self.0.blinded_hops.remove(0);
+ mem::swap(&mut self.inner_path.blinding_point, &mut new_blinding_point);
+ self.inner_path.introduction_node = IntroductionNode::NodeId(next_node_id);
+ self.inner_path.blinded_hops.remove(0);
Ok(())
},
_ => Err(())
}
}
+ pub(crate) fn inner_blinded_path(&self) -> &BlindedPath {
+ &self.inner_path
+ }
+
+ pub(crate) fn from_parts(inner_path: BlindedPath, payinfo: BlindedPayInfo) -> Self {
+ Self { inner_path, payinfo }
+ }
+
#[cfg(any(test, fuzzing))]
pub fn from_raw(
- introduction_node_id: PublicKey, blinding_point: PublicKey, blinded_hops: Vec<BlindedHop>
+ introduction_node_id: PublicKey, blinding_point: PublicKey, blinded_hops: Vec<BlindedHop>,
+ payinfo: BlindedPayInfo
) -> Self {
- Self(BlindedPath {
- introduction_node: IntroductionNode::NodeId(introduction_node_id),
- blinding_point,
- blinded_hops,
- })
+ Self {
+ inner_path: BlindedPath {
+ introduction_node: IntroductionNode::NodeId(introduction_node_id),
+ blinding_point,
+ blinded_hops,
+ },
+ payinfo
+ }
}
#[cfg(test)]
pub fn clear_blinded_hops(&mut self) {
- self.0.blinded_hops.clear()
+ self.inner_path.blinded_hops.clear()
}
}
use crate::ln::onion_utils;
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
use crate::ln::outbound_payment::{Retry, IDEMPOTENCY_TIMEOUT_TICKS};
-use crate::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
+use crate::offers::invoice::UnsignedBolt12Invoice;
use crate::offers::invoice_request::UnsignedInvoiceRequest;
use crate::prelude::*;
use crate::routing::router::{BlindedTail, Path, Payee, PaymentParameters, RouteHop, RouteParameters};
payment_secret: PaymentSecret, intro_node_min_htlc: u64, intro_node_max_htlc: u64,
node_ids: Vec<PublicKey>, channel_upds: &[&msgs::UnsignedChannelUpdate],
keys_manager: &test_utils::TestKeysInterface
-) -> (BlindedPayInfo, BlindedPaymentPath) {
+) -> BlindedPaymentPath {
let mut intermediate_nodes = Vec::new();
let mut intro_node_min_htlc_opt = Some(intro_node_min_htlc);
let mut intro_node_max_htlc_opt = Some(intro_node_max_htlc);
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&high_htlc_minimum_upd],
&chanmon_cfgs[2].keys_manager);
if let Payee::Blinded { route_hints, .. } = high_htlc_min_params.payment_params.payee {
- route_hints[0].1.clone()
+ route_hints[0].clone()
} else { panic!() }
};
if let Payee::Blinded { ref mut route_hints, .. } = route_params.payment_params.payee {
- route_hints[0].1 = high_htlc_min_bp;
+ route_hints[0] = high_htlc_min_bp;
+ route_hints[0].payinfo.htlc_minimum_msat = amt_msat;
} else { panic!() }
find_route(&nodes[0], &route_params).unwrap()
} else {
nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()],
&[&chan_1_2.0.contents, &chan_2_3.0.contents], &chanmon_cfgs[3].keys_manager);
assert_eq!(min_htlc_msat,
- route_params.payment_params.payee.blinded_route_hints()[0].0.htlc_minimum_msat);
+ route_params.payment_params.payee.blinded_route_hints()[0].payinfo.htlc_minimum_msat);
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
nodes[0].node.timer_tick_occurred();
}
if let Payee::Blinded { ref mut route_hints, .. } = route_params.payment_params.payee {
- route_hints[0].0.htlc_minimum_msat -= 1;
+ route_hints[0].payinfo.htlc_minimum_msat -= 1;
} else { panic!() }
route_params.final_value_msat -= 1;
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
use crate::ln::outbound_payment;
use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration};
use crate::ln::wire::Encode;
-use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
+use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
use crate::offers::invoice_error::InvoiceError;
use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder};
use crate::offers::nonce::Nonce;
/// [`Router::create_blinded_payment_paths`].
fn create_blinded_payment_paths(
&self, amount_msats: u64, payment_secret: PaymentSecret, payment_context: PaymentContext
- ) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, ()> {
+ ) -> Result<Vec<BlindedPaymentPath>, ()> {
let secp_ctx = &self.secp_ctx;
let first_hops = self.list_usable_channels();
sender_intended_htlc_amt_msat: MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY,
total_msat: MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY,
cltv_expiry_height: nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
- encrypted_tlvs: &blinded_path.1.blinded_hops()[0].encrypted_payload,
- intro_node_blinding_point: Some(blinded_path.1.blinding_point()),
+ encrypted_tlvs: &blinded_path.blinded_hops()[0].encrypted_payload,
+ intro_node_blinding_point: Some(blinded_path.blinding_point()),
keysend_preimage: None,
custom_tlvs: &Vec::new()
}.serialized_length();
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes(&nodes, 0, 1);
- nodes[1].router.expect_blinded_payment_paths(vec![(
- BlindedPayInfo {
- fee_base_msat: 42,
- fee_proportional_millionths: 42,
- cltv_expiry_delta: 42,
- htlc_minimum_msat: 42,
- htlc_maximum_msat: 42_000_000,
- features: BlindedHopFeatures::empty(),
- },
+ nodes[1].router.expect_blinded_payment_paths(vec![
BlindedPaymentPath::from_raw(
PublicKey::from_slice(&[2; 33]).unwrap(), PublicKey::from_slice(&[2; 33]).unwrap(),
vec![
blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(),
encrypted_payload: vec![42; 1300],
},
- ]
+ ],
+ BlindedPayInfo {
+ fee_base_msat: 42,
+ fee_proportional_millionths: 42,
+ cltv_expiry_delta: 42,
+ htlc_minimum_msat: 42,
+ htlc_maximum_msat: 42_000_000,
+ features: BlindedHopFeatures::empty(),
+ }
)
- )]);
+ ]);
let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
let payment_id = PaymentId([1; 32]);
assert_eq!(invoice.amount_msats(), 10_000_000);
assert_ne!(invoice.signing_pubkey(), alice_id);
assert!(!invoice.payment_paths().is_empty());
- for (_, path) in invoice.payment_paths() {
+ for path in invoice.payment_paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
}
assert_eq!(invoice.amount_msats(), 10_000_000);
assert_ne!(invoice.signing_pubkey(), alice_id);
assert!(!invoice.payment_paths().is_empty());
- for (_, path) in invoice.payment_paths() {
+ for path in invoice.payment_paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
}
assert_eq!(invoice.amount_msats(), 10_000_000);
assert_ne!(invoice.signing_pubkey(), alice_id);
assert!(!invoice.payment_paths().is_empty());
- for (_, path) in invoice.payment_paths() {
+ for path in invoice.payment_paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id));
}
assert_eq!(invoice.amount_msats(), 10_000_000);
assert_ne!(invoice.signing_pubkey(), alice_id);
assert!(!invoice.payment_paths().is_empty());
- for (_, path) in invoice.payment_paths() {
+ for path in invoice.payment_paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id));
}
assert_eq!(invoice.amount_msats(), 10_000_000);
assert_ne!(invoice.signing_pubkey(), alice_id);
assert!(!invoice.payment_paths().is_empty());
- for (_, path) in invoice.payment_paths() {
+ for path in invoice.payment_paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id));
}
let (invoice, _) = extract_invoice(bob, &onion_message);
assert_ne!(invoice.signing_pubkey(), alice_id);
assert!(!invoice.payment_paths().is_empty());
- for (_, path) in invoice.payment_paths() {
+ for path in invoice.payment_paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
}
assert_eq!(invoice, expected_invoice);
assert_ne!(invoice.signing_pubkey(), alice_id);
assert!(!invoice.payment_paths().is_empty());
- for (_, path) in invoice.payment_paths() {
+ for path in invoice.payment_paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
}
}
.payee
.blinded_route_hints()
.iter()
- .map(|(_, path)| path)
- .max_by_key(|path| path.serialized_length())
+ .max_by_key(|path| path.inner_blinded_path().serialized_length())
.map(|largest_path| BlindedTailHopIter {
hops: largest_path.blinded_hops().iter(),
blinding_point: largest_path.blinding_point(),
// Advance any blinded path where the introduction node is our node.
if let Ok(our_node_id) = node_signer.get_node_id(Recipient::Node) {
- for (_, path) in payment_params.payee.blinded_route_hints_mut().iter_mut() {
+ for path in payment_params.payee.blinded_route_hints_mut().iter_mut() {
let introduction_node_id = match path.introduction_node() {
IntroductionNode::NodeId(pubkey) => *pubkey,
IntroductionNode::DirectedShortChannelId(direction, scid) => {
//! # use lightning::offers::invoice::{BlindedPayInfo, ExplicitSigningPubkey, InvoiceBuilder};
//! # use lightning::blinded_path::payment::BlindedPaymentPath;
//! #
-//! # fn create_payment_paths() -> Vec<(BlindedPayInfo, BlindedPaymentPath)> { unimplemented!() }
+//! # fn create_payment_paths() -> Vec<BlindedPaymentPath> { unimplemented!() }
//! # fn create_payment_hash() -> PaymentHash { unimplemented!() }
//! #
//! # fn parse_invoice_request(bytes: Vec<u8>) -> Result<(), lightning::offers::parse::Bolt12ParseError> {
use core::time::Duration;
use core::hash::{Hash, Hasher};
use crate::io;
+use crate::blinded_path::BlindedPath;
use crate::blinded_path::message::BlindedMessagePath;
use crate::blinded_path::payment::BlindedPaymentPath;
use crate::ln::types::PaymentHash;
macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => {
#[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn for_offer(
- invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
+ invoice_request: &'a InvoiceRequest, payment_paths: Vec<BlindedPaymentPath>,
created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey
) -> Result<Self, Bolt12SemanticError> {
let amount_msats = Self::amount_msats(invoice_request)?;
#[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn for_refund(
- refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, created_at: Duration,
+ refund: &'a Refund, payment_paths: Vec<BlindedPaymentPath>, created_at: Duration,
payment_hash: PaymentHash, signing_pubkey: PublicKey
) -> Result<Self, Bolt12SemanticError> {
let amount_msats = refund.amount_msats();
macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => {
#[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn for_offer_using_keys(
- invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
+ invoice_request: &'a InvoiceRequest, payment_paths: Vec<BlindedPaymentPath>,
created_at: Duration, payment_hash: PaymentHash, keys: Keypair
) -> Result<Self, Bolt12SemanticError> {
let amount_msats = Self::amount_msats(invoice_request)?;
#[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn for_refund_using_keys(
- refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, created_at: Duration,
+ refund: &'a Refund, payment_paths: Vec<BlindedPaymentPath>, created_at: Duration,
payment_hash: PaymentHash, keys: Keypair,
) -> Result<Self, Bolt12SemanticError> {
let amount_msats = refund.amount_msats();
#[cfg_attr(c_bindings, allow(dead_code))]
fn fields(
- payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, created_at: Duration,
- payment_hash: PaymentHash, amount_msats: u64, signing_pubkey: PublicKey
+ payment_paths: Vec<BlindedPaymentPath>, created_at: Duration, payment_hash: PaymentHash,
+ amount_msats: u64, signing_pubkey: PublicKey
) -> InvoiceFields {
InvoiceFields {
payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats,
/// Invoice-specific fields for an `invoice` message.
#[derive(Clone, Debug, PartialEq)]
struct InvoiceFields {
- payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
+ payment_paths: Vec<BlindedPaymentPath>,
created_at: Duration,
relative_expiry: Option<Duration>,
payment_hash: PaymentHash,
}
}
- fn payment_paths(&self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
+ fn payment_paths(&self) -> &[BlindedPaymentPath] {
&self.fields().payment_paths[..]
}
};
InvoiceTlvStreamRef {
- paths: Some(Iterable(self.payment_paths.iter().map(|(_, path)| path))),
- blindedpay: Some(Iterable(self.payment_paths.iter().map(|(payinfo, _)| payinfo))),
+ paths: Some(Iterable(self.payment_paths.iter().map(|path| path.inner_blinded_path()))),
+ blindedpay: Some(Iterable(self.payment_paths.iter().map(|path| &path.payinfo))),
created_at: Some(self.created_at.as_secs()),
relative_expiry: self.relative_expiry.map(|duration| duration.as_secs() as u32),
payment_hash: Some(&self.payment_hash),
}
tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
- (160, paths: (Vec<BlindedPaymentPath>, WithoutLength, Iterable<'a, BlindedPathIter<'a>, BlindedPaymentPath>)),
+ (160, paths: (Vec<BlindedPath>, WithoutLength, Iterable<'a, BlindedPathIter<'a>, BlindedPath>)),
(162, blindedpay: (Vec<BlindedPayInfo>, WithoutLength, Iterable<'a, BlindedPayInfoIter<'a>, BlindedPayInfo>)),
(164, created_at: (u64, HighZeroBytesDroppedBigSize)),
(166, relative_expiry: (u32, HighZeroBytesDroppedBigSize)),
});
pub(super) type BlindedPathIter<'a> = core::iter::Map<
- core::slice::Iter<'a, (BlindedPayInfo, BlindedPaymentPath)>,
- for<'r> fn(&'r (BlindedPayInfo, BlindedPaymentPath)) -> &'r BlindedPaymentPath,
+ core::slice::Iter<'a, BlindedPaymentPath>,
+ for<'r> fn(&'r BlindedPaymentPath) -> &'r BlindedPath,
>;
pub(super) type BlindedPayInfoIter<'a> = core::iter::Map<
- core::slice::Iter<'a, (BlindedPayInfo, BlindedPaymentPath)>,
- for<'r> fn(&'r (BlindedPayInfo, BlindedPaymentPath)) -> &'r BlindedPayInfo,
+ core::slice::Iter<'a, BlindedPaymentPath>,
+ for<'r> fn(&'r BlindedPaymentPath) -> &'r BlindedPayInfo,
>;
/// Information needed to route a payment across a [`BlindedPaymentPath`].
}
pub(super) fn construct_payment_paths(
- blinded_payinfos: Option<Vec<BlindedPayInfo>>, blinded_paths: Option<Vec<BlindedPaymentPath>>
-) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, Bolt12SemanticError> {
+ blinded_payinfos: Option<Vec<BlindedPayInfo>>, blinded_paths: Option<Vec<BlindedPath>>
+) -> Result<Vec<BlindedPaymentPath>, Bolt12SemanticError> {
match (blinded_payinfos, blinded_paths) {
(_, None) => Err(Bolt12SemanticError::MissingPaths),
(None, _) => Err(Bolt12SemanticError::InvalidPayInfo),
Err(Bolt12SemanticError::InvalidPayInfo)
},
(Some(blindedpay), Some(paths)) => {
- Ok(blindedpay.into_iter().zip(paths.into_iter()).collect::<Vec<_>>())
+ Ok(blindedpay
+ .into_iter()
+ .zip(paths.into_iter())
+ .map(|(payinfo, path)| BlindedPaymentPath::from_parts(path, payinfo))
+ .collect::<Vec<_>>()
+ )
},
}
}
paths: None,
},
InvoiceTlvStreamRef {
- paths: Some(Iterable(payment_paths.iter().map(|(_, path)| path))),
- blindedpay: Some(Iterable(payment_paths.iter().map(|(payinfo, _)| payinfo))),
+ paths: Some(Iterable(payment_paths.iter().map(|path| path.inner_blinded_path()))),
+ blindedpay: Some(Iterable(payment_paths.iter().map(|path| &path.payinfo))),
created_at: Some(now.as_secs()),
relative_expiry: None,
payment_hash: Some(&payment_hash),
paths: None,
},
InvoiceTlvStreamRef {
- paths: Some(Iterable(payment_paths.iter().map(|(_, path)| path))),
- blindedpay: Some(Iterable(payment_paths.iter().map(|(payinfo, _)| payinfo))),
+ paths: Some(Iterable(payment_paths.iter().map(|path| path.inner_blinded_path()))),
+ blindedpay: Some(Iterable(payment_paths.iter().map(|path| &path.payinfo))),
created_at: Some(now.as_secs()),
relative_expiry: None,
payment_hash: Some(&payment_hash),
let empty_payment_paths = vec![];
let mut tlv_stream = invoice.as_tlv_stream();
- tlv_stream.3.paths = Some(Iterable(empty_payment_paths.iter().map(|(_, path)| path)));
+ tlv_stream.3.paths = Some(Iterable(empty_payment_paths.iter().map(|path| path.inner_blinded_path())));
match Bolt12Invoice::try_from(tlv_stream.to_bytes()) {
Ok(_) => panic!("expected error"),
let mut payment_paths = payment_paths();
payment_paths.pop();
let mut tlv_stream = invoice.as_tlv_stream();
- tlv_stream.3.blindedpay = Some(Iterable(payment_paths.iter().map(|(payinfo, _)| payinfo)));
+ tlv_stream.3.blindedpay = Some(Iterable(payment_paths.iter().map(|path| &path.payinfo)));
match Bolt12Invoice::try_from(tlv_stream.to_bytes()) {
Ok(_) => panic!("expected error"),
///
/// This is not exported to bindings users as slices with non-reference types cannot be ABI
/// matched in another language.
- pub fn payment_paths(&$self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
+ pub fn payment_paths(&$self) -> &[BlindedPaymentPath] {
$contents.payment_paths()
}
use crate::ln::features::InvoiceRequestFeatures;
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN};
use crate::ln::msgs::DecodeError;
-use crate::offers::invoice::BlindedPayInfo;
use crate::offers::merkle::{SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, self};
use crate::offers::nonce::Nonce;
use crate::offers::offer::{Offer, OfferContents, OfferId, OfferTlvStream, OfferTlvStreamRef};
/// [`Duration`]: core::time::Duration
#[cfg(feature = "std")]
pub fn respond_with(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash
) -> Result<$builder, Bolt12SemanticError> {
let created_at = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
/// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
pub fn respond_with_no_std(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
created_at: core::time::Duration
) -> Result<$builder, Bolt12SemanticError> {
if $contents.invoice_request_features().requires_unknown_bits() {
#[cfg(test)]
#[allow(dead_code)]
pub(super) fn respond_with_no_std_using_signing_pubkey(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
created_at: core::time::Duration, signing_pubkey: PublicKey
) -> Result<$builder, Bolt12SemanticError> {
debug_assert!($contents.contents.inner.offer.signing_pubkey().is_none());
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
#[cfg(feature = "std")]
pub fn respond_using_derived_keys(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash
) -> Result<$builder, Bolt12SemanticError> {
let created_at = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
pub fn respond_using_derived_keys_no_std(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
created_at: core::time::Duration
) -> Result<$builder, Bolt12SemanticError> {
if $self.inner.invoice_request_features().requires_unknown_bits() {
use crate::ln::features::InvoiceRequestFeatures;
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN};
use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
-use crate::offers::invoice::BlindedPayInfo;
use crate::offers::invoice_request::{InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef};
use crate::offers::nonce::Nonce;
use crate::offers::offer::{OfferTlvStream, OfferTlvStreamRef};
/// [`Duration`]: core::time::Duration
#[cfg(feature = "std")]
pub fn respond_with(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
signing_pubkey: PublicKey,
) -> Result<$builder, Bolt12SemanticError> {
let created_at = std::time::SystemTime::now()
///
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
pub fn respond_with_no_std(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
signing_pubkey: PublicKey, created_at: Duration
) -> Result<$builder, Bolt12SemanticError> {
if $self.features().requires_unknown_bits() {
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
#[cfg(feature = "std")]
pub fn respond_using_derived_keys<ES: Deref>(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
expanded_key: &ExpandedKey, entropy_source: ES
) -> Result<$builder, Bolt12SemanticError>
where
///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
pub fn respond_using_derived_keys_no_std<ES: Deref>(
- &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
created_at: core::time::Duration, expanded_key: &ExpandedKey, entropy_source: ES
) -> Result<$builder, Bolt12SemanticError>
where
use crate::ln::inbound_payment::ExpandedKey;
use crate::ln::msgs::DecodeError;
use crate::offers::invoice::{
- check_invoice_signing_pubkey, construct_payment_paths, filter_fallbacks, BlindedPayInfo,
- FallbackAddress, InvoiceTlvStream, InvoiceTlvStreamRef,
+ check_invoice_signing_pubkey, construct_payment_paths, filter_fallbacks, FallbackAddress,
+ InvoiceTlvStream, InvoiceTlvStreamRef,
};
use crate::offers::invoice_macros::{invoice_accessors_common, invoice_builder_methods_common};
use crate::offers::merkle::{
#[derive(Clone, Debug)]
struct InvoiceContents {
offer: OfferContents,
- payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
+ payment_paths: Vec<BlindedPaymentPath>,
created_at: Duration,
relative_expiry: Option<Duration>,
fallbacks: Option<Vec<FallbackAddress>>,
/// Unless [`StaticInvoiceBuilder::relative_expiry`] is set, the invoice will expire 24 hours
/// after `created_at`.
pub fn for_offer_using_derived_keys<T: secp256k1::Signing>(
- offer: &'a Offer, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
+ offer: &'a Offer, payment_paths: Vec<BlindedPaymentPath>,
message_paths: Vec<BlindedMessagePath>, created_at: Duration, expanded_key: &ExpandedKey,
nonce: Nonce, secp_ctx: &Secp256k1<T>,
) -> Result<Self, Bolt12SemanticError> {
}
fn new(
- offer: &Offer, payment_paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
+ offer: &Offer, payment_paths: Vec<BlindedPaymentPath>,
message_paths: Vec<BlindedMessagePath>, created_at: Duration, signing_pubkey: PublicKey,
) -> Self {
Self {
};
let invoice = InvoiceTlvStreamRef {
- paths: Some(Iterable(self.payment_paths.iter().map(|(_, path)| path))),
+ paths: Some(Iterable(self.payment_paths.iter().map(|path| path.inner_blinded_path()))),
message_paths: Some(self.message_paths.as_ref()),
- blindedpay: Some(Iterable(self.payment_paths.iter().map(|(payinfo, _)| payinfo))),
+ blindedpay: Some(Iterable(self.payment_paths.iter().map(|path| &path.payinfo))),
created_at: Some(self.created_at.as_secs()),
relative_expiry: self.relative_expiry.map(|duration| duration.as_secs() as u32),
fallbacks: self.fallbacks.as_ref(),
self.offer.supported_quantity()
}
- fn payment_paths(&self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
+ fn payment_paths(&self) -> &[BlindedPaymentPath] {
&self.payment_paths[..]
}
node_id: Some(&offer_signing_pubkey),
},
InvoiceTlvStreamRef {
- paths: Some(Iterable(payment_paths.iter().map(|(_, path)| path))),
- blindedpay: Some(Iterable(payment_paths.iter().map(|(payinfo, _)| payinfo))),
+ paths: Some(Iterable(
+ payment_paths.iter().map(|path| path.inner_blinded_path())
+ )),
+ blindedpay: Some(Iterable(payment_paths.iter().map(|path| &path.payinfo))),
created_at: Some(now.as_secs()),
relative_expiry: None,
payment_hash: None,
SecretKey::from_slice(&[byte; 32]).unwrap()
}
-pub(crate) fn payment_paths() -> Vec<(BlindedPayInfo, BlindedPaymentPath)> {
- let paths = vec![
+pub(crate) fn payment_paths() -> Vec<BlindedPaymentPath> {
+ vec![
BlindedPaymentPath::from_raw(
pubkey(40), pubkey(41),
vec![
BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] },
BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] },
- ]
+ ],
+ BlindedPayInfo {
+ fee_base_msat: 1,
+ fee_proportional_millionths: 1_000,
+ cltv_expiry_delta: 42,
+ htlc_minimum_msat: 100,
+ htlc_maximum_msat: 1_000_000_000_000,
+ features: BlindedHopFeatures::empty(),
+ },
),
BlindedPaymentPath::from_raw(
pubkey(40), pubkey(41),
vec![
BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] },
BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] },
- ]
+ ],
+ BlindedPayInfo {
+ fee_base_msat: 1,
+ fee_proportional_millionths: 1_000,
+ cltv_expiry_delta: 42,
+ htlc_minimum_msat: 100,
+ htlc_maximum_msat: 1_000_000_000_000,
+ features: BlindedHopFeatures::empty(),
+ },
),
- ];
-
- let payinfo = vec![
- BlindedPayInfo {
- fee_base_msat: 1,
- fee_proportional_millionths: 1_000,
- cltv_expiry_delta: 42,
- htlc_minimum_msat: 100,
- htlc_maximum_msat: 1_000_000_000_000,
- features: BlindedHopFeatures::empty(),
- },
- BlindedPayInfo {
- fee_base_msat: 1,
- fee_proportional_millionths: 1_000,
- cltv_expiry_delta: 42,
- htlc_minimum_msat: 100,
- htlc_maximum_msat: 1_000_000_000_000,
- features: BlindedHopFeatures::empty(),
- },
- ];
-
- payinfo.into_iter().zip(paths.into_iter()).collect()
+ ]
}
pub(crate) fn payment_hash() -> PaymentHash {
use crate::ln::features::{BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures};
use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
use crate::ln::onion_utils;
-use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice};
+use crate::offers::invoice::Bolt12Invoice;
use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath};
use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId};
use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp};
> (
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
amount_msats: u64, secp_ctx: &Secp256k1<T>
- ) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, ()> {
+ ) -> Result<Vec<BlindedPaymentPath>, ()> {
// Limit the number of blinded paths that are computed.
const MAX_PAYMENT_PATHS: usize = 3;
> (
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
amount_msats: u64, secp_ctx: &Secp256k1<T>
- ) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, ()>;
+ ) -> Result<Vec<BlindedPaymentPath>, ()>;
}
/// [`ScoreLookUp`] implementation that factors in in-flight HTLC liquidity.
impl Writeable for PaymentParameters {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
let mut clear_hints = &vec![];
- let mut blinded_hints = &vec![];
+ let mut blinded_hints = None;
match &self.payee {
Payee::Clear { route_hints, .. } => clear_hints = route_hints,
- Payee::Blinded { route_hints, .. } => blinded_hints = route_hints,
+ Payee::Blinded { route_hints, .. } => {
+ let hints_iter = route_hints.iter().map(|path| (&path.payinfo, path.inner_blinded_path()));
+ blinded_hints = Some(crate::util::ser::IterableOwned(hints_iter));
+ }
}
write_tlv_fields!(writer, {
(0, self.payee.node_id(), option),
(5, self.max_channel_saturation_power_of_half, required),
(6, self.expiry_time, option),
(7, self.previously_failed_channels, required_vec),
- (8, *blinded_hints, optional_vec),
+ (8, blinded_hints, option),
(9, self.payee.final_cltv_expiry_delta(), option),
(11, self.previously_failed_blinded_path_idxs, required_vec),
(13, self.max_path_length, required),
let payee = if blinded_route_hints.len() != 0 {
if clear_route_hints.len() != 0 || payee_pubkey.is_some() { return Err(DecodeError::InvalidValue) }
Payee::Blinded {
- route_hints: blinded_route_hints,
+ route_hints: blinded_route_hints
+ .into_iter()
+ .map(|(payinfo, path)| BlindedPaymentPath::from_parts(path, payinfo))
+ .collect(),
features: features.and_then(|f: Features| f.bolt12()),
}
} else {
}
/// Creates parameters for paying to a blinded payee from the provided blinded route hints.
- pub fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPaymentPath)>) -> Self {
+ pub fn blinded(blinded_route_hints: Vec<BlindedPaymentPath>) -> Self {
Self {
payee: Payee::Blinded { route_hints: blinded_route_hints, features: None },
expiry_time: None,
pub(crate) fn insert_previously_failed_blinded_path(&mut self, failed_blinded_tail: &BlindedTail) {
let mut found_blinded_tail = false;
- for (idx, (_, path)) in self.payee.blinded_route_hints().iter().enumerate() {
+ for (idx, path) in self.payee.blinded_route_hints().iter().enumerate() {
if &failed_blinded_tail.hops == path.blinded_hops() &&
failed_blinded_tail.blinding_point == path.blinding_point()
{
Blinded {
/// Aggregated routing info and blinded paths, for routing to the payee without knowing their
/// node id.
- route_hints: Vec<(BlindedPayInfo, BlindedPaymentPath)>,
+ route_hints: Vec<BlindedPaymentPath>,
/// Features supported by the payee.
///
/// May be set from the payee's invoice. May be `None` if the invoice does not contain any
_ => None,
}
}
- pub(crate) fn blinded_route_hints(&self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
+ pub(crate) fn blinded_route_hints(&self) -> &[BlindedPaymentPath] {
match self {
Self::Blinded { route_hints, .. } => &route_hints[..],
Self::Clear { .. } => &[]
}
}
- pub(crate) fn blinded_route_hints_mut(&mut self) -> &mut [(BlindedPayInfo, BlindedPaymentPath)] {
+ pub(crate) fn blinded_route_hints_mut(&mut self) -> &mut [BlindedPaymentPath] {
match self {
Self::Blinded { route_hints, .. } => &mut route_hints[..],
Self::Clear { .. } => &mut []
/// cryptographic material required to build an HTLC through the given path.
///
/// This is not exported to bindings users as lifetimes are not expressible in most languages.
- pub hint: &'a (BlindedPayInfo, BlindedPaymentPath),
+ pub hint: &'a BlindedPaymentPath,
/// Index of the hint in the original list of blinded hints.
///
/// This is used to cheaply uniquely identify this blinded path, even though we don't have
/// Note that the [`BlindedPayInfo`] is ignored here.
///
/// This is not exported to bindings users as lifetimes are not expressible in most languages.
- pub hint: &'a (BlindedPayInfo, BlindedPaymentPath),
+ ///
+ /// [`BlindedPayInfo`]: crate::offers::invoice::BlindedPayInfo
+ pub hint: &'a BlindedPaymentPath,
/// Index of the hint in the original list of blinded hints.
///
/// This is used to cheaply uniquely identify this blinded path, even though we don't have
///
/// This primarily exists to track that we need to included a blinded path at the end of our
/// [`Route`], even though it doesn't actually add an additional hop in the payment.
+ ///
+ /// [`BlindedPayInfo`]: crate::offers::invoice::BlindedPayInfo
OneHopBlinded(OneHopBlindedPathCandidate<'a>),
}
CandidateRouteHop::FirstHop(_) => 0,
CandidateRouteHop::PublicHop(hop) => hop.info.direction().cltv_expiry_delta as u32,
CandidateRouteHop::PrivateHop(hop) => hop.hint.cltv_expiry_delta as u32,
- CandidateRouteHop::Blinded(hop) => hop.hint.0.cltv_expiry_delta as u32,
+ CandidateRouteHop::Blinded(hop) => hop.hint.payinfo.cltv_expiry_delta as u32,
CandidateRouteHop::OneHopBlinded(_) => 0,
}
}
CandidateRouteHop::FirstHop(hop) => hop.details.next_outbound_htlc_minimum_msat,
CandidateRouteHop::PublicHop(hop) => hop.info.direction().htlc_minimum_msat,
CandidateRouteHop::PrivateHop(hop) => hop.hint.htlc_minimum_msat.unwrap_or(0),
- CandidateRouteHop::Blinded(hop) => hop.hint.0.htlc_minimum_msat,
+ CandidateRouteHop::Blinded(hop) => hop.hint.payinfo.htlc_minimum_msat,
CandidateRouteHop::OneHopBlinded { .. } => 0,
}
}
CandidateRouteHop::PrivateHop(hop) => hop.hint.fees,
CandidateRouteHop::Blinded(hop) => {
RoutingFees {
- base_msat: hop.hint.0.fee_base_msat,
- proportional_millionths: hop.hint.0.fee_proportional_millionths
+ base_msat: hop.hint.payinfo.fee_base_msat,
+ proportional_millionths: hop.hint.payinfo.fee_proportional_millionths
}
},
CandidateRouteHop::OneHopBlinded(_) =>
CandidateRouteHop::PrivateHop(PrivateHopCandidate { hint: RouteHintHop { htlc_maximum_msat: None, .. }, .. }) =>
EffectiveCapacity::Infinite,
CandidateRouteHop::Blinded(hop) =>
- EffectiveCapacity::HintMaxHTLC { amount_msat: hop.hint.0.htlc_maximum_msat },
+ EffectiveCapacity::HintMaxHTLC { amount_msat: hop.hint.payinfo.htlc_maximum_msat },
CandidateRouteHop::OneHopBlinded(_) => EffectiveCapacity::Infinite,
}
}
fn blinded_path(&self) -> Option<&'a BlindedPaymentPath> {
match self {
CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => {
- Some(&hint.1)
+ Some(&hint)
},
_ => None,
}
) -> Result<Vec<Option<(&'a NodeId, u32)>>, LightningError>
where L::Target: Logger {
let introduction_node_id_cache = payment_params.payee.blinded_route_hints().iter()
- .map(|(_, path)| {
+ .map(|path| {
match path.introduction_node() {
IntroductionNode::NodeId(pubkey) => {
// Note that this will only return `Some` if the `pubkey` is somehow known to
if introduction_node_id_cache.iter().all(|info_opt| info_opt.map(|(a, _)| a) == Some(&our_node_id)) {
return Err(LightningError{err: "Cannot generate a route to blinded paths if we are the introduction node to all of them".to_owned(), action: ErrorAction::IgnoreError});
}
- for ((_, blinded_path), info_opt) in route_hints.iter().zip(introduction_node_id_cache.iter()) {
+ for (blinded_path, info_opt) in route_hints.iter().zip(introduction_node_id_cache.iter()) {
if blinded_path.blinded_hops().len() == 0 {
return Err(LightningError{err: "0-hop blinded path provided".to_owned(), action: ErrorAction::IgnoreError});
}
} else if blinded_path.blinded_hops().len() == 1 &&
route_hints
.iter().zip(introduction_node_id_cache.iter())
- .filter(|((_, p), _)| p.blinded_hops().len() == 1)
+ .filter(|(p, _)| p.blinded_hops().len() == 1)
.any(|(_, iter_info_opt)| iter_info_opt.is_some() && iter_info_opt != info_opt)
{
return Err(LightningError{err: format!("1-hop blinded paths must all have matching introduction node ids"), action: ErrorAction::IgnoreError});
match self.0 {
CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => {
"blinded route hint with introduction node ".fmt(f)?;
- match hint.1.introduction_node() {
+ match hint.introduction_node() {
IntroductionNode::NodeId(pubkey) => write!(f, "id {}", pubkey)?,
IntroductionNode::DirectedShortChannelId(direction, scid) => {
match direction {
}
}
" and blinding point ".fmt(f)?;
- hint.1.blinding_point().fmt(f)
+ hint.blinding_point().fmt(f)
},
CandidateRouteHop::FirstHop(_) => {
"first hop with SCID ".fmt(f)?;
let source_node_opt = introduction_node_id_cache[hint_idx];
let (source_node_id, source_node_counter) = if let Some(v) = source_node_opt { v } else { continue };
if our_node_id == *source_node_id { continue }
- let candidate = if hint.1.blinded_hops().len() == 1 {
+ let candidate = if hint.blinded_hops().len() == 1 {
CandidateRouteHop::OneHopBlinded(
OneHopBlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx }
)
}
}
- fn dummy_blinded_path(intro_node: PublicKey) -> BlindedPaymentPath {
+ fn dummy_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath {
BlindedPaymentPath::from_raw(
intro_node, ln_test_utils::pubkey(42),
vec![
BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }
- ]
+ ],
+ payinfo
)
}
- fn dummy_one_hop_blinded_path(intro_node: PublicKey) -> BlindedPaymentPath {
+ fn dummy_one_hop_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath {
BlindedPaymentPath::from_raw(
intro_node, ln_test_utils::pubkey(42),
vec![
BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
- ]
+ ],
+ payinfo
)
}
// MPP to a 1-hop blinded path for nodes[2]
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
- let blinded_path = dummy_one_hop_blinded_path(nodes[2]);
let blinded_payinfo = BlindedPayInfo { // These fields are ignored for 1-hop blinded paths
fee_base_msat: 0,
fee_proportional_millionths: 0,
cltv_expiry_delta: 0,
features: BlindedHopFeatures::empty(),
};
- let one_hop_blinded_payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), blinded_path.clone())])
+ let blinded_path = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone());
+ let one_hop_blinded_payment_params = PaymentParameters::blinded(vec![blinded_path.clone()])
.with_bolt12_features(bolt12_features.clone()).unwrap();
do_simple_mpp_route_test(one_hop_blinded_payment_params.clone());
// MPP to 3 2-hop blinded paths
- let blinded_path_node_0 = dummy_blinded_path(nodes[0]);
let mut node_0_payinfo = blinded_payinfo.clone();
node_0_payinfo.htlc_maximum_msat = 50_000;
+ let blinded_path_node_0 = dummy_blinded_path(nodes[0], node_0_payinfo);
- let blinded_path_node_7 = dummy_blinded_path(nodes[7]);
let mut node_7_payinfo = blinded_payinfo.clone();
node_7_payinfo.htlc_maximum_msat = 60_000;
+ let blinded_path_node_7 = dummy_blinded_path(nodes[7], node_7_payinfo);
- let blinded_path_node_1 = dummy_blinded_path(nodes[1]);
- let mut node_1_payinfo = blinded_payinfo.clone();
+ let mut node_1_payinfo = blinded_payinfo;
node_1_payinfo.htlc_maximum_msat = 180_000;
+ let blinded_path_node_1 = dummy_blinded_path(nodes[1], node_1_payinfo);
let two_hop_blinded_payment_params = PaymentParameters::blinded(
- vec![
- (node_0_payinfo, blinded_path_node_0),
- (node_7_payinfo, blinded_path_node_7),
- (node_1_payinfo, blinded_path_node_1)
- ])
+ vec![blinded_path_node_0, blinded_path_node_7, blinded_path_node_1])
.with_bolt12_features(bolt12_features).unwrap();
do_simple_mpp_route_test(two_hop_blinded_payment_params);
}
assert_eq!(
NodeId::from_pubkey(&path.hops.last().unwrap().pubkey),
payment_params.payee.blinded_route_hints().iter()
- .find(|(p, _)| p.htlc_maximum_msat == path.final_value_msat())
- .and_then(|(_, p)| p.public_introduction_node_id(&network_graph))
+ .find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat())
+ .and_then(|p| p.public_introduction_node_id(&network_graph))
.copied()
.unwrap()
);
assert_eq!(route.get_total_amount(), amt_msat);
// Make sure this works for blinded route hints.
- let blinded_path = dummy_blinded_path(intermed_node_id);
let blinded_payinfo = BlindedPayInfo {
fee_base_msat: 100,
fee_proportional_millionths: 0,
cltv_expiry_delta: 10,
features: BlindedHopFeatures::empty(),
};
+ let blinded_path = dummy_blinded_path(intermed_node_id, blinded_payinfo);
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
let payment_params = PaymentParameters::blinded(vec![
- (blinded_payinfo.clone(), blinded_path.clone()),
- (blinded_payinfo.clone(), blinded_path.clone())])
- .with_bolt12_features(bolt12_features).unwrap();
+ blinded_path.clone(), blinded_path.clone()
+ ]).with_bolt12_features(bolt12_features).unwrap();
let route_params = RouteParameters::from_payment_params_and_value(
payment_params, amt_msat);
let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 + i as u8), encrypted_payload: Vec::new() },
);
}
- let blinded_path = BlindedPaymentPath::from_raw(nodes[2], ln_test_utils::pubkey(42), blinded_hops);
let blinded_payinfo = BlindedPayInfo {
fee_base_msat: 100,
fee_proportional_millionths: 500,
cltv_expiry_delta: 15,
features: BlindedHopFeatures::empty(),
};
+ let blinded_path = BlindedPaymentPath::from_raw(nodes[2], ln_test_utils::pubkey(42), blinded_hops, blinded_payinfo.clone());
- let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), blinded_path.clone())]);
+ let payment_params = PaymentParameters::blinded(vec![blinded_path.clone()]);
let route_params = RouteParameters::from_payment_params_and_value(
payment_params, 1001);
let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
features: BlindedHopFeatures::empty(),
};
- let invalid_blinded_path_2 = dummy_one_hop_blinded_path(nodes[2]);
- let invalid_blinded_path_3 = dummy_one_hop_blinded_path(nodes[3]);
+ let invalid_blinded_path_2 = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone());
+ let invalid_blinded_path_3 = dummy_one_hop_blinded_path(nodes[3], blinded_payinfo.clone());
let payment_params = PaymentParameters::blinded(vec![
- (blinded_payinfo.clone(), invalid_blinded_path_2),
- (blinded_payinfo.clone(), invalid_blinded_path_3)]);
+ invalid_blinded_path_2, invalid_blinded_path_3]);
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
&scorer, &Default::default(), &random_seed_bytes)
_ => panic!("Expected error")
}
- let invalid_blinded_path = dummy_blinded_path(our_id);
- let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), invalid_blinded_path)]);
+ let invalid_blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
+ let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]);
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
&Default::default(), &random_seed_bytes)
_ => panic!("Expected error")
}
- let mut invalid_blinded_path = dummy_one_hop_blinded_path(ln_test_utils::pubkey(46));
+ let mut invalid_blinded_path = dummy_one_hop_blinded_path(ln_test_utils::pubkey(46), blinded_payinfo);
invalid_blinded_path.clear_blinded_hops();
- let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo, invalid_blinded_path)]);
+ let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]);
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
&Default::default(), &random_seed_bytes)
let config = UserConfig::default();
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
- let blinded_path_1 = dummy_blinded_path(nodes[2]);
let blinded_payinfo_1 = BlindedPayInfo {
fee_base_msat: 0,
fee_proportional_millionths: 0,
cltv_expiry_delta: 0,
features: BlindedHopFeatures::empty(),
};
+ let blinded_path_1 = dummy_blinded_path(nodes[2], blinded_payinfo_1.clone());
+ let mut blinded_payinfo_2 = blinded_payinfo_1;
+ blinded_payinfo_2.htlc_maximum_msat = 70_000;
let blinded_path_2 = BlindedPaymentPath::from_raw(nodes[2], ln_test_utils::pubkey(43),
vec![
BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }
- ]
+ ],
+ blinded_payinfo_2
);
- let mut blinded_payinfo_2 = blinded_payinfo_1.clone();
- blinded_payinfo_2.htlc_maximum_msat = 70_000;
- let blinded_hints = vec![
- (blinded_payinfo_1.clone(), blinded_path_1.clone()),
- (blinded_payinfo_2.clone(), blinded_path_2.clone()),
- ];
+ let blinded_hints = vec![blinded_path_1.clone(), blinded_path_2.clone()];
let payment_params = PaymentParameters::blinded(blinded_hints.clone())
.with_bolt12_features(bolt12_features).unwrap();
assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
if let Some(bt) = &path.blinded_tail {
assert_eq!(bt.blinding_point,
- blinded_hints.iter().find(|(p, _)| p.htlc_maximum_msat == path.final_value_msat())
- .map(|(_, bp)| bp.blinding_point()).unwrap());
+ blinded_hints.iter().find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat())
+ .map(|bp| bp.blinding_point()).unwrap());
} else { panic!(); }
total_amount_paid_msat += path.final_value_msat();
}
let first_hops = vec![
get_channel_details(Some(1), nodes[1], InitFeatures::from_le_bytes(vec![0b11]), 10_000_000)];
- let blinded_path = dummy_blinded_path(nodes[1]);
let blinded_payinfo = BlindedPayInfo {
fee_base_msat: 1000,
fee_proportional_millionths: 0,
cltv_expiry_delta: 0,
features: BlindedHopFeatures::empty(),
};
- let blinded_hints = vec![(blinded_payinfo.clone(), blinded_path)];
+ let blinded_path = dummy_blinded_path(nodes[1], blinded_payinfo.clone());
+ let blinded_hints = vec![blinded_path];
let payment_params = PaymentParameters::blinded(blinded_hints.clone());
get_channel_details(Some(1), nodes[1], channelmanager::provided_init_features(&config),
18446744073709551615)];
- let blinded_path = dummy_blinded_path(nodes[1]);
let blinded_payinfo = BlindedPayInfo {
fee_base_msat: 5046_2720,
fee_proportional_millionths: 0,
cltv_expiry_delta: 0,
features: BlindedHopFeatures::empty(),
};
- let mut blinded_hints = vec![
- (blinded_payinfo.clone(), blinded_path.clone()),
- (blinded_payinfo.clone(), blinded_path.clone()),
- ];
- blinded_hints[1].0.fee_base_msat = 419_4304;
- blinded_hints[1].0.fee_proportional_millionths = 257;
- blinded_hints[1].0.htlc_minimum_msat = 280_8908_6115_8400;
- blinded_hints[1].0.htlc_maximum_msat = 2_8089_0861_1584_0000;
- blinded_hints[1].0.cltv_expiry_delta = 0;
+ let blinded_path = dummy_blinded_path(nodes[1], blinded_payinfo.clone());
+ let mut blinded_hints = vec![blinded_path.clone(), blinded_path.clone()];
+ blinded_hints[1].payinfo.fee_base_msat = 419_4304;
+ blinded_hints[1].payinfo.fee_proportional_millionths = 257;
+ blinded_hints[1].payinfo.htlc_minimum_msat = 280_8908_6115_8400;
+ blinded_hints[1].payinfo.htlc_maximum_msat = 2_8089_0861_1584_0000;
+ blinded_hints[1].payinfo.cltv_expiry_delta = 0;
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
let payment_params = PaymentParameters::blinded(blinded_hints.clone())
// Values are taken from the fuzz input that uncovered this panic.
let amt_msat = 21_7020_5185_1423_0019;
- let blinded_path = dummy_blinded_path(our_id);
let blinded_payinfo = BlindedPayInfo {
fee_base_msat: 5052_9027,
fee_proportional_millionths: 0,
cltv_expiry_delta: 0,
features: BlindedHopFeatures::empty(),
};
- let mut blinded_hints = vec![
- (blinded_payinfo.clone(), blinded_path.clone()),
- (blinded_payinfo.clone(), blinded_path.clone()),
- ];
- blinded_hints[1].1 = dummy_blinded_path(nodes[6]);
+ let blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
+ let mut blinded_hints = vec![blinded_path.clone(), blinded_path.clone()];
+ blinded_hints[1] = dummy_blinded_path(nodes[6], blinded_payinfo);
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
let payment_params = PaymentParameters::blinded(blinded_hints.clone())
// Values are taken from the fuzz input that uncovered this panic.
let amt_msat = 21_7020_5185_1423_0019;
- let blinded_path = dummy_blinded_path(our_id);
let blinded_payinfo = BlindedPayInfo {
fee_base_msat: 10_4425_1395,
fee_proportional_millionths: 0,
cltv_expiry_delta: 0,
features: BlindedHopFeatures::empty(),
};
+ let blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
let mut blinded_hints = vec![
- (blinded_payinfo.clone(), blinded_path.clone()),
- (blinded_payinfo.clone(), blinded_path.clone()),
- (blinded_payinfo.clone(), blinded_path.clone()),
+ blinded_path.clone(), blinded_path.clone(), blinded_path.clone(),
];
- blinded_hints[1].0.fee_base_msat = 5052_9027;
- blinded_hints[1].0.htlc_minimum_msat = 21_7020_5185_1423_0019;
- blinded_hints[1].0.htlc_maximum_msat = 1844_6744_0737_0955_1615;
+ blinded_hints[1].payinfo.fee_base_msat = 5052_9027;
+ blinded_hints[1].payinfo.htlc_minimum_msat = 21_7020_5185_1423_0019;
+ blinded_hints[1].payinfo.htlc_maximum_msat = 1844_6744_0737_0955_1615;
- blinded_hints[2].1 = dummy_blinded_path(nodes[6]);
+ blinded_hints[2] = dummy_blinded_path(nodes[6], blinded_payinfo);
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
let payment_params = PaymentParameters::blinded(blinded_hints.clone())
let base_fee = 1_6778_3453;
let htlc_min = 2_5165_8240;
let payment_params = if blinded_payee {
- let blinded_path = dummy_blinded_path(nodes[0]);
let blinded_payinfo = BlindedPayInfo {
fee_base_msat: base_fee,
fee_proportional_millionths: 0,
cltv_expiry_delta: 0,
features: BlindedHopFeatures::empty(),
};
+ let blinded_path = dummy_blinded_path(nodes[0], blinded_payinfo);
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
- PaymentParameters::blinded(vec![(blinded_payinfo, blinded_path)])
+ PaymentParameters::blinded(vec![blinded_path])
.with_bolt12_features(bolt12_features.clone()).unwrap()
} else {
let route_hint = RouteHint(vec![RouteHintHop {
let base_fees = [0, 425_9840, 0, 0];
let htlc_mins = [1_4392, 19_7401, 1027, 6_5535];
let payment_params = if blinded_payee {
- let blinded_path = dummy_blinded_path(nodes[0]);
let mut blinded_hints = Vec::new();
for (base_fee, htlc_min) in base_fees.iter().zip(htlc_mins.iter()) {
- blinded_hints.push((BlindedPayInfo {
+ let blinded_payinfo = BlindedPayInfo {
fee_base_msat: *base_fee,
fee_proportional_millionths: 0,
htlc_minimum_msat: *htlc_min,
htlc_maximum_msat: htlc_min * 100,
cltv_expiry_delta: 10,
features: BlindedHopFeatures::empty(),
- }, blinded_path.clone()));
+ };
+ blinded_hints.push(dummy_blinded_path(nodes[0], blinded_payinfo));
}
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
PaymentParameters::blinded(blinded_hints.clone())
let htlc_min = 2_5165_8240;
let blinded_hints = vec![
- (BlindedPayInfo {
+ dummy_blinded_path(nodes[0], BlindedPayInfo {
fee_base_msat: 1_6778_3453,
fee_proportional_millionths: 0,
htlc_minimum_msat: htlc_min,
htlc_maximum_msat: htlc_min * 100,
cltv_expiry_delta: 10,
features: BlindedHopFeatures::empty(),
- }, dummy_blinded_path(nodes[0]))
+ })
];
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
let payment_params = PaymentParameters::blinded(blinded_hints.clone())
let htlc_mins = [49_0000, 1125_0000];
let payment_params = {
- let blinded_path = dummy_blinded_path(nodes[0]);
let mut blinded_hints = Vec::new();
for htlc_min in htlc_mins.iter() {
- blinded_hints.push((BlindedPayInfo {
+ let payinfo = BlindedPayInfo {
fee_base_msat: 0,
fee_proportional_millionths: 0,
htlc_minimum_msat: *htlc_min,
htlc_maximum_msat: *htlc_min * 100,
cltv_expiry_delta: 10,
features: BlindedHopFeatures::empty(),
- }, blinded_path.clone()));
+ };
+ blinded_hints.push(dummy_blinded_path(nodes[0], payinfo));
}
let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
PaymentParameters::blinded(blinded_hints.clone())
}
}
+#[derive(Debug)]
+pub(crate) struct IterableOwned<I: Iterator<Item = T> + Clone, T>(pub I);
+
+impl<I: Iterator<Item = T> + Clone, T: Writeable> Writeable for IterableOwned<I, T> {
+ #[inline]
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ for ref v in self.0.clone() {
+ v.write(writer)?;
+ }
+ Ok(())
+ }
+}
+
macro_rules! impl_for_map {
($ty: ident, $keybound: ident, $constr: expr) => {
impl<K, V> Writeable for $ty<K, V>
use crate::ln::{msgs, wire};
use crate::ln::msgs::LightningError;
use crate::ln::script::ShutdownScript;
-use crate::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
+use crate::offers::invoice::UnsignedBolt12Invoice;
use crate::offers::invoice_request::UnsignedInvoiceRequest;
use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath};
use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees};
>,
pub network_graph: Arc<NetworkGraph<&'a TestLogger>>,
pub next_routes: Mutex<VecDeque<(RouteParameters, Option<Result<Route, LightningError>>)>>,
- pub next_blinded_payment_paths: Mutex<Vec<(BlindedPayInfo, BlindedPaymentPath)>>,
+ pub next_blinded_payment_paths: Mutex<Vec<BlindedPaymentPath>>,
pub scorer: &'a RwLock<TestScorer>,
}
expected_routes.push_back((query, None));
}
- pub fn expect_blinded_payment_paths(&self, mut paths: Vec<(BlindedPayInfo, BlindedPaymentPath)>) {
+ pub fn expect_blinded_payment_paths(&self, mut paths: Vec<BlindedPaymentPath>) {
let mut expected_paths = self.next_blinded_payment_paths.lock().unwrap();
core::mem::swap(&mut *expected_paths, &mut paths);
}
>(
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
amount_msats: u64, secp_ctx: &Secp256k1<T>,
- ) -> Result<Vec<(BlindedPayInfo, BlindedPaymentPath)>, ()> {
+ ) -> Result<Vec<BlindedPaymentPath>, ()> {
let mut expected_paths = self.next_blinded_payment_paths.lock().unwrap();
if expected_paths.is_empty() {
self.router.create_blinded_payment_paths(