lightning/blinded_path/
payment.rs

1// This file is Copyright its original authors, visible in version control
2// history.
3//
4// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7// You may not use this file except in accordance with one or both of these
8// licenses.
9
10//! Data structures and methods for constructing [`BlindedPaymentPath`]s to send a payment over.
11
12use bitcoin::hashes::hmac::Hmac;
13use bitcoin::hashes::sha256::Hash as Sha256;
14use bitcoin::secp256k1::ecdh::SharedSecret;
15use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
16
17use crate::blinded_path::utils::{self, BlindedPathWithPadding};
18use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NodeIdLookUp};
19use crate::crypto::streams::ChaChaPolyReadAdapter;
20use crate::io;
21use crate::io::Cursor;
22use crate::ln::channel_state::CounterpartyForwardingInfo;
23use crate::ln::channelmanager::Verification;
24use crate::ln::inbound_payment::ExpandedKey;
25use crate::ln::msgs::DecodeError;
26use crate::ln::onion_utils;
27use crate::offers::invoice_request::InvoiceRequestFields;
28use crate::offers::nonce::Nonce;
29use crate::offers::offer::OfferId;
30use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph};
31use crate::sign::{EntropySource, NodeSigner, Recipient};
32use crate::types::features::BlindedHopFeatures;
33use crate::types::payment::PaymentSecret;
34use crate::types::routing::RoutingFees;
35use crate::util::ser::{
36	FixedLengthReader, HighZeroBytesDroppedBigSize, LengthReadableArgs, Readable, WithoutLength,
37	Writeable, Writer,
38};
39
40use core::mem;
41use core::ops::Deref;
42
43#[allow(unused_imports)]
44use crate::prelude::*;
45
46/// Information needed to route a payment across a [`BlindedPaymentPath`].
47#[derive(Clone, Debug, Hash, Eq, PartialEq)]
48pub struct BlindedPayInfo {
49	/// Base fee charged (in millisatoshi) for the entire blinded path.
50	pub fee_base_msat: u32,
51
52	/// Liquidity fee charged (in millionths of the amount transferred) for the entire blinded path
53	/// (i.e., 10,000 is 1%).
54	pub fee_proportional_millionths: u32,
55
56	/// Number of blocks subtracted from an incoming HTLC's `cltv_expiry` for the entire blinded
57	/// path.
58	pub cltv_expiry_delta: u16,
59
60	/// The minimum HTLC value (in millisatoshi) that is acceptable to all channel peers on the
61	/// blinded path from the introduction node to the recipient, accounting for any fees, i.e., as
62	/// seen by the recipient.
63	pub htlc_minimum_msat: u64,
64
65	/// The maximum HTLC value (in millisatoshi) that is acceptable to all channel peers on the
66	/// blinded path from the introduction node to the recipient, accounting for any fees, i.e., as
67	/// seen by the recipient.
68	pub htlc_maximum_msat: u64,
69
70	/// Features set in `encrypted_data_tlv` for the `encrypted_recipient_data` TLV record in an
71	/// onion payload.
72	pub features: BlindedHopFeatures,
73}
74
75impl_writeable!(BlindedPayInfo, {
76	fee_base_msat,
77	fee_proportional_millionths,
78	cltv_expiry_delta,
79	htlc_minimum_msat,
80	htlc_maximum_msat,
81	features
82});
83
84/// A blinded path to be used for sending or receiving a payment, hiding the identity of the
85/// recipient.
86#[derive(Clone, Debug, Hash, PartialEq, Eq)]
87pub struct BlindedPaymentPath {
88	pub(super) inner_path: BlindedPath,
89	/// The [`BlindedPayInfo`] used to pay this blinded path.
90	pub payinfo: BlindedPayInfo,
91}
92
93impl BlindedPaymentPath {
94	/// Create a one-hop blinded path for a payment.
95	pub fn one_hop<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
96		payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs, min_final_cltv_expiry_delta: u16,
97		entropy_source: ES, secp_ctx: &Secp256k1<T>,
98	) -> Result<Self, ()>
99	where
100		ES::Target: EntropySource,
101	{
102		// This value is not considered in pathfinding for 1-hop blinded paths, because it's intended to
103		// be in relation to a specific channel.
104		let htlc_maximum_msat = u64::max_value();
105		Self::new(
106			&[],
107			payee_node_id,
108			payee_tlvs,
109			htlc_maximum_msat,
110			min_final_cltv_expiry_delta,
111			entropy_source,
112			secp_ctx,
113		)
114	}
115
116	/// Create a blinded path for a payment, to be forwarded along `intermediate_nodes`.
117	///
118	/// Errors if:
119	/// * [`BlindedPayInfo`] calculation results in an integer overflow
120	/// * any unknown features are required in the provided [`ForwardTlvs`]
121	//  TODO: make all payloads the same size with padding + add dummy hops
122	pub fn new<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
123		intermediate_nodes: &[PaymentForwardNode], payee_node_id: PublicKey,
124		payee_tlvs: ReceiveTlvs, htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16,
125		entropy_source: ES, secp_ctx: &Secp256k1<T>,
126	) -> Result<Self, ()>
127	where
128		ES::Target: EntropySource,
129	{
130		let introduction_node = IntroductionNode::NodeId(
131			intermediate_nodes.first().map_or(payee_node_id, |n| n.node_id),
132		);
133		let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
134		let blinding_secret =
135			SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
136
137		let blinded_payinfo = compute_payinfo(
138			intermediate_nodes,
139			&payee_tlvs.tlvs,
140			htlc_maximum_msat,
141			min_final_cltv_expiry_delta,
142		)?;
143		Ok(Self {
144			inner_path: BlindedPath {
145				introduction_node,
146				blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
147				blinded_hops: blinded_hops(
148					secp_ctx,
149					intermediate_nodes,
150					payee_node_id,
151					payee_tlvs,
152					&blinding_secret,
153				),
154			},
155			payinfo: blinded_payinfo,
156		})
157	}
158
159	/// Returns the introduction [`NodeId`] of the blinded path, if it is publicly reachable (i.e.,
160	/// it is found in the network graph).
161	pub fn public_introduction_node_id<'a>(
162		&self, network_graph: &'a ReadOnlyNetworkGraph,
163	) -> Option<&'a NodeId> {
164		self.inner_path.public_introduction_node_id(network_graph)
165	}
166
167	/// The [`IntroductionNode`] of the blinded path.
168	pub fn introduction_node(&self) -> &IntroductionNode {
169		&self.inner_path.introduction_node
170	}
171
172	/// Used by the [`IntroductionNode`] to decrypt its [`encrypted_payload`] to forward the payment.
173	///
174	/// [`encrypted_payload`]: BlindedHop::encrypted_payload
175	pub fn blinding_point(&self) -> PublicKey {
176		self.inner_path.blinding_point
177	}
178
179	/// The [`BlindedHop`]s within the blinded path.
180	pub fn blinded_hops(&self) -> &[BlindedHop] {
181		&self.inner_path.blinded_hops
182	}
183
184	/// Advance the blinded onion payment path by one hop, making the second hop into the new
185	/// introduction node.
186	///
187	/// Will only modify `self` when returning `Ok`.
188	pub fn advance_path_by_one<NS: Deref, NL: Deref, T>(
189		&mut self, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>,
190	) -> Result<(), ()>
191	where
192		NS::Target: NodeSigner,
193		NL::Target: NodeIdLookUp,
194		T: secp256k1::Signing + secp256k1::Verification,
195	{
196		match self.decrypt_intro_payload::<NS>(node_signer) {
197			Ok((
198				BlindedPaymentTlvs::Forward(ForwardTlvs { short_channel_id, .. }),
199				control_tlvs_ss,
200			)) => {
201				let next_node_id = match node_id_lookup.next_node_id(short_channel_id) {
202					Some(node_id) => node_id,
203					None => return Err(()),
204				};
205				let mut new_blinding_point = onion_utils::next_hop_pubkey(
206					secp_ctx,
207					self.inner_path.blinding_point,
208					control_tlvs_ss.as_ref(),
209				)
210				.map_err(|_| ())?;
211				mem::swap(&mut self.inner_path.blinding_point, &mut new_blinding_point);
212				self.inner_path.introduction_node = IntroductionNode::NodeId(next_node_id);
213				self.inner_path.blinded_hops.remove(0);
214				Ok(())
215			},
216			_ => Err(()),
217		}
218	}
219
220	pub(crate) fn decrypt_intro_payload<NS: Deref>(
221		&self, node_signer: &NS,
222	) -> Result<(BlindedPaymentTlvs, SharedSecret), ()>
223	where
224		NS::Target: NodeSigner,
225	{
226		let control_tlvs_ss =
227			node_signer.ecdh(Recipient::Node, &self.inner_path.blinding_point, None)?;
228		let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
229		let encrypted_control_tlvs =
230			&self.inner_path.blinded_hops.get(0).ok_or(())?.encrypted_payload;
231		let mut s = Cursor::new(encrypted_control_tlvs);
232		let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64);
233		match ChaChaPolyReadAdapter::read(&mut reader, rho) {
234			Ok(ChaChaPolyReadAdapter { readable, .. }) => Ok((readable, control_tlvs_ss)),
235			_ => Err(()),
236		}
237	}
238
239	pub(crate) fn inner_blinded_path(&self) -> &BlindedPath {
240		&self.inner_path
241	}
242
243	pub(crate) fn from_parts(inner_path: BlindedPath, payinfo: BlindedPayInfo) -> Self {
244		Self { inner_path, payinfo }
245	}
246
247	/// Builds a new [`BlindedPaymentPath`] from its constituent parts.
248	///
249	/// Useful when reconstructing a blinded path from previously serialized components.
250	///
251	/// Parameters:
252	/// * `introduction_node_id`: The public key of the introduction node in the path.
253	/// * `blinding_point`: The public key used for blinding the path.
254	/// * `blinded_hops`: The encrypted routing information for each hop in the path.
255	/// * `payinfo`: The [`BlindedPayInfo`] for the blinded path.
256	pub fn from_blinded_path_and_payinfo(
257		introduction_node_id: PublicKey, blinding_point: PublicKey, blinded_hops: Vec<BlindedHop>,
258		payinfo: BlindedPayInfo,
259	) -> Self {
260		Self::from_parts(
261			BlindedPath {
262				introduction_node: IntroductionNode::NodeId(introduction_node_id),
263				blinding_point,
264				blinded_hops,
265			},
266			payinfo,
267		)
268	}
269
270	#[cfg(test)]
271	pub fn clear_blinded_hops(&mut self) {
272		self.inner_path.blinded_hops.clear()
273	}
274}
275
276/// An intermediate node, its outbound channel, and relay parameters.
277#[derive(Clone, Debug)]
278pub struct PaymentForwardNode {
279	/// The TLVs for this node's [`BlindedHop`], where the fee parameters contained within are also
280	/// used for [`BlindedPayInfo`] construction.
281	pub tlvs: ForwardTlvs,
282	/// This node's pubkey.
283	pub node_id: PublicKey,
284	/// The maximum value, in msat, that may be accepted by this node.
285	pub htlc_maximum_msat: u64,
286}
287
288/// Data to construct a [`BlindedHop`] for forwarding a payment.
289#[derive(Clone, Debug)]
290pub struct ForwardTlvs {
291	/// The short channel id this payment should be forwarded out over.
292	pub short_channel_id: u64,
293	/// Payment parameters for relaying over [`Self::short_channel_id`].
294	pub payment_relay: PaymentRelay,
295	/// Payment constraints for relaying over [`Self::short_channel_id`].
296	pub payment_constraints: PaymentConstraints,
297	/// Supported and required features when relaying a payment onion containing this object's
298	/// corresponding [`BlindedHop::encrypted_payload`].
299	///
300	/// [`BlindedHop::encrypted_payload`]: crate::blinded_path::BlindedHop::encrypted_payload
301	pub features: BlindedHopFeatures,
302	/// Set if this [`BlindedPaymentPath`] is concatenated to another, to indicate the
303	/// [`BlindedPaymentPath::blinding_point`] of the appended blinded path.
304	pub next_blinding_override: Option<PublicKey>,
305}
306
307/// Data to construct a [`BlindedHop`] for forwarding a Trampoline payment.
308#[derive(Clone, Debug)]
309pub struct TrampolineForwardTlvs {
310	/// The node id to which the trampoline node must find a route.
311	pub next_trampoline: PublicKey,
312	/// Payment parameters for relaying over [`Self::next_trampoline`].
313	pub payment_relay: PaymentRelay,
314	/// Payment constraints for relaying over [`Self::next_trampoline`].
315	pub payment_constraints: PaymentConstraints,
316	/// Supported and required features when relaying a payment onion containing this object's
317	/// corresponding [`BlindedHop::encrypted_payload`].
318	///
319	/// [`BlindedHop::encrypted_payload`]: crate::blinded_path::BlindedHop::encrypted_payload
320	pub features: BlindedHopFeatures,
321	/// Set if this [`BlindedPaymentPath`] is concatenated to another, to indicate the
322	/// [`BlindedPaymentPath::blinding_point`] of the appended blinded path.
323	pub next_blinding_override: Option<PublicKey>,
324}
325
326/// Data to construct a [`BlindedHop`] for receiving a payment. This payload is custom to LDK and
327/// may not be valid if received by another lightning implementation.
328///
329/// Can only be constructed by calling [`UnauthenticatedReceiveTlvs::authenticate`].
330#[derive(Clone, Debug)]
331pub struct ReceiveTlvs {
332	/// The TLVs for which the HMAC in `authentication` is derived.
333	pub(crate) tlvs: UnauthenticatedReceiveTlvs,
334	/// An HMAC of `tlvs` along with a nonce used to construct it.
335	pub(crate) authentication: (Hmac<Sha256>, Nonce),
336}
337
338impl ReceiveTlvs {
339	/// Returns the underlying TLVs.
340	pub fn tlvs(&self) -> &UnauthenticatedReceiveTlvs {
341		&self.tlvs
342	}
343}
344
345/// An unauthenticated [`ReceiveTlvs`].
346#[derive(Clone, Debug)]
347pub struct UnauthenticatedReceiveTlvs {
348	/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together.
349	pub payment_secret: PaymentSecret,
350	/// Constraints for the receiver of this payment.
351	pub payment_constraints: PaymentConstraints,
352	/// Context for the receiver of this payment.
353	pub payment_context: PaymentContext,
354}
355
356impl UnauthenticatedReceiveTlvs {
357	/// Creates an authenticated [`ReceiveTlvs`], which includes an HMAC and the provide [`Nonce`]
358	/// that can be use later to verify it authenticity.
359	pub fn authenticate(self, nonce: Nonce, expanded_key: &ExpandedKey) -> ReceiveTlvs {
360		ReceiveTlvs {
361			authentication: (self.hmac_for_offer_payment(nonce, expanded_key), nonce),
362			tlvs: self,
363		}
364	}
365}
366
367/// Data to construct a [`BlindedHop`] for sending a payment over.
368///
369/// [`BlindedHop`]: crate::blinded_path::BlindedHop
370pub(crate) enum BlindedPaymentTlvs {
371	/// This blinded payment data is for a forwarding node.
372	Forward(ForwardTlvs),
373	/// This blinded payment data is for the receiving node.
374	Receive(ReceiveTlvs),
375}
376
377/// Data to construct a [`BlindedHop`] for sending a Trampoline payment over.
378///
379/// [`BlindedHop`]: crate::blinded_path::BlindedHop
380pub(crate) enum BlindedTrampolineTlvs {
381	/// This blinded payment data is for a forwarding node.
382	Forward(TrampolineForwardTlvs),
383	/// This blinded payment data is for the receiving node.
384	Receive(ReceiveTlvs),
385}
386
387// Used to include forward and receive TLVs in the same iterator for encoding.
388enum BlindedPaymentTlvsRef<'a> {
389	Forward(&'a ForwardTlvs),
390	Receive(&'a ReceiveTlvs),
391}
392
393/// Parameters for relaying over a given [`BlindedHop`].
394///
395/// [`BlindedHop`]: crate::blinded_path::BlindedHop
396#[derive(Clone, Debug, PartialEq)]
397pub struct PaymentRelay {
398	/// Number of blocks subtracted from an incoming HTLC's `cltv_expiry` for this [`BlindedHop`].
399	pub cltv_expiry_delta: u16,
400	/// Liquidity fee charged (in millionths of the amount transferred) for relaying a payment over
401	/// this [`BlindedHop`], (i.e., 10,000 is 1%).
402	pub fee_proportional_millionths: u32,
403	/// Base fee charged (in millisatoshi) for relaying a payment over this [`BlindedHop`].
404	pub fee_base_msat: u32,
405}
406
407/// Constraints for relaying over a given [`BlindedHop`].
408///
409/// [`BlindedHop`]: crate::blinded_path::BlindedHop
410#[derive(Clone, Debug, PartialEq)]
411pub struct PaymentConstraints {
412	/// The maximum total CLTV that is acceptable when relaying a payment over this [`BlindedHop`].
413	pub max_cltv_expiry: u32,
414	/// The minimum value, in msat, that may be accepted by the node corresponding to this
415	/// [`BlindedHop`].
416	pub htlc_minimum_msat: u64,
417}
418
419/// The context of an inbound payment, which is included in a [`BlindedPaymentPath`] via
420/// [`ReceiveTlvs`] and surfaced in [`PaymentPurpose`].
421///
422/// [`PaymentPurpose`]: crate::events::PaymentPurpose
423#[derive(Clone, Debug, Eq, PartialEq)]
424pub enum PaymentContext {
425	/// The payment was made for an invoice requested from a BOLT 12 [`Offer`].
426	///
427	/// [`Offer`]: crate::offers::offer::Offer
428	Bolt12Offer(Bolt12OfferContext),
429
430	/// The payment was made for a static invoice requested from a BOLT 12 [`Offer`].
431	///
432	/// [`Offer`]: crate::offers::offer::Offer
433	AsyncBolt12Offer(AsyncBolt12OfferContext),
434
435	/// The payment was made for an invoice sent for a BOLT 12 [`Refund`].
436	///
437	/// [`Refund`]: crate::offers::refund::Refund
438	Bolt12Refund(Bolt12RefundContext),
439}
440
441// Used when writing PaymentContext in Event::PaymentClaimable to avoid cloning.
442pub(crate) enum PaymentContextRef<'a> {
443	Bolt12Offer(&'a Bolt12OfferContext),
444	Bolt12Refund(&'a Bolt12RefundContext),
445}
446
447/// The context of a payment made for an invoice requested from a BOLT 12 [`Offer`].
448///
449/// [`Offer`]: crate::offers::offer::Offer
450#[derive(Clone, Debug, Eq, PartialEq)]
451pub struct Bolt12OfferContext {
452	/// The identifier of the [`Offer`].
453	///
454	/// [`Offer`]: crate::offers::offer::Offer
455	pub offer_id: OfferId,
456
457	/// Fields from an [`InvoiceRequest`] sent for a [`Bolt12Invoice`].
458	///
459	/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
460	/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
461	pub invoice_request: InvoiceRequestFields,
462}
463
464/// The context of a payment made for a static invoice requested from a BOLT 12 [`Offer`].
465///
466/// [`Offer`]: crate::offers::offer::Offer
467#[derive(Clone, Debug, Eq, PartialEq)]
468pub struct AsyncBolt12OfferContext {
469	/// The [`Nonce`] used to verify that an inbound [`InvoiceRequest`] corresponds to this static
470	/// invoice's offer.
471	///
472	/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
473	pub offer_nonce: Nonce,
474}
475
476/// The context of a payment made for an invoice sent for a BOLT 12 [`Refund`].
477///
478/// [`Refund`]: crate::offers::refund::Refund
479#[derive(Clone, Debug, Eq, PartialEq)]
480pub struct Bolt12RefundContext {}
481
482impl TryFrom<CounterpartyForwardingInfo> for PaymentRelay {
483	type Error = ();
484
485	fn try_from(info: CounterpartyForwardingInfo) -> Result<Self, ()> {
486		let CounterpartyForwardingInfo {
487			fee_base_msat,
488			fee_proportional_millionths,
489			cltv_expiry_delta,
490		} = info;
491
492		// Avoid exposing esoteric CLTV expiry deltas
493		let cltv_expiry_delta = match cltv_expiry_delta {
494			0..=40 => 40,
495			41..=80 => 80,
496			81..=144 => 144,
497			145..=216 => 216,
498			_ => return Err(()),
499		};
500
501		Ok(Self { cltv_expiry_delta, fee_proportional_millionths, fee_base_msat })
502	}
503}
504
505impl Writeable for ForwardTlvs {
506	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
507		let features_opt = if self.features == BlindedHopFeatures::empty() {
508			None
509		} else {
510			Some(WithoutLength(&self.features))
511		};
512		encode_tlv_stream!(w, {
513			(2, self.short_channel_id, required),
514			(10, self.payment_relay, required),
515			(12, self.payment_constraints, required),
516			(14, features_opt, option)
517		});
518		Ok(())
519	}
520}
521
522impl Writeable for TrampolineForwardTlvs {
523	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
524		let features_opt = if self.features == BlindedHopFeatures::empty() {
525			None
526		} else {
527			Some(WithoutLength(&self.features))
528		};
529		encode_tlv_stream!(w, {
530			(4, self.next_trampoline, required),
531			(10, self.payment_relay, required),
532			(12, self.payment_constraints, required),
533			(14, features_opt, option)
534		});
535		Ok(())
536	}
537}
538
539impl Writeable for ReceiveTlvs {
540	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
541		encode_tlv_stream!(w, {
542			(12, self.tlvs.payment_constraints, required),
543			(65536, self.tlvs.payment_secret, required),
544			(65537, self.tlvs.payment_context, required),
545			(65539, self.authentication, required),
546		});
547		Ok(())
548	}
549}
550
551impl Writeable for UnauthenticatedReceiveTlvs {
552	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
553		encode_tlv_stream!(w, {
554			(12, self.payment_constraints, required),
555			(65536, self.payment_secret, required),
556			(65537, self.payment_context, required),
557		});
558		Ok(())
559	}
560}
561
562impl<'a> Writeable for BlindedPaymentTlvsRef<'a> {
563	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
564		match self {
565			Self::Forward(tlvs) => tlvs.write(w)?,
566			Self::Receive(tlvs) => tlvs.write(w)?,
567		}
568		Ok(())
569	}
570}
571
572impl Readable for BlindedPaymentTlvs {
573	fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
574		_init_and_read_tlv_stream!(r, {
575			// Reasoning: Padding refers to filler data added to a packet to increase
576			// its size and obscure its actual length. Since padding contains no meaningful
577			// information, we can safely omit reading it here.
578			// (1, _padding, option),
579			(2, scid, option),
580			(8, next_blinding_override, option),
581			(10, payment_relay, option),
582			(12, payment_constraints, required),
583			(14, features, (option, encoding: (BlindedHopFeatures, WithoutLength))),
584			(65536, payment_secret, option),
585			(65537, payment_context, option),
586			(65539, authentication, option),
587		});
588
589		if let Some(short_channel_id) = scid {
590			if payment_secret.is_some() {
591				return Err(DecodeError::InvalidValue);
592			}
593			Ok(BlindedPaymentTlvs::Forward(ForwardTlvs {
594				short_channel_id,
595				payment_relay: payment_relay.ok_or(DecodeError::InvalidValue)?,
596				payment_constraints: payment_constraints.0.unwrap(),
597				next_blinding_override,
598				features: features.unwrap_or_else(BlindedHopFeatures::empty),
599			}))
600		} else {
601			if payment_relay.is_some() || features.is_some() {
602				return Err(DecodeError::InvalidValue);
603			}
604			Ok(BlindedPaymentTlvs::Receive(ReceiveTlvs {
605				tlvs: UnauthenticatedReceiveTlvs {
606					payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?,
607					payment_constraints: payment_constraints.0.unwrap(),
608					payment_context: payment_context.ok_or(DecodeError::InvalidValue)?,
609				},
610				authentication: authentication.ok_or(DecodeError::InvalidValue)?,
611			}))
612		}
613	}
614}
615
616impl Readable for BlindedTrampolineTlvs {
617	fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
618		_init_and_read_tlv_stream!(r, {
619			(4, next_trampoline, option),
620			(8, next_blinding_override, option),
621			(10, payment_relay, option),
622			(12, payment_constraints, required),
623			(14, features, (option, encoding: (BlindedHopFeatures, WithoutLength))),
624			(65536, payment_secret, option),
625			(65537, payment_context, option),
626			(65539, authentication, option),
627		});
628
629		if let Some(next_trampoline) = next_trampoline {
630			if payment_secret.is_some() {
631				return Err(DecodeError::InvalidValue);
632			}
633			Ok(BlindedTrampolineTlvs::Forward(TrampolineForwardTlvs {
634				next_trampoline,
635				payment_relay: payment_relay.ok_or(DecodeError::InvalidValue)?,
636				payment_constraints: payment_constraints.0.unwrap(),
637				next_blinding_override,
638				features: features.unwrap_or_else(BlindedHopFeatures::empty),
639			}))
640		} else {
641			if payment_relay.is_some() || features.is_some() {
642				return Err(DecodeError::InvalidValue);
643			}
644			Ok(BlindedTrampolineTlvs::Receive(ReceiveTlvs {
645				tlvs: UnauthenticatedReceiveTlvs {
646					payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?,
647					payment_constraints: payment_constraints.0.unwrap(),
648					payment_context: payment_context.ok_or(DecodeError::InvalidValue)?,
649				},
650				authentication: authentication.ok_or(DecodeError::InvalidValue)?,
651			}))
652		}
653	}
654}
655
656/// Represents the padding round off size (in bytes) that
657/// is used to pad payment bilnded path's [`BlindedHop`]
658pub(crate) const PAYMENT_PADDING_ROUND_OFF: usize = 30;
659
660/// Construct blinded payment hops for the given `intermediate_nodes` and payee info.
661pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
662	secp_ctx: &Secp256k1<T>, intermediate_nodes: &[PaymentForwardNode], payee_node_id: PublicKey,
663	payee_tlvs: ReceiveTlvs, session_priv: &SecretKey,
664) -> Vec<BlindedHop> {
665	let pks = intermediate_nodes
666		.iter()
667		.map(|node| (node.node_id, None))
668		.chain(core::iter::once((payee_node_id, None)));
669	let tlvs = intermediate_nodes
670		.iter()
671		.map(|node| BlindedPaymentTlvsRef::Forward(&node.tlvs))
672		.chain(core::iter::once(BlindedPaymentTlvsRef::Receive(&payee_tlvs)));
673
674	let path = pks.zip(
675		tlvs.map(|tlv| BlindedPathWithPadding { tlvs: tlv, round_off: PAYMENT_PADDING_ROUND_OFF }),
676	);
677
678	utils::construct_blinded_hops(secp_ctx, path, session_priv)
679}
680
681/// `None` if underflow occurs.
682pub(crate) fn amt_to_forward_msat(
683	inbound_amt_msat: u64, payment_relay: &PaymentRelay,
684) -> Option<u64> {
685	let inbound_amt = inbound_amt_msat as u128;
686	let base = payment_relay.fee_base_msat as u128;
687	let prop = payment_relay.fee_proportional_millionths as u128;
688
689	let post_base_fee_inbound_amt =
690		if let Some(amt) = inbound_amt.checked_sub(base) { amt } else { return None };
691	let mut amt_to_forward =
692		(post_base_fee_inbound_amt * 1_000_000 + 1_000_000 + prop - 1) / (prop + 1_000_000);
693
694	let fee = ((amt_to_forward * prop) / 1_000_000) + base;
695	if inbound_amt - fee < amt_to_forward {
696		// Rounding up the forwarded amount resulted in underpaying this node, so take an extra 1 msat
697		// in fee to compensate.
698		amt_to_forward -= 1;
699	}
700	debug_assert_eq!(amt_to_forward + fee, inbound_amt);
701	u64::try_from(amt_to_forward).ok()
702}
703
704// Returns (aggregated_base_fee, aggregated_proportional_fee)
705pub(crate) fn compute_aggregated_base_prop_fee<I>(hops_fees: I) -> Result<(u64, u64), ()>
706where
707	I: DoubleEndedIterator<Item = RoutingFees>,
708{
709	let mut curr_base_fee: u64 = 0;
710	let mut curr_prop_mil: u64 = 0;
711	for fees in hops_fees.rev() {
712		let next_base_fee = fees.base_msat as u64;
713		let next_prop_mil = fees.proportional_millionths as u64;
714
715		// Use integer arithmetic to compute `ceil(a/b)` as `(a+b-1)/b`
716		// ((curr_base_fee * (1_000_000 + next_prop_mil)) / 1_000_000) + next_base_fee
717		curr_base_fee = curr_base_fee
718			.checked_mul(1_000_000 + next_prop_mil)
719			.and_then(|f| f.checked_add(1_000_000 - 1))
720			.map(|f| f / 1_000_000)
721			.and_then(|f| f.checked_add(next_base_fee))
722			.ok_or(())?;
723		// ceil(((curr_prop_mil + 1_000_000) * (next_prop_mil + 1_000_000)) / 1_000_000) - 1_000_000
724		curr_prop_mil = curr_prop_mil
725			.checked_add(1_000_000)
726			.and_then(|f1| next_prop_mil.checked_add(1_000_000).and_then(|f2| f2.checked_mul(f1)))
727			.and_then(|f| f.checked_add(1_000_000 - 1))
728			.map(|f| f / 1_000_000)
729			.and_then(|f| f.checked_sub(1_000_000))
730			.ok_or(())?;
731	}
732
733	Ok((curr_base_fee, curr_prop_mil))
734}
735
736pub(super) fn compute_payinfo(
737	intermediate_nodes: &[PaymentForwardNode], payee_tlvs: &UnauthenticatedReceiveTlvs,
738	payee_htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16,
739) -> Result<BlindedPayInfo, ()> {
740	let (aggregated_base_fee, aggregated_prop_fee) =
741		compute_aggregated_base_prop_fee(intermediate_nodes.iter().map(|node| RoutingFees {
742			base_msat: node.tlvs.payment_relay.fee_base_msat,
743			proportional_millionths: node.tlvs.payment_relay.fee_proportional_millionths,
744		}))?;
745
746	let mut htlc_minimum_msat: u64 = 1;
747	let mut htlc_maximum_msat: u64 = 21_000_000 * 100_000_000 * 1_000; // Total bitcoin supply
748	let mut cltv_expiry_delta: u16 = min_final_cltv_expiry_delta;
749	for node in intermediate_nodes.iter() {
750		// In the future, we'll want to take the intersection of all supported features for the
751		// `BlindedPayInfo`, but there are no features in that context right now.
752		if node.tlvs.features.requires_unknown_bits_from(&BlindedHopFeatures::empty()) {
753			return Err(());
754		}
755
756		cltv_expiry_delta =
757			cltv_expiry_delta.checked_add(node.tlvs.payment_relay.cltv_expiry_delta).ok_or(())?;
758
759		// The min htlc for an intermediate node is that node's min minus the fees charged by all of the
760		// following hops for forwarding that min, since that fee amount will automatically be included
761		// in the amount that this node receives and contribute towards reaching its min.
762		htlc_minimum_msat = amt_to_forward_msat(
763			core::cmp::max(node.tlvs.payment_constraints.htlc_minimum_msat, htlc_minimum_msat),
764			&node.tlvs.payment_relay,
765		)
766		.unwrap_or(1); // If underflow occurs, we definitely reached this node's min
767		htlc_maximum_msat = amt_to_forward_msat(
768			core::cmp::min(node.htlc_maximum_msat, htlc_maximum_msat),
769			&node.tlvs.payment_relay,
770		)
771		.ok_or(())?; // If underflow occurs, we cannot send to this hop without exceeding their max
772	}
773	htlc_minimum_msat =
774		core::cmp::max(payee_tlvs.payment_constraints.htlc_minimum_msat, htlc_minimum_msat);
775	htlc_maximum_msat = core::cmp::min(payee_htlc_maximum_msat, htlc_maximum_msat);
776
777	if htlc_maximum_msat < htlc_minimum_msat {
778		return Err(());
779	}
780	Ok(BlindedPayInfo {
781		fee_base_msat: u32::try_from(aggregated_base_fee).map_err(|_| ())?,
782		fee_proportional_millionths: u32::try_from(aggregated_prop_fee).map_err(|_| ())?,
783		cltv_expiry_delta,
784		htlc_minimum_msat,
785		htlc_maximum_msat,
786		features: BlindedHopFeatures::empty(),
787	})
788}
789
790impl Writeable for PaymentRelay {
791	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
792		self.cltv_expiry_delta.write(w)?;
793		self.fee_proportional_millionths.write(w)?;
794		HighZeroBytesDroppedBigSize(self.fee_base_msat).write(w)
795	}
796}
797impl Readable for PaymentRelay {
798	fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
799		let cltv_expiry_delta: u16 = Readable::read(r)?;
800		let fee_proportional_millionths: u32 = Readable::read(r)?;
801		let fee_base_msat: HighZeroBytesDroppedBigSize<u32> = Readable::read(r)?;
802		Ok(Self { cltv_expiry_delta, fee_proportional_millionths, fee_base_msat: fee_base_msat.0 })
803	}
804}
805
806impl Writeable for PaymentConstraints {
807	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
808		self.max_cltv_expiry.write(w)?;
809		HighZeroBytesDroppedBigSize(self.htlc_minimum_msat).write(w)
810	}
811}
812impl Readable for PaymentConstraints {
813	fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
814		let max_cltv_expiry: u32 = Readable::read(r)?;
815		let htlc_minimum_msat: HighZeroBytesDroppedBigSize<u64> = Readable::read(r)?;
816		Ok(Self { max_cltv_expiry, htlc_minimum_msat: htlc_minimum_msat.0 })
817	}
818}
819
820impl_writeable_tlv_based_enum_legacy!(PaymentContext,
821	;
822	// 0 for Unknown removed in version 0.1.
823	(1, Bolt12Offer),
824	(2, Bolt12Refund),
825	(3, AsyncBolt12Offer),
826);
827
828impl<'a> Writeable for PaymentContextRef<'a> {
829	fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
830		match self {
831			PaymentContextRef::Bolt12Offer(context) => {
832				1u8.write(w)?;
833				context.write(w)?;
834			},
835			PaymentContextRef::Bolt12Refund(context) => {
836				2u8.write(w)?;
837				context.write(w)?;
838			},
839		}
840
841		Ok(())
842	}
843}
844
845impl_writeable_tlv_based!(Bolt12OfferContext, {
846	(0, offer_id, required),
847	(2, invoice_request, required),
848});
849
850impl_writeable_tlv_based!(AsyncBolt12OfferContext, {
851	(0, offer_nonce, required),
852});
853
854impl_writeable_tlv_based!(Bolt12RefundContext, {});
855
856#[cfg(test)]
857mod tests {
858	use crate::blinded_path::payment::{
859		Bolt12RefundContext, ForwardTlvs, PaymentConstraints, PaymentContext, PaymentForwardNode,
860		PaymentRelay, UnauthenticatedReceiveTlvs,
861	};
862	use crate::ln::functional_test_utils::TEST_FINAL_CLTV;
863	use crate::types::features::BlindedHopFeatures;
864	use crate::types::payment::PaymentSecret;
865	use bitcoin::secp256k1::PublicKey;
866
867	#[test]
868	fn compute_payinfo() {
869		// Taken from the spec example for aggregating blinded payment info. See
870		// https://github.com/lightning/bolts/blob/master/proposals/route-blinding.md#blinded-payments
871		let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap();
872		let intermediate_nodes = [
873			PaymentForwardNode {
874				node_id: dummy_pk,
875				tlvs: ForwardTlvs {
876					short_channel_id: 0,
877					payment_relay: PaymentRelay {
878						cltv_expiry_delta: 144,
879						fee_proportional_millionths: 500,
880						fee_base_msat: 100,
881					},
882					payment_constraints: PaymentConstraints {
883						max_cltv_expiry: 0,
884						htlc_minimum_msat: 100,
885					},
886					next_blinding_override: None,
887					features: BlindedHopFeatures::empty(),
888				},
889				htlc_maximum_msat: u64::max_value(),
890			},
891			PaymentForwardNode {
892				node_id: dummy_pk,
893				tlvs: ForwardTlvs {
894					short_channel_id: 0,
895					payment_relay: PaymentRelay {
896						cltv_expiry_delta: 144,
897						fee_proportional_millionths: 500,
898						fee_base_msat: 100,
899					},
900					payment_constraints: PaymentConstraints {
901						max_cltv_expiry: 0,
902						htlc_minimum_msat: 1_000,
903					},
904					next_blinding_override: None,
905					features: BlindedHopFeatures::empty(),
906				},
907				htlc_maximum_msat: u64::max_value(),
908			},
909		];
910		let recv_tlvs = UnauthenticatedReceiveTlvs {
911			payment_secret: PaymentSecret([0; 32]),
912			payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 },
913			payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
914		};
915		let htlc_maximum_msat = 100_000;
916		let blinded_payinfo =
917			super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat, 12)
918				.unwrap();
919		assert_eq!(blinded_payinfo.fee_base_msat, 201);
920		assert_eq!(blinded_payinfo.fee_proportional_millionths, 1001);
921		assert_eq!(blinded_payinfo.cltv_expiry_delta, 300);
922		assert_eq!(blinded_payinfo.htlc_minimum_msat, 900);
923		assert_eq!(blinded_payinfo.htlc_maximum_msat, htlc_maximum_msat);
924	}
925
926	#[test]
927	fn compute_payinfo_1_hop() {
928		let recv_tlvs = UnauthenticatedReceiveTlvs {
929			payment_secret: PaymentSecret([0; 32]),
930			payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 },
931			payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
932		};
933		let blinded_payinfo =
934			super::compute_payinfo(&[], &recv_tlvs, 4242, TEST_FINAL_CLTV as u16).unwrap();
935		assert_eq!(blinded_payinfo.fee_base_msat, 0);
936		assert_eq!(blinded_payinfo.fee_proportional_millionths, 0);
937		assert_eq!(blinded_payinfo.cltv_expiry_delta, TEST_FINAL_CLTV as u16);
938		assert_eq!(blinded_payinfo.htlc_minimum_msat, 1);
939		assert_eq!(blinded_payinfo.htlc_maximum_msat, 4242);
940	}
941
942	#[test]
943	fn simple_aggregated_htlc_min() {
944		// If no hops charge fees, the htlc_minimum_msat should just be the maximum htlc_minimum_msat
945		// along the path.
946		let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap();
947		let intermediate_nodes = [
948			PaymentForwardNode {
949				node_id: dummy_pk,
950				tlvs: ForwardTlvs {
951					short_channel_id: 0,
952					payment_relay: PaymentRelay {
953						cltv_expiry_delta: 0,
954						fee_proportional_millionths: 0,
955						fee_base_msat: 0,
956					},
957					payment_constraints: PaymentConstraints {
958						max_cltv_expiry: 0,
959						htlc_minimum_msat: 1,
960					},
961					next_blinding_override: None,
962					features: BlindedHopFeatures::empty(),
963				},
964				htlc_maximum_msat: u64::max_value(),
965			},
966			PaymentForwardNode {
967				node_id: dummy_pk,
968				tlvs: ForwardTlvs {
969					short_channel_id: 0,
970					payment_relay: PaymentRelay {
971						cltv_expiry_delta: 0,
972						fee_proportional_millionths: 0,
973						fee_base_msat: 0,
974					},
975					payment_constraints: PaymentConstraints {
976						max_cltv_expiry: 0,
977						htlc_minimum_msat: 2_000,
978					},
979					next_blinding_override: None,
980					features: BlindedHopFeatures::empty(),
981				},
982				htlc_maximum_msat: u64::max_value(),
983			},
984		];
985		let recv_tlvs = UnauthenticatedReceiveTlvs {
986			payment_secret: PaymentSecret([0; 32]),
987			payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 3 },
988			payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
989		};
990		let htlc_maximum_msat = 100_000;
991		let blinded_payinfo = super::compute_payinfo(
992			&intermediate_nodes[..],
993			&recv_tlvs,
994			htlc_maximum_msat,
995			TEST_FINAL_CLTV as u16,
996		)
997		.unwrap();
998		assert_eq!(blinded_payinfo.htlc_minimum_msat, 2_000);
999	}
1000
1001	#[test]
1002	fn aggregated_htlc_min() {
1003		// Create a path with varying fees and htlc_mins, and make sure htlc_minimum_msat ends up as the
1004		// max (htlc_min - following_fees) along the path.
1005		let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap();
1006		let intermediate_nodes = [
1007			PaymentForwardNode {
1008				node_id: dummy_pk,
1009				tlvs: ForwardTlvs {
1010					short_channel_id: 0,
1011					payment_relay: PaymentRelay {
1012						cltv_expiry_delta: 0,
1013						fee_proportional_millionths: 500,
1014						fee_base_msat: 1_000,
1015					},
1016					payment_constraints: PaymentConstraints {
1017						max_cltv_expiry: 0,
1018						htlc_minimum_msat: 5_000,
1019					},
1020					next_blinding_override: None,
1021					features: BlindedHopFeatures::empty(),
1022				},
1023				htlc_maximum_msat: u64::max_value(),
1024			},
1025			PaymentForwardNode {
1026				node_id: dummy_pk,
1027				tlvs: ForwardTlvs {
1028					short_channel_id: 0,
1029					payment_relay: PaymentRelay {
1030						cltv_expiry_delta: 0,
1031						fee_proportional_millionths: 500,
1032						fee_base_msat: 200,
1033					},
1034					payment_constraints: PaymentConstraints {
1035						max_cltv_expiry: 0,
1036						htlc_minimum_msat: 2_000,
1037					},
1038					next_blinding_override: None,
1039					features: BlindedHopFeatures::empty(),
1040				},
1041				htlc_maximum_msat: u64::max_value(),
1042			},
1043		];
1044		let recv_tlvs = UnauthenticatedReceiveTlvs {
1045			payment_secret: PaymentSecret([0; 32]),
1046			payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 },
1047			payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
1048		};
1049		let htlc_minimum_msat = 3798;
1050		assert!(super::compute_payinfo(
1051			&intermediate_nodes[..],
1052			&recv_tlvs,
1053			htlc_minimum_msat - 1,
1054			TEST_FINAL_CLTV as u16
1055		)
1056		.is_err());
1057
1058		let htlc_maximum_msat = htlc_minimum_msat + 1;
1059		let blinded_payinfo = super::compute_payinfo(
1060			&intermediate_nodes[..],
1061			&recv_tlvs,
1062			htlc_maximum_msat,
1063			TEST_FINAL_CLTV as u16,
1064		)
1065		.unwrap();
1066		assert_eq!(blinded_payinfo.htlc_minimum_msat, htlc_minimum_msat);
1067		assert_eq!(blinded_payinfo.htlc_maximum_msat, htlc_maximum_msat);
1068	}
1069
1070	#[test]
1071	fn aggregated_htlc_max() {
1072		// Create a path with varying fees and `htlc_maximum_msat`s, and make sure the aggregated max
1073		// htlc ends up as the min (htlc_max - following_fees) along the path.
1074		let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap();
1075		let intermediate_nodes = [
1076			PaymentForwardNode {
1077				node_id: dummy_pk,
1078				tlvs: ForwardTlvs {
1079					short_channel_id: 0,
1080					payment_relay: PaymentRelay {
1081						cltv_expiry_delta: 0,
1082						fee_proportional_millionths: 500,
1083						fee_base_msat: 1_000,
1084					},
1085					payment_constraints: PaymentConstraints {
1086						max_cltv_expiry: 0,
1087						htlc_minimum_msat: 1,
1088					},
1089					next_blinding_override: None,
1090					features: BlindedHopFeatures::empty(),
1091				},
1092				htlc_maximum_msat: 5_000,
1093			},
1094			PaymentForwardNode {
1095				node_id: dummy_pk,
1096				tlvs: ForwardTlvs {
1097					short_channel_id: 0,
1098					payment_relay: PaymentRelay {
1099						cltv_expiry_delta: 0,
1100						fee_proportional_millionths: 500,
1101						fee_base_msat: 1,
1102					},
1103					payment_constraints: PaymentConstraints {
1104						max_cltv_expiry: 0,
1105						htlc_minimum_msat: 1,
1106					},
1107					next_blinding_override: None,
1108					features: BlindedHopFeatures::empty(),
1109				},
1110				htlc_maximum_msat: 10_000,
1111			},
1112		];
1113		let recv_tlvs = UnauthenticatedReceiveTlvs {
1114			payment_secret: PaymentSecret([0; 32]),
1115			payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 },
1116			payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
1117		};
1118
1119		let blinded_payinfo = super::compute_payinfo(
1120			&intermediate_nodes[..],
1121			&recv_tlvs,
1122			10_000,
1123			TEST_FINAL_CLTV as u16,
1124		)
1125		.unwrap();
1126		assert_eq!(blinded_payinfo.htlc_maximum_msat, 3997);
1127	}
1128}