]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Support next_blinding_override in blinded payment paths.
authorValentine Wallace <vwallace@protonmail.com>
Mon, 22 Jul 2024 19:22:54 +0000 (15:22 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Mon, 19 Aug 2024 16:47:40 +0000 (12:47 -0400)
This allow us to forward blinded payments where the blinded path that we are
forwarding within was concatenated to another blinded path that starts at the
next hop.

Also allows constructing blinded paths using this override.

fuzz/src/invoice_request_deser.rs
fuzz/src/refund_deser.rs
lightning/src/blinded_path/payment.rs
lightning/src/ln/blinded_payment_tests.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_payment.rs
lightning/src/routing/router.rs

index a5db1c4be9928ee240d0d5505c41dc81b7f3fd7d..3abb0974e43660cb2a482c3bc955550cfd09ae13 100644 (file)
@@ -113,6 +113,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
                                htlc_minimum_msat: 100,
                        },
                        features: BlindedHopFeatures::empty(),
+                       next_blinding_override: None,
                },
                node_id: pubkey(43),
                htlc_maximum_msat: 1_000_000_000_000,
index 58dc68eed5cb875940f3c18ee777f75458aebe19..17f255081c46649fcf70376e8a808102d195ca57 100644 (file)
@@ -91,6 +91,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
                                htlc_minimum_msat: 100,
                        },
                        features: BlindedHopFeatures::empty(),
+                       next_blinding_override: None,
                },
                node_id: pubkey(43),
                htlc_maximum_msat: 1_000_000_000_000,
index 765e0b91f05590651c9e32d3f324047c6d689f0b..ca937c57d722f43c38a554509059b0f4771ad314 100644 (file)
@@ -201,6 +201,9 @@ pub struct ForwardTlvs {
        ///
        /// [`BlindedHop::encrypted_payload`]: crate::blinded_path::BlindedHop::encrypted_payload
        pub features: BlindedHopFeatures,
+       /// Set if this [`BlindedPaymentPath`] is concatenated to another, to indicate the
+       /// [`BlindedPaymentPath::blinding_point`] of the appended blinded path.
+       pub next_blinding_override: Option<PublicKey>,
 }
 
 /// Data to construct a [`BlindedHop`] for receiving a payment. This payload is custom to LDK and
@@ -379,6 +382,7 @@ impl Readable for BlindedPaymentTlvs {
                _init_and_read_tlv_stream!(r, {
                        (1, _padding, option),
                        (2, scid, option),
+                       (8, next_blinding_override, option),
                        (10, payment_relay, option),
                        (12, payment_constraints, required),
                        (14, features, option),
@@ -395,6 +399,7 @@ impl Readable for BlindedPaymentTlvs {
                                short_channel_id,
                                payment_relay: payment_relay.ok_or(DecodeError::InvalidValue)?,
                                payment_constraints: payment_constraints.0.unwrap(),
+                               next_blinding_override,
                                features: features.unwrap_or_else(BlindedHopFeatures::empty),
                        }))
                } else {
@@ -602,6 +607,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 100,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: u64::max_value(),
@@ -618,6 +624,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 1_000,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: u64::max_value(),
@@ -675,6 +682,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 1,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: u64::max_value()
@@ -691,6 +699,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 2_000,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: u64::max_value()
@@ -726,6 +735,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 5_000,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: u64::max_value()
@@ -742,6 +752,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 2_000,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: u64::max_value()
@@ -781,6 +792,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 1,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: 5_000,
@@ -797,6 +809,7 @@ mod tests {
                                        max_cltv_expiry: 0,
                                        htlc_minimum_msat: 1,
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: 10_000
index b13b1e04d64f7ab1addd03489ad6841a534d8f9c..e959000d32bcc704fd1d0b47e9989e3ae6d3116b 100644 (file)
@@ -49,6 +49,7 @@ fn blinded_payment_path(
                                        htlc_minimum_msat: intro_node_min_htlc_opt.take()
                                                .unwrap_or_else(|| channel_upds[idx - 1].htlc_minimum_msat),
                                },
+                               next_blinding_override: None,
                                features: BlindedHopFeatures::empty(),
                        },
                        htlc_maximum_msat: intro_node_max_htlc_opt.take()
index 641810f2f4ed010e5bfb10cd1d0844c0eda6fdfd..e08b45558c608a06f8793742d9a8d657d3b09f94 100644 (file)
@@ -226,6 +226,10 @@ pub struct BlindedForward {
        /// If needed, this determines how this HTLC should be failed backwards, based on whether we are
        /// the introduction node.
        pub failure: BlindedFailure,
+       /// Overrides the next hop's [`msgs::UpdateAddHTLC::blinding_point`]. Set if this HTLC is being
+       /// forwarded within a [`BlindedPaymentPath`] that was concatenated to another blinded path that
+       /// starts at the next hop.
+       pub next_blinding_override: Option<PublicKey>,
 }
 
 impl PendingHTLCRouting {
@@ -5313,12 +5317,14 @@ where
                                                                        blinded_failure: blinded.map(|b| b.failure),
                                                                });
                                                                let next_blinding_point = blinded.and_then(|b| {
-                                                                       let encrypted_tlvs_ss = self.node_signer.ecdh(
-                                                                               Recipient::Node, &b.inbound_blinding_point, None
-                                                                       ).unwrap().secret_bytes();
-                                                                       onion_utils::next_hop_pubkey(
-                                                                               &self.secp_ctx, b.inbound_blinding_point, &encrypted_tlvs_ss
-                                                                       ).ok()
+                                                                       b.next_blinding_override.or_else(|| {
+                                                                               let encrypted_tlvs_ss = self.node_signer.ecdh(
+                                                                                       Recipient::Node, &b.inbound_blinding_point, None
+                                                                               ).unwrap().secret_bytes();
+                                                                               onion_utils::next_hop_pubkey(
+                                                                                       &self.secp_ctx, b.inbound_blinding_point, &encrypted_tlvs_ss
+                                                                               ).ok()
+                                                                       })
                                                                });
 
                                                                // Forward the HTLC over the most appropriate channel with the corresponding peer,
@@ -11034,6 +11040,7 @@ impl_writeable_tlv_based!(PhantomRouteHints, {
 impl_writeable_tlv_based!(BlindedForward, {
        (0, inbound_blinding_point, required),
        (1, failure, (default_value, BlindedFailure::FromIntroductionNode)),
+       (3, next_blinding_override, option),
 });
 
 impl_writeable_tlv_based_enum!(PendingHTLCRouting,
index 85f1ae0aa48614e70ca5b2abd70a5486fccc37dc..83ce4f91409a31cb750e599ff0c2913bfb2e52e9 100644 (file)
@@ -1764,6 +1764,7 @@ mod fuzzy_internal_msgs {
                        payment_constraints: PaymentConstraints,
                        features: BlindedHopFeatures,
                        intro_node_blinding_point: Option<PublicKey>,
+                       next_blinding_override: Option<PublicKey>,
                },
                BlindedReceive {
                        sender_intended_htlc_amt_msat: u64,
@@ -2808,7 +2809,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                        let mut reader = FixedLengthReader::new(&mut s, enc_tlvs.len() as u64);
                        match ChaChaPolyReadAdapter::read(&mut reader, rho)? {
                                ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Forward(ForwardTlvs {
-                                       short_channel_id, payment_relay, payment_constraints, features
+                                       short_channel_id, payment_relay, payment_constraints, features, next_blinding_override
                                })} => {
                                        if amt.is_some() || cltv_value.is_some() || total_msat.is_some() ||
                                                keysend_preimage.is_some()
@@ -2821,6 +2822,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                                                payment_constraints,
                                                features,
                                                intro_node_blinding_point,
+                                               next_blinding_override,
                                        })
                                },
                                ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(ReceiveTlvs {
index f62ca5d84e637bc4d95bb48d679f00151a756d0e..1163a5e638fd3f45996171cc51bef3b195b6a2b4 100644 (file)
@@ -75,12 +75,14 @@ pub(super) fn create_fwd_pending_htlc_info(
        };
 
        let (
-               short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point
+               short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
+               next_blinding_override
        ) = match hop_data {
                msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } =>
-                       (short_channel_id, amt_to_forward, outgoing_cltv_value, None),
+                       (short_channel_id, amt_to_forward, outgoing_cltv_value, None, None),
                msgs::InboundOnionPayload::BlindedForward {
                        short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features,
+                       next_blinding_override,
                } => {
                        let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward(
                                msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features
@@ -93,7 +95,8 @@ pub(super) fn create_fwd_pending_htlc_info(
                                        err_data: vec![0; 32],
                                }
                        })?;
-                       (short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point)
+                       (short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
+                        next_blinding_override)
                },
                msgs::InboundOnionPayload::Receive { .. } | msgs::InboundOnionPayload::BlindedReceive { .. } =>
                        return Err(InboundHTLCErr {
@@ -110,6 +113,7 @@ pub(super) fn create_fwd_pending_htlc_info(
                        blinded: intro_node_blinding_point.or(msg.blinding_point)
                                .map(|bp| BlindedForward {
                                        inbound_blinding_point: bp,
+                                       next_blinding_override,
                                        failure: intro_node_blinding_point
                                                .map(|_| BlindedFailure::FromIntroductionNode)
                                                .unwrap_or(BlindedFailure::FromBlindedNode),
index 2d7450b91c53be82d3b26037692ad9c25f54dff6..43c4b7343e722c6cdca7f716ead9427664341a58 100644 (file)
@@ -151,6 +151,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref, SP: Size
                                                short_channel_id,
                                                payment_relay,
                                                payment_constraints,
+                                               next_blinding_override: None,
                                                features: BlindedHopFeatures::empty(),
                                        },
                                        node_id: details.counterparty.node_id,