]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Move BlindedPayInfo into BlindedPaymentPath.
authorValentine Wallace <vwallace@protonmail.com>
Mon, 19 Aug 2024 15:25:05 +0000 (11:25 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Mon, 19 Aug 2024 20:28:30 +0000 (16:28 -0400)
Also removes the implementation of Writeable for BlindedPaymentPath, to ensure
callsites are explicit about what they're writing.

20 files changed:
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/router.rs
lightning/src/blinded_path/mod.rs
lightning/src/blinded_path/payment.rs
lightning/src/ln/blinded_payment_tests.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/max_payment_path_len_tests.rs
lightning/src/ln/offers_tests.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/outbound_payment.rs
lightning/src/offers/invoice.rs
lightning/src/offers/invoice_macros.rs
lightning/src/offers/invoice_request.rs
lightning/src/offers/refund.rs
lightning/src/offers/static_invoice.rs
lightning/src/offers/test_utils.rs
lightning/src/routing/router.rs
lightning/src/util/ser.rs
lightning/src/util/test_utils.rs

index a34df1d5a07554c7dbf2da1cb865138244c5d814..84cc4bf260f582e36f422092397550735ffc1de7 100644 (file)
@@ -56,7 +56,7 @@ use lightning::ln::msgs::{
 };
 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};
@@ -126,7 +126,7 @@ impl Router for FuzzRouter {
        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!()
        }
 }
index 57aa0632bf44dd0eaca7ecce0541c90bd363bc3c..90449248e32eb69c636ecdb9946712a4869ddc93 100644 (file)
@@ -49,7 +49,7 @@ use lightning::ln::peer_handler::{
 };
 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};
@@ -163,7 +163,7 @@ impl Router for FuzzRouter {
        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!()
        }
 }
index 5aa029088de0a161167afa6ace88bc5dab016207..c315f58e250249b5141df211e4532bd3c4e91597 100644 (file)
@@ -381,7 +381,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                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];
@@ -401,9 +401,11 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                                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();
index 70ee11617f6f50e1036e827b5775cc7bbc93a5c4..168bc7174d6b7a2ce3df070a126c8a4f43284fa0 100644 (file)
@@ -26,7 +26,7 @@ use crate::prelude::*;
 /// 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.
index 70f2220dcdc6d728bb83e5228e8743db0d2e6375..4c7066b9ad58c93b5a19f86b9afb32fa5cadc621 100644 (file)
@@ -37,18 +37,10 @@ use crate::prelude::*;
 /// 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 {
@@ -56,7 +48,7 @@ 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();
@@ -77,7 +69,7 @@ impl BlindedPaymentPath {
                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)
                );
@@ -87,13 +79,16 @@ impl BlindedPaymentPath {
                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.,
@@ -101,24 +96,24 @@ impl BlindedPaymentPath {
        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
@@ -133,9 +128,9 @@ impl BlindedPaymentPath {
                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) {
@@ -147,31 +142,43 @@ impl BlindedPaymentPath {
                                        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()
        }
 }
 
index 12c0dc33a0060f64d1330af28c78e5e7b454b269..eecbb9c4b923c140032e7de5c701794c5546a769 100644 (file)
@@ -25,7 +25,7 @@ use crate::ln::onion_payment;
 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};
@@ -39,7 +39,7 @@ fn blinded_payment_path(
        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);
@@ -839,11 +839,12 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
                                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 {
@@ -1121,7 +1122,7 @@ fn min_htlc() {
                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);
@@ -1133,7 +1134,7 @@ fn min_htlc() {
                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();
index f49d8b639341cbe7b7da69f9d1c9c2f73ce0ea79..167ab0ac8fd8a16475abc99890939df39e372e6f 100644 (file)
@@ -62,7 +62,7 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
 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;
@@ -9373,7 +9373,7 @@ where
        /// [`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();
index 8e5edd4e91b19252e014f53ee74d4fc6ebf6042f..a22d7d1643c8b275688a8b4f7a726aab6c32073c 100644 (file)
@@ -182,8 +182,8 @@ fn one_hop_blinded_path_with_custom_tlv() {
                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();
@@ -354,15 +354,7 @@ fn bolt12_invoice_too_large_blinded_paths() {
        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![
@@ -374,9 +366,17 @@ fn bolt12_invoice_too_large_blinded_paths() {
                                        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]);
index 8edeefcf871babbf3209c6ed79e32951515c4e0a..b1c09fd54f8c8f96ff2f9d4ea310a92e29fb57a2 100644 (file)
@@ -584,7 +584,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
        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));
        }
 
@@ -665,7 +665,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
        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));
        }
 
@@ -730,7 +730,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
        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));
        }
 
@@ -785,7 +785,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
        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));
        }
 
@@ -1109,7 +1109,7 @@ fn pays_bolt12_invoice_asynchronously() {
        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));
        }
 
@@ -1193,7 +1193,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() {
        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));
        }
 
@@ -1243,7 +1243,7 @@ fn creates_refund_with_blinded_path_using_unannounced_introduction_node() {
        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));
        }
 }
index a3372dda8e0623f3202698482962d311bffab213..5ad68407631dd982aeb233a6cb068e73fbbb218a 100644 (file)
@@ -337,8 +337,7 @@ pub(crate) fn set_max_path_length(
                .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(),
index aff2367779b7d17920c41d01f0f0d56c8f382def..1fda943373d7f2ae49dd03e5c2e6938dae2e5176 100644 (file)
@@ -833,7 +833,7 @@ impl OutboundPayments {
 
                // 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) => {
index 3c2c2cb99850832898dccb4cea18918b268c3ff2..693e8e00f54174121a69b768d5cac1063ed9774e 100644 (file)
@@ -32,7 +32,7 @@
 //! # 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> {
@@ -110,6 +110,7 @@ use bitcoin::address::Address;
 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;
@@ -212,7 +213,7 @@ impl SigningPubkeyStrategy for DerivedSigningPubkey {}
 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)?;
@@ -228,7 +229,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $s
 
        #[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();
@@ -270,7 +271,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $s
 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)?;
@@ -287,7 +288,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $se
 
        #[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();
@@ -356,8 +357,8 @@ macro_rules! invoice_builder_methods { (
 
        #[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,
@@ -603,7 +604,7 @@ enum InvoiceContents {
 /// 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,
@@ -988,7 +989,7 @@ impl InvoiceContents {
                }
        }
 
-       fn payment_paths(&self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
+       fn payment_paths(&self) -> &[BlindedPaymentPath] {
                &self.fields().payment_paths[..]
        }
 
@@ -1124,8 +1125,8 @@ impl InvoiceFields {
                };
 
                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),
@@ -1192,7 +1193,7 @@ impl TryFrom<Vec<u8>> for Bolt12Invoice {
 }
 
 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)),
@@ -1206,13 +1207,13 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
 });
 
 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`].
@@ -1387,8 +1388,8 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
 }
 
 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),
@@ -1397,7 +1398,12 @@ pub(super) fn construct_payment_paths(
                        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<_>>()
+                       )
                },
        }
 }
@@ -1605,8 +1611,8 @@ mod tests {
                                        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),
@@ -1698,8 +1704,8 @@ mod tests {
                                        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),
@@ -2110,7 +2116,7 @@ mod tests {
 
                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"),
@@ -2120,7 +2126,7 @@ mod tests {
                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"),
index a06c0663a0fb7d2899626fc61d851a0f04b1203b..3037ccfa803ed33fb5c7668248b89d1cdc5955ee 100644 (file)
@@ -107,7 +107,7 @@ macro_rules! invoice_accessors_common { ($self: ident, $contents: expr, $invoice
        ///
        /// 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()
        }
 
index a021a1a3a97675a646a5d19b53f71c4a90d17203..fa3d9161b8221567a694c4792632f4e3fb8df63b 100644 (file)
@@ -69,7 +69,6 @@ use crate::ln::channelmanager::PaymentId;
 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};
@@ -708,7 +707,7 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
        /// [`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)
@@ -743,7 +742,7 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
        /// [`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() {
@@ -761,7 +760,7 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
        #[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());
@@ -881,7 +880,7 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
        /// [`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)
@@ -898,7 +897,7 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
        ///
        /// [`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() {
index 3dba3637da4059848905ed8244f9a2a1a9590d8a..c07055c5c1010ff122be02c8683d282bce124041 100644 (file)
@@ -98,7 +98,6 @@ use crate::ln::channelmanager::PaymentId;
 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};
@@ -533,7 +532,7 @@ macro_rules! respond_with_explicit_signing_pubkey_methods { ($self: ident, $buil
        /// [`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()
@@ -566,7 +565,7 @@ macro_rules! respond_with_explicit_signing_pubkey_methods { ($self: ident, $buil
        ///
        /// [`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() {
@@ -588,7 +587,7 @@ macro_rules! respond_with_derived_signing_pubkey_methods { ($self: ident, $build
        /// [`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
@@ -612,7 +611,7 @@ macro_rules! respond_with_derived_signing_pubkey_methods { ($self: ident, $build
        ///
        /// [`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
index 63b32ccf38909ad05e2d9e7471c2334457690b64..33706f928d8993aa88760c1b0f43ad99bb5d8b50 100644 (file)
@@ -16,8 +16,8 @@ use crate::ln::features::{Bolt12InvoiceFeatures, OfferFeatures};
 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::{
@@ -71,7 +71,7 @@ pub struct StaticInvoice {
 #[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>>,
@@ -97,7 +97,7 @@ impl<'a> StaticInvoiceBuilder<'a> {
        /// 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> {
@@ -326,7 +326,7 @@ impl InvoiceContents {
        }
 
        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 {
@@ -351,9 +351,9 @@ impl InvoiceContents {
                };
 
                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(),
@@ -407,7 +407,7 @@ impl InvoiceContents {
                self.offer.supported_quantity()
        }
 
-       fn payment_paths(&self) -> &[(BlindedPayInfo, BlindedPaymentPath)] {
+       fn payment_paths(&self) -> &[BlindedPaymentPath] {
                &self.payment_paths[..]
        }
 
@@ -720,8 +720,10 @@ mod tests {
                                        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,
index 588c167bf5f75ee32e45f21fb936fa691543c8c6..d815338d7579f0280897e8fdde3aa78822f8e5c4 100644 (file)
@@ -67,44 +67,39 @@ pub(super) fn privkey(byte: u8) -> SecretKey {
        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 {
index 439838832be0106011ab2e47376cc80a6c360425..495ff30a92006e14bd7258fc76401db3b1fdc77a 100644 (file)
@@ -20,7 +20,7 @@ use crate::ln::channelmanager::{PaymentId, MIN_FINAL_CLTV_EXPIRY_DELTA, Recipien
 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};
@@ -94,7 +94,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref, SP: Size
        > (
                &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;
 
@@ -245,7 +245,7 @@ pub trait Router: MessageRouter {
        > (
                &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.
@@ -759,10 +759,13 @@ pub struct PaymentParameters {
 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),
@@ -773,7 +776,7 @@ impl Writeable for PaymentParameters {
                        (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),
@@ -802,7 +805,10 @@ impl ReadableArgs<u32> for PaymentParameters {
                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 {
@@ -872,7 +878,7 @@ impl PaymentParameters {
        }
 
        /// 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,
@@ -960,7 +966,7 @@ impl PaymentParameters {
 
        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()
                        {
@@ -981,7 +987,7 @@ pub enum Payee {
        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
@@ -1037,14 +1043,14 @@ impl Payee {
                        _ => 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 []
@@ -1246,7 +1252,7 @@ pub struct BlindedPathCandidate<'a> {
        /// 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
@@ -1275,7 +1281,9 @@ pub struct OneHopBlindedPathCandidate<'a> {
        /// 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
@@ -1325,6 +1333,8 @@ pub enum CandidateRouteHop<'a> {
        ///
        /// 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>),
 }
 
@@ -1393,7 +1403,7 @@ impl<'a> CandidateRouteHop<'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,
                }
        }
@@ -1405,7 +1415,7 @@ impl<'a> CandidateRouteHop<'a> {
                        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,
                }
        }
@@ -1443,8 +1453,8 @@ impl<'a> CandidateRouteHop<'a> {
                        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(_) =>
@@ -1467,7 +1477,7 @@ impl<'a> CandidateRouteHop<'a> {
                        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,
                }
        }
@@ -1486,7 +1496,7 @@ impl<'a> CandidateRouteHop<'a> {
        fn blinded_path(&self) -> Option<&'a BlindedPaymentPath> {
                match self {
                        CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => {
-                               Some(&hint.1)
+                               Some(&hint)
                        },
                        _ => None,
                }
@@ -1639,7 +1649,7 @@ fn calculate_blinded_path_intro_points<'a, L: Deref>(
 ) -> 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
@@ -1678,7 +1688,7 @@ where L::Target: Logger {
                        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});
                                }
@@ -1691,7 +1701,7 @@ where L::Target: Logger {
                                } 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});
@@ -1974,7 +1984,7 @@ impl<'a> fmt::Display for LoggedCandidateHop<'a> {
                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 {
@@ -1988,7 +1998,7 @@ impl<'a> fmt::Display for LoggedCandidateHop<'a> {
                                        }
                                }
                                " and blinding point ".fmt(f)?;
-                               hint.1.blinding_point().fmt(f)
+                               hint.blinding_point().fmt(f)
                        },
                        CandidateRouteHop::FirstHop(_) => {
                                "first hop with SCID ".fmt(f)?;
@@ -2821,7 +2831,7 @@ where L::Target: Logger {
                        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 }
                                )
@@ -3620,22 +3630,24 @@ mod tests {
                }
        }
 
-       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
                )
        }
 
@@ -5469,7 +5481,6 @@ mod tests {
 
                // 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,
@@ -5478,29 +5489,26 @@ mod tests {
                        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);
        }
@@ -5682,8 +5690,8 @@ mod tests {
                                                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()
                                                );
@@ -7656,7 +7664,6 @@ mod tests {
                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,
@@ -7665,11 +7672,11 @@ mod tests {
                        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(),
@@ -7834,7 +7841,6 @@ mod tests {
                                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,
@@ -7843,8 +7849,9 @@ mod tests {
                        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),
@@ -7891,11 +7898,10 @@ mod tests {
                        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)
@@ -7906,8 +7912,8 @@ mod tests {
                        _ => 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)
@@ -7918,9 +7924,9 @@ mod tests {
                        _ => 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)
@@ -7945,7 +7951,6 @@ mod tests {
                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,
@@ -7954,20 +7959,19 @@ mod tests {
                        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();
 
@@ -7981,8 +7985,8 @@ mod tests {
                        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();
                }
@@ -8040,7 +8044,6 @@ mod tests {
                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,
@@ -8049,7 +8052,8 @@ mod tests {
                        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());
 
@@ -8101,7 +8105,6 @@ mod tests {
                        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,
@@ -8110,15 +8113,13 @@ mod tests {
                        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())
@@ -8149,7 +8150,6 @@ mod tests {
                // 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,
@@ -8158,11 +8158,9 @@ mod tests {
                        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())
@@ -8193,7 +8191,6 @@ mod tests {
                // 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,
@@ -8202,16 +8199,15 @@ mod tests {
                        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())
@@ -8256,7 +8252,6 @@ mod tests {
                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,
@@ -8265,8 +8260,9 @@ mod tests {
                                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 {
@@ -8328,17 +8324,17 @@ mod tests {
                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())
@@ -8415,14 +8411,14 @@ mod tests {
 
                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())
@@ -8464,17 +8460,17 @@ mod tests {
 
                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())
index de54a14f2f778db575a304a222f924c3601f6c55..1c48463b89f3600340e29b0f026253a4094037cb 100644 (file)
@@ -805,6 +805,19 @@ impl<'a, I: Iterator<Item = &'a T> + Clone, T: 'a + PartialEq> PartialEq for Ite
        }
 }
 
+#[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>
index 3f2226d741d3a0180143ffd43de257bfadbbec70..45e8c081a7bbcdc6ac32887bc34ab44a8c896202 100644 (file)
@@ -33,7 +33,7 @@ use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 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};
@@ -119,7 +119,7 @@ pub struct TestRouter<'a> {
        >,
        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>,
 }
 
@@ -148,7 +148,7 @@ impl<'a> TestRouter<'a> {
                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);
        }
@@ -246,7 +246,7 @@ impl<'a> Router for TestRouter<'a> {
        >(
                &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(