lightning/ln/
onion_payment.rs

1//! Utilities to decode payment onions and do contextless validation of incoming payments.
2//!
3//! Primarily features [`peel_payment_onion`], which allows the decoding of an onion statelessly
4//! and can be used to predict whether we'd accept a payment.
5
6use bitcoin::hashes::sha256::Hash as Sha256;
7use bitcoin::hashes::Hash;
8use bitcoin::secp256k1::ecdh::SharedSecret;
9use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
10
11use crate::blinded_path;
12use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay};
13use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
14use crate::ln::channelmanager::{
15	BlindedFailure, BlindedForward, HTLCFailureMsg, PendingHTLCInfo, PendingHTLCRouting,
16	CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA,
17};
18use crate::ln::msgs;
19use crate::ln::onion_utils;
20use crate::ln::onion_utils::{HTLCFailReason, LocalHTLCFailureReason, ONION_DATA_LEN};
21use crate::sign::{NodeSigner, Recipient};
22use crate::types::features::BlindedHopFeatures;
23use crate::types::payment::PaymentHash;
24use crate::util::logger::Logger;
25
26#[allow(unused_imports)]
27use crate::prelude::*;
28
29use core::ops::Deref;
30
31/// Invalid inbound onion payment.
32#[derive(Clone, Debug, Hash, PartialEq, Eq)]
33pub struct InboundHTLCErr {
34	/// BOLT 4 error code.
35	pub reason: LocalHTLCFailureReason,
36	/// Data attached to this error.
37	pub err_data: Vec<u8>,
38	/// Error message text.
39	pub msg: &'static str,
40}
41
42/// Writes payment data for invalid or unknown payment error code.
43pub(super) fn invalid_payment_err_data(amt_msat: u64, current_height: u32) -> Vec<u8> {
44	let mut err_data = Vec::with_capacity(12);
45	err_data.extend_from_slice(&amt_msat.to_be_bytes());
46	err_data.extend_from_slice(&current_height.to_be_bytes());
47	err_data
48}
49
50#[rustfmt::skip]
51fn check_blinded_payment_constraints(
52	amt_msat: u64, cltv_expiry: u32, constraints: &PaymentConstraints
53) -> Result<(), ()> {
54	if amt_msat < constraints.htlc_minimum_msat ||
55		cltv_expiry > constraints.max_cltv_expiry
56	{ return Err(()) }
57	Ok(())
58}
59
60#[rustfmt::skip]
61fn check_blinded_forward(
62	inbound_amt_msat: u64, inbound_cltv_expiry: u32, payment_relay: &PaymentRelay,
63	payment_constraints: &PaymentConstraints, features: &BlindedHopFeatures
64) -> Result<(u64, u32), ()> {
65	let amt_to_forward = blinded_path::payment::amt_to_forward_msat(
66		inbound_amt_msat, payment_relay
67	).ok_or(())?;
68	let outgoing_cltv_value = inbound_cltv_expiry.checked_sub(
69		payment_relay.cltv_expiry_delta as u32
70	).ok_or(())?;
71	check_blinded_payment_constraints(inbound_amt_msat, outgoing_cltv_value, payment_constraints)?;
72
73	if features.requires_unknown_bits_from(&BlindedHopFeatures::empty()) { return Err(()) }
74	Ok((amt_to_forward, outgoing_cltv_value))
75}
76
77enum RoutingInfo {
78	Direct {
79		short_channel_id: u64,
80		new_packet_bytes: [u8; ONION_DATA_LEN],
81		next_hop_hmac: [u8; 32],
82	},
83	Trampoline {
84		next_trampoline: PublicKey,
85		// Trampoline onions are currently variable length
86		new_packet_bytes: Vec<u8>,
87		next_hop_hmac: [u8; 32],
88		shared_secret: SharedSecret,
89		current_path_key: Option<PublicKey>,
90	},
91}
92
93#[rustfmt::skip]
94pub(super) fn create_fwd_pending_htlc_info(
95	msg: &msgs::UpdateAddHTLC, hop_data: onion_utils::Hop, shared_secret: [u8; 32],
96	next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
97) -> Result<PendingHTLCInfo, InboundHTLCErr> {
98	debug_assert!(next_packet_pubkey_opt.is_some());
99
100	let (
101		routing_info, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
102		next_blinding_override
103	) = match hop_data {
104		onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload {
105			short_channel_id, amt_to_forward, outgoing_cltv_value
106		}, new_packet_bytes, next_hop_hmac, .. } =>
107			(RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, None, None),
108		onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload {
109			short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features,
110			next_blinding_override,
111		}, new_packet_bytes, next_hop_hmac, .. } => {
112			let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward(
113				msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features
114			).map_err(|()| {
115				// We should be returning malformed here if `msg.blinding_point` is set, but this is
116				// unreachable right now since we checked it in `decode_update_add_htlc_onion`.
117				InboundHTLCErr {
118					msg: "Underflow calculating outbound amount or cltv value for blinded forward",
119					reason: LocalHTLCFailureReason::InvalidOnionBlinding,
120					err_data: vec![0; 32],
121				}
122			})?;
123			(RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
124				next_blinding_override)
125		},
126		onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } =>
127			return Err(InboundHTLCErr {
128				msg: "Final Node OnionHopData provided for us as an intermediary node",
129				reason: LocalHTLCFailureReason::InvalidOnionPayload,
130				err_data: Vec::new(),
131			}),
132		onion_utils::Hop::TrampolineReceive { .. } | onion_utils::Hop::TrampolineBlindedReceive { .. } =>
133			return Err(InboundHTLCErr {
134				msg: "Final Node OnionHopData provided for us as an intermediary node",
135				reason: LocalHTLCFailureReason::InvalidOnionPayload,
136				err_data: Vec::new(),
137			}),
138		onion_utils::Hop::TrampolineForward { next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
139			(
140				RoutingInfo::Trampoline {
141					next_trampoline: next_trampoline_hop_data.next_trampoline,
142					new_packet_bytes: new_trampoline_packet_bytes,
143					next_hop_hmac: next_trampoline_hop_hmac,
144					shared_secret: trampoline_shared_secret,
145					current_path_key: None
146				},
147				next_trampoline_hop_data.amt_to_forward,
148				next_trampoline_hop_data.outgoing_cltv_value,
149				None,
150				None
151			)
152		},
153		onion_utils::Hop::TrampolineBlindedForward { outer_hop_data, next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
154			let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward(
155				msg.amount_msat, msg.cltv_expiry, &next_trampoline_hop_data.payment_relay, &next_trampoline_hop_data.payment_constraints, &next_trampoline_hop_data.features
156			).map_err(|()| {
157				// We should be returning malformed here if `msg.blinding_point` is set, but this is
158				// unreachable right now since we checked it in `decode_update_add_htlc_onion`.
159				InboundHTLCErr {
160					msg: "Underflow calculating outbound amount or cltv value for blinded forward",
161					reason: LocalHTLCFailureReason::InvalidOnionBlinding,
162					err_data: vec![0; 32],
163				}
164			})?;
165			(
166				RoutingInfo::Trampoline {
167					next_trampoline: next_trampoline_hop_data.next_trampoline,
168					new_packet_bytes: new_trampoline_packet_bytes,
169					next_hop_hmac: next_trampoline_hop_hmac,
170					shared_secret: trampoline_shared_secret,
171					current_path_key: outer_hop_data.current_path_key
172				},
173				amt_to_forward,
174				outgoing_cltv_value,
175				next_trampoline_hop_data.intro_node_blinding_point,
176				next_trampoline_hop_data.next_blinding_override
177			)
178		},
179	};
180
181	let routing = match routing_info {
182		RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac } => {
183			let outgoing_packet = msgs::OnionPacket {
184				version: 0,
185				public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
186				hop_data: new_packet_bytes,
187				hmac: next_hop_hmac,
188			};
189			PendingHTLCRouting::Forward {
190				onion_packet: outgoing_packet,
191				short_channel_id,
192				incoming_cltv_expiry: Some(msg.cltv_expiry),
193				hold_htlc: msg.hold_htlc,
194				blinded: intro_node_blinding_point.or(msg.blinding_point)
195					.map(|bp| BlindedForward {
196						inbound_blinding_point: bp,
197						next_blinding_override,
198						failure: intro_node_blinding_point
199							.map(|_| BlindedFailure::FromIntroductionNode)
200							.unwrap_or(BlindedFailure::FromBlindedNode),
201					}),
202			}
203		}
204		RoutingInfo::Trampoline { next_trampoline, new_packet_bytes, next_hop_hmac, shared_secret, current_path_key } => {
205			let next_trampoline_packet_pubkey = match next_packet_pubkey_opt {
206				Some(Ok(pubkey)) => pubkey,
207				_ => return Err(InboundHTLCErr {
208					msg: "Missing next Trampoline hop pubkey from intermediate Trampoline forwarding data",
209					reason: LocalHTLCFailureReason::InvalidTrampolinePayload,
210					err_data: Vec::new(),
211				}),
212			};
213			let outgoing_packet = msgs::TrampolineOnionPacket {
214				version: 0,
215				public_key: next_trampoline_packet_pubkey,
216				hop_data: new_packet_bytes,
217				hmac: next_hop_hmac,
218			};
219			PendingHTLCRouting::TrampolineForward {
220				incoming_shared_secret: shared_secret.secret_bytes(),
221				onion_packet: outgoing_packet,
222				node_id: next_trampoline,
223				incoming_cltv_expiry: msg.cltv_expiry,
224				blinded: intro_node_blinding_point.or(current_path_key)
225					.map(|bp| BlindedForward {
226						inbound_blinding_point: bp,
227						next_blinding_override,
228						failure: intro_node_blinding_point
229							.map(|_| BlindedFailure::FromIntroductionNode)
230							.unwrap_or(BlindedFailure::FromBlindedNode),
231					})
232			}
233		}
234	};
235
236	Ok(PendingHTLCInfo {
237		routing,
238		payment_hash: msg.payment_hash,
239		incoming_shared_secret: shared_secret,
240		incoming_amt_msat: Some(msg.amount_msat),
241		outgoing_amt_msat: amt_to_forward,
242		outgoing_cltv_value,
243		skimmed_fee_msat: None,
244	})
245}
246
247#[rustfmt::skip]
248pub(super) fn create_recv_pending_htlc_info(
249	hop_data: onion_utils::Hop, shared_secret: [u8; 32], payment_hash: PaymentHash,
250	amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool,
251	counterparty_skimmed_fee_msat: Option<u64>, current_height: u32
252) -> Result<PendingHTLCInfo, InboundHTLCErr> {
253	let (
254		payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, onion_cltv_expiry,
255		payment_metadata, payment_context, requires_blinded_error, has_recipient_created_payment_secret,
256		invoice_request
257	) = match hop_data {
258		onion_utils::Hop::Receive { hop_data: msgs::InboundOnionReceivePayload {
259			payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
260			cltv_expiry_height, payment_metadata, ..
261		}, .. } =>
262			(payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
263			 cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None),
264		onion_utils::Hop::BlindedReceive { hop_data: msgs::InboundOnionBlindedReceivePayload {
265			sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
266			intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage,
267			custom_tlvs, invoice_request
268		}, .. } => {
269			check_blinded_payment_constraints(
270				sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints
271			)
272				.map_err(|()| {
273					InboundHTLCErr {
274						reason: LocalHTLCFailureReason::InvalidOnionBlinding,
275						err_data: vec![0; 32],
276						msg: "Amount or cltv_expiry violated blinded payment constraints",
277					}
278				})?;
279			let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
280			(Some(payment_data), keysend_preimage, custom_tlvs,
281			 sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
282			 intro_node_blinding_point.is_none(), true, invoice_request)
283		}
284		onion_utils::Hop::TrampolineReceive {
285			trampoline_hop_data: msgs::InboundOnionReceivePayload {
286				payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
287				cltv_expiry_height, payment_metadata, ..
288			}, ..
289		} =>
290			(payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
291				cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None),
292		onion_utils::Hop::TrampolineBlindedReceive {
293			trampoline_hop_data: msgs::InboundOnionBlindedReceivePayload {
294				sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
295				intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage,
296				custom_tlvs, invoice_request
297			}, ..
298		} => {
299			check_blinded_payment_constraints(
300				sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints,
301			)
302				.map_err(|()| {
303					InboundHTLCErr {
304						reason: LocalHTLCFailureReason::InvalidOnionBlinding,
305						err_data: vec![0; 32],
306						msg: "Amount or cltv_expiry violated blinded payment constraints within Trampoline onion",
307					}
308				})?;
309			let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
310			(Some(payment_data), keysend_preimage, custom_tlvs,
311				sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
312				intro_node_blinding_point.is_none(), true, invoice_request)
313		},
314		onion_utils::Hop::Forward { .. } => {
315			return Err(InboundHTLCErr {
316				reason: LocalHTLCFailureReason::InvalidOnionPayload,
317				err_data: Vec::new(),
318				msg: "Got non final data with an HMAC of 0",
319			})
320		},
321		onion_utils::Hop::BlindedForward { .. } => {
322			return Err(InboundHTLCErr {
323				reason: LocalHTLCFailureReason::InvalidOnionBlinding,
324				err_data: vec![0; 32],
325				msg: "Got blinded non final data with an HMAC of 0",
326			})
327		},
328		onion_utils::Hop::TrampolineForward { .. } | onion_utils::Hop::TrampolineBlindedForward { .. } => {
329			return Err(InboundHTLCErr {
330				reason: LocalHTLCFailureReason::InvalidOnionPayload,
331				err_data: Vec::new(),
332				msg: "Got Trampoline non final data with an HMAC of 0",
333			})
334		},
335	};
336	// final_incorrect_cltv_expiry
337	if onion_cltv_expiry > cltv_expiry {
338		return Err(InboundHTLCErr {
339			msg: "Upstream node set CLTV to less than the CLTV set by the sender",
340			reason: LocalHTLCFailureReason::FinalIncorrectCLTVExpiry,
341			err_data: cltv_expiry.to_be_bytes().to_vec()
342		})
343	}
344	// final_expiry_too_soon
345	// We have to have some headroom to broadcast on chain if we have the preimage, so make sure
346	// we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
347	//
348	// Also, ensure that, in the case of an unknown preimage for the received payment hash, our
349	// payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
350	// channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
351	if cltv_expiry <= current_height + HTLC_FAIL_BACK_BUFFER + 1 {
352		return Err(InboundHTLCErr {
353			reason: LocalHTLCFailureReason::PaymentClaimBuffer,
354			err_data: invalid_payment_err_data(amt_msat, current_height),
355			msg: "The final CLTV expiry is too soon to handle",
356		});
357	}
358	if (!allow_underpay && onion_amt_msat > amt_msat) ||
359		(allow_underpay && onion_amt_msat >
360		 amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0)))
361	{
362		return Err(InboundHTLCErr {
363			reason: LocalHTLCFailureReason::FinalIncorrectHTLCAmount,
364			err_data: amt_msat.to_be_bytes().to_vec(),
365			msg: "Upstream node sent less than we were supposed to receive in payment",
366		});
367	}
368
369	let routing = if let Some(payment_preimage) = keysend_preimage {
370		// We need to check that the sender knows the keysend preimage before processing this
371		// payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
372		// could discover the final destination of X, by probing the adjacent nodes on the route
373		// with a keysend payment of identical payment hash to X and observing the processing
374		// time discrepancies due to a hash collision with X.
375		let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array());
376		if hashed_preimage != payment_hash {
377			return Err(InboundHTLCErr {
378				reason: LocalHTLCFailureReason::InvalidKeysendPreimage,
379				err_data: invalid_payment_err_data(amt_msat, current_height),
380				msg: "Payment preimage didn't match payment hash",
381			});
382		}
383		PendingHTLCRouting::ReceiveKeysend {
384			payment_data,
385			payment_preimage,
386			payment_metadata,
387			incoming_cltv_expiry: onion_cltv_expiry,
388			custom_tlvs,
389			requires_blinded_error,
390			has_recipient_created_payment_secret,
391			payment_context,
392			invoice_request,
393		}
394	} else if let Some(data) = payment_data {
395		PendingHTLCRouting::Receive {
396			payment_data: data,
397			payment_metadata,
398			payment_context,
399			incoming_cltv_expiry: onion_cltv_expiry,
400			phantom_shared_secret,
401			custom_tlvs,
402			requires_blinded_error,
403		}
404	} else {
405		return Err(InboundHTLCErr {
406			reason: LocalHTLCFailureReason::PaymentSecretRequired,
407			err_data: Vec::new(),
408			msg: "We require payment_secrets",
409		});
410	};
411	Ok(PendingHTLCInfo {
412		routing,
413		payment_hash,
414		incoming_shared_secret: shared_secret,
415		incoming_amt_msat: Some(amt_msat),
416		outgoing_amt_msat: onion_amt_msat,
417		outgoing_cltv_value: onion_cltv_expiry,
418		skimmed_fee_msat: counterparty_skimmed_fee_msat,
419	})
420}
421
422/// Peel one layer off an incoming onion, returning a [`PendingHTLCInfo`] that contains information
423/// about the intended next-hop for the HTLC.
424///
425/// This does all the relevant context-free checks that LDK requires for payment relay or
426/// acceptance. If the payment is to be received, and the amount matches the expected amount for
427/// a given invoice, this indicates the [`msgs::UpdateAddHTLC`], once fully committed in the
428/// channel, will generate an [`Event::PaymentClaimable`].
429///
430/// [`Event::PaymentClaimable`]: crate::events::Event::PaymentClaimable
431#[rustfmt::skip]
432pub fn peel_payment_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
433	msg: &msgs::UpdateAddHTLC, node_signer: NS, logger: L, secp_ctx: &Secp256k1<T>,
434	cur_height: u32, allow_skimmed_fees: bool,
435) -> Result<PendingHTLCInfo, InboundHTLCErr>
436where
437	NS::Target: NodeSigner,
438	L::Target: Logger,
439{
440	let (hop, next_packet_details_opt) =
441		decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx
442	).map_err(|(msg, failure_reason)| {
443		let (reason, err_data) = match msg {
444			HTLCFailureMsg::Malformed(_) => (failure_reason, Vec::new()),
445			HTLCFailureMsg::Relay(r) => (LocalHTLCFailureReason::InvalidOnionPayload, r.reason),
446		};
447		let msg = "Failed to decode update add htlc onion";
448		InboundHTLCErr { msg, reason, err_data }
449	})?;
450	Ok(match hop {
451		onion_utils::Hop::Forward { shared_secret, .. } |
452		onion_utils::Hop::BlindedForward { shared_secret, .. } => {
453			let NextPacketDetails {
454				next_packet_pubkey, outgoing_amt_msat: _, outgoing_connector: _, outgoing_cltv_value
455			} = match next_packet_details_opt {
456				Some(next_packet_details) => next_packet_details,
457				// Forward should always include the next hop details
458				None => return Err(InboundHTLCErr {
459					msg: "Failed to decode update add htlc onion",
460					reason: LocalHTLCFailureReason::InvalidOnionPayload,
461					err_data: Vec::new(),
462				}),
463			};
464
465			if let Err(reason) = check_incoming_htlc_cltv(
466				cur_height, outgoing_cltv_value, msg.cltv_expiry,
467			) {
468				return Err(InboundHTLCErr {
469					msg: "incoming cltv check failed",
470					reason,
471					err_data: Vec::new(),
472				});
473			}
474
475			// TODO: If this is potentially a phantom payment we should decode the phantom payment
476			// onion here and check it.
477			create_fwd_pending_htlc_info(msg, hop, shared_secret.secret_bytes(), Some(next_packet_pubkey))?
478		},
479		_ => {
480			let shared_secret = hop.shared_secret().secret_bytes();
481			create_recv_pending_htlc_info(
482				hop, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
483				None, allow_skimmed_fees, msg.skimmed_fee_msat, cur_height,
484			)?
485		}
486	})
487}
488
489pub(super) enum HopConnector {
490	// scid-based routing
491	ShortChannelId(u64),
492	// Trampoline-based routing
493	#[allow(unused)]
494	Trampoline(PublicKey),
495}
496
497pub(super) struct NextPacketDetails {
498	pub(super) next_packet_pubkey: Result<PublicKey, secp256k1::Error>,
499	pub(super) outgoing_connector: HopConnector,
500	pub(super) outgoing_amt_msat: u64,
501	pub(super) outgoing_cltv_value: u32,
502}
503
504#[rustfmt::skip]
505pub(super) fn decode_incoming_update_add_htlc_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
506	msg: &msgs::UpdateAddHTLC, node_signer: NS, logger: L, secp_ctx: &Secp256k1<T>,
507) -> Result<(onion_utils::Hop, Option<NextPacketDetails>), (HTLCFailureMsg, LocalHTLCFailureReason)>
508where
509	NS::Target: NodeSigner,
510	L::Target: Logger,
511{
512	let encode_malformed_error = |message: &str, failure_reason: LocalHTLCFailureReason| {
513		log_info!(logger, "Failed to accept/forward incoming HTLC: {}", message);
514		let (sha256_of_onion, failure_reason) = if msg.blinding_point.is_some() || failure_reason == LocalHTLCFailureReason::InvalidOnionBlinding {
515			([0; 32], LocalHTLCFailureReason::InvalidOnionBlinding)
516		} else {
517			(Sha256::hash(&msg.onion_routing_packet.hop_data).to_byte_array(), failure_reason)
518		};
519		return Err((HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
520			channel_id: msg.channel_id,
521			htlc_id: msg.htlc_id,
522			sha256_of_onion,
523			failure_code: failure_reason.failure_code(),
524		}), failure_reason));
525	};
526
527	if let Err(_) = msg.onion_routing_packet.public_key {
528		return encode_malformed_error("invalid ephemeral pubkey", LocalHTLCFailureReason::InvalidOnionKey);
529	}
530
531	if msg.onion_routing_packet.version != 0 {
532		//TODO: Spec doesn't indicate if we should only hash hop_data here (and in other
533		//sha256_of_onion error data packets), or the entire onion_routing_packet. Either way,
534		//the hash doesn't really serve any purpose - in the case of hashing all data, the
535		//receiving node would have to brute force to figure out which version was put in the
536		//packet by the node that send us the message, in the case of hashing the hop_data, the
537		//node knows the HMAC matched, so they already know what is there...
538		return encode_malformed_error("Unknown onion packet version", LocalHTLCFailureReason::InvalidOnionVersion)
539	}
540
541	let encode_relay_error = |message: &str, reason: LocalHTLCFailureReason, shared_secret: [u8; 32], trampoline_shared_secret: Option<[u8; 32]>, data: &[u8]| {
542		if msg.blinding_point.is_some() {
543			return encode_malformed_error(message, LocalHTLCFailureReason::InvalidOnionBlinding)
544		}
545
546		log_info!(logger, "Failed to accept/forward incoming HTLC: {}", message);
547		let failure = HTLCFailReason::reason(reason, data.to_vec())
548			.get_encrypted_failure_packet(&shared_secret, &trampoline_shared_secret);
549		return Err((HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
550			channel_id: msg.channel_id,
551			htlc_id: msg.htlc_id,
552			reason: failure.data,
553			attribution_data: failure.attribution_data,
554		}), reason));
555	};
556
557	let next_hop = match onion_utils::decode_next_payment_hop(
558		Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac,
559		msg.payment_hash, msg.blinding_point, node_signer
560	) {
561		Ok(res) => res,
562		Err(onion_utils::OnionDecodeErr::Malformed { err_msg, reason }) => {
563			return encode_malformed_error(err_msg, reason);
564		},
565		Err(onion_utils::OnionDecodeErr::Relay { err_msg, reason, shared_secret, trampoline_shared_secret }) => {
566			return encode_relay_error(err_msg, reason, shared_secret.secret_bytes(), trampoline_shared_secret.map(|tss| tss.secret_bytes()), &[0; 0]);
567		},
568	};
569
570	let next_packet_details = match next_hop {
571		onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload { short_channel_id, amt_to_forward, outgoing_cltv_value }, shared_secret, .. } => {
572			let next_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx,
573				msg.onion_routing_packet.public_key.unwrap(), &shared_secret.secret_bytes());
574			Some(NextPacketDetails {
575				next_packet_pubkey, outgoing_connector: HopConnector::ShortChannelId(short_channel_id),
576				outgoing_amt_msat: amt_to_forward, outgoing_cltv_value
577			})
578		}
579		onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload { short_channel_id, ref payment_relay, ref payment_constraints, ref features, .. }, shared_secret, .. } => {
580			let (amt_to_forward, outgoing_cltv_value) = match check_blinded_forward(
581				msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features
582			) {
583				Ok((amt, cltv)) => (amt, cltv),
584				Err(()) => {
585					return encode_relay_error("Underflow calculating outbound amount or cltv value for blinded forward",
586						LocalHTLCFailureReason::InvalidOnionBlinding, shared_secret.secret_bytes(), None, &[0; 32]);
587				}
588			};
589			let next_packet_pubkey = onion_utils::next_hop_pubkey(&secp_ctx,
590				msg.onion_routing_packet.public_key.unwrap(), &shared_secret.secret_bytes());
591			Some(NextPacketDetails {
592				next_packet_pubkey, outgoing_connector: HopConnector::ShortChannelId(short_channel_id), outgoing_amt_msat: amt_to_forward,
593				outgoing_cltv_value
594			})
595		}
596		onion_utils::Hop::TrampolineForward { next_trampoline_hop_data: msgs::InboundTrampolineForwardPayload { amt_to_forward, outgoing_cltv_value, next_trampoline }, trampoline_shared_secret, incoming_trampoline_public_key, .. } => {
597			let next_trampoline_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx,
598				incoming_trampoline_public_key, &trampoline_shared_secret.secret_bytes());
599			Some(NextPacketDetails {
600				next_packet_pubkey: next_trampoline_packet_pubkey,
601				outgoing_connector: HopConnector::Trampoline(next_trampoline),
602				outgoing_amt_msat: amt_to_forward,
603				outgoing_cltv_value,
604			})
605		}
606		_ => None
607	};
608
609	Ok((next_hop, next_packet_details))
610}
611
612pub(super) fn check_incoming_htlc_cltv(
613	cur_height: u32, outgoing_cltv_value: u32, cltv_expiry: u32,
614) -> Result<(), LocalHTLCFailureReason> {
615	if (cltv_expiry as u64) < (outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 {
616		return Err(LocalHTLCFailureReason::IncorrectCLTVExpiry);
617	}
618	// Theoretically, channel counterparty shouldn't send us a HTLC expiring now,
619	// but we want to be robust wrt to counterparty packet sanitization (see
620	// HTLC_FAIL_BACK_BUFFER rationale).
621	if cltv_expiry <= cur_height + HTLC_FAIL_BACK_BUFFER as u32 {
622		return Err(LocalHTLCFailureReason::CLTVExpiryTooSoon);
623	}
624	if cltv_expiry > cur_height + CLTV_FAR_FAR_AWAY as u32 {
625		return Err(LocalHTLCFailureReason::CLTVExpiryTooFar);
626	}
627	// If the HTLC expires ~now, don't bother trying to forward it to our
628	// counterparty. They should fail it anyway, but we don't want to bother with
629	// the round-trips or risk them deciding they definitely want the HTLC and
630	// force-closing to ensure they get it if we're offline.
631	// We previously had a much more aggressive check here which tried to ensure
632	// our counterparty receives an HTLC which has *our* risk threshold met on it,
633	// but there is no need to do that, and since we're a bit conservative with our
634	// risk threshold it just results in failing to forward payments.
635	if (outgoing_cltv_value) as u64 <= (cur_height + LATENCY_GRACE_PERIOD_BLOCKS) as u64 {
636		return Err(LocalHTLCFailureReason::OutgoingCLTVTooSoon);
637	}
638
639	Ok(())
640}
641
642#[cfg(test)]
643mod tests {
644	use crate::ln::channelmanager::{RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA};
645	use crate::ln::functional_test_utils::TEST_FINAL_CLTV;
646	use crate::ln::msgs;
647	use crate::ln::onion_utils::create_payment_onion;
648	use crate::ln::types::ChannelId;
649	use crate::routing::router::{Path, RouteHop};
650	use crate::types::features::{ChannelFeatures, NodeFeatures};
651	use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
652	use crate::util::test_utils;
653	use bitcoin::hashes::sha256::Hash as Sha256;
654	use bitcoin::hashes::Hash;
655	use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
656
657	#[test]
658	#[rustfmt::skip]
659	fn fail_construct_onion_on_too_big_payloads() {
660		// Ensure that if we call `construct_onion_packet` and friends where payloads are too large for
661		// the allotted packet length, we'll fail to construct. Previously, senders would happily
662		// construct invalid packets by array-shifting the final node's HMAC out of the packet when
663		// adding an intermediate onion layer, causing the receiver to error with "final payload
664		// provided for us as an intermediate node."
665		let secp_ctx = Secp256k1::new();
666		let bob = crate::sign::KeysManager::new(&[2; 32], 42, 42, true);
667		let bob_pk = PublicKey::from_secret_key(&secp_ctx, &bob.get_node_secret_key());
668		let charlie = crate::sign::KeysManager::new(&[3; 32], 42, 42, true);
669		let charlie_pk = PublicKey::from_secret_key(&secp_ctx, &charlie.get_node_secret_key());
670
671		let (
672			session_priv, total_amt_msat, cur_height, mut recipient_onion, keysend_preimage, payment_hash,
673			prng_seed, hops, ..
674		) = payment_onion_args(bob_pk, charlie_pk);
675
676		// Ensure the onion will not fit all the payloads by adding a large custom TLV.
677		recipient_onion.custom_tlvs.push((13377331, vec![0; 1156]));
678
679		let path = Path { hops, blinded_tail: None, };
680		let onion_keys = super::onion_utils::construct_onion_keys(&secp_ctx, &path, &session_priv);
681		let (onion_payloads, ..) = super::onion_utils::build_onion_payloads(
682			&path, total_amt_msat, &recipient_onion, cur_height + 1, &Some(keysend_preimage), None, None
683		).unwrap();
684
685		assert!(super::onion_utils::construct_onion_packet(
686				onion_payloads, onion_keys, prng_seed, &payment_hash
687		).is_err());
688	}
689
690	#[test]
691	#[rustfmt::skip]
692	fn test_peel_payment_onion() {
693		use super::*;
694		let secp_ctx = Secp256k1::new();
695
696		let bob = crate::sign::KeysManager::new(&[2; 32], 42, 42, true);
697		let bob_pk = PublicKey::from_secret_key(&secp_ctx, &bob.get_node_secret_key());
698		let charlie = crate::sign::KeysManager::new(&[3; 32], 42, 42, true);
699		let charlie_pk = PublicKey::from_secret_key(&secp_ctx, &charlie.get_node_secret_key());
700
701		let (session_priv, total_amt_msat, cur_height, recipient_onion, preimage, payment_hash,
702			prng_seed, hops, recipient_amount, pay_secret) = payment_onion_args(bob_pk, charlie_pk);
703
704		let path = Path {
705			hops: hops,
706			blinded_tail: None,
707		};
708
709		let (onion, amount_msat, cltv_expiry) = create_payment_onion(
710			&secp_ctx, &path, &session_priv, total_amt_msat, &recipient_onion,
711			cur_height, &payment_hash, &Some(preimage), None, prng_seed
712		).unwrap();
713
714		let msg = make_update_add_msg(amount_msat, cltv_expiry, payment_hash, onion);
715		let logger = test_utils::TestLogger::with_id("bob".to_string());
716
717		let peeled = peel_payment_onion(&msg, &bob, &logger, &secp_ctx, cur_height, false)
718			.map_err(|e| e.msg).unwrap();
719
720		let next_onion = match peeled.routing {
721			PendingHTLCRouting::Forward { onion_packet, .. } => {
722				onion_packet
723			},
724			_ => panic!("expected a forwarded onion"),
725		};
726
727		let msg2 = make_update_add_msg(amount_msat, cltv_expiry, payment_hash, next_onion);
728		let peeled2 = peel_payment_onion(&msg2, &charlie, &logger, &secp_ctx, cur_height, false)
729			.map_err(|e| e.msg).unwrap();
730
731		match peeled2.routing {
732			PendingHTLCRouting::ReceiveKeysend { payment_preimage, payment_data, incoming_cltv_expiry, .. } => {
733				assert_eq!(payment_preimage, preimage);
734				assert_eq!(peeled2.outgoing_amt_msat, recipient_amount);
735				assert_eq!(incoming_cltv_expiry, peeled2.outgoing_cltv_value);
736				let msgs::FinalOnionHopData{total_msat, payment_secret} = payment_data.unwrap();
737				assert_eq!(total_msat, total_amt_msat);
738				assert_eq!(payment_secret, pay_secret);
739			},
740			_ => panic!("expected a received keysend"),
741		};
742	}
743
744	fn make_update_add_msg(
745		amount_msat: u64, cltv_expiry: u32, payment_hash: PaymentHash,
746		onion_routing_packet: msgs::OnionPacket,
747	) -> msgs::UpdateAddHTLC {
748		msgs::UpdateAddHTLC {
749			channel_id: ChannelId::from_bytes([0; 32]),
750			htlc_id: 0,
751			amount_msat,
752			cltv_expiry,
753			payment_hash,
754			onion_routing_packet,
755			skimmed_fee_msat: None,
756			blinding_point: None,
757			hold_htlc: None,
758		}
759	}
760
761	#[rustfmt::skip]
762	fn payment_onion_args(hop_pk: PublicKey, recipient_pk: PublicKey) -> (
763		SecretKey, u64, u32, RecipientOnionFields, PaymentPreimage, PaymentHash, [u8; 32],
764		Vec<RouteHop>, u64, PaymentSecret,
765	) {
766		let session_priv_bytes = [42; 32];
767		let session_priv = SecretKey::from_slice(&session_priv_bytes).unwrap();
768		let total_amt_msat = 1000;
769		let cur_height = 1000;
770		let pay_secret = PaymentSecret([99; 32]);
771		let recipient_onion = RecipientOnionFields::secret_only(pay_secret);
772		let preimage_bytes = [43; 32];
773		let preimage = PaymentPreimage(preimage_bytes);
774		let rhash_bytes = Sha256::hash(&preimage_bytes).to_byte_array();
775		let payment_hash = PaymentHash(rhash_bytes);
776		let prng_seed = [44; 32];
777
778		// make a route alice -> bob -> charlie
779		let hop_fee = 1;
780		let recipient_amount = total_amt_msat - hop_fee;
781		let hops = vec![
782			RouteHop {
783				pubkey: hop_pk,
784				fee_msat: hop_fee,
785				cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA as u32,
786				short_channel_id: 1,
787				node_features: NodeFeatures::empty(),
788				channel_features: ChannelFeatures::empty(),
789				maybe_announced_channel: false,
790			},
791			RouteHop {
792				pubkey: recipient_pk,
793				fee_msat: recipient_amount,
794				cltv_expiry_delta: TEST_FINAL_CLTV,
795				short_channel_id: 2,
796				node_features: NodeFeatures::empty(),
797				channel_features: ChannelFeatures::empty(),
798				maybe_announced_channel: false,
799			}
800		];
801
802		(session_priv, total_amt_msat, cur_height, recipient_onion, preimage, payment_hash,
803			prng_seed, hops, recipient_amount, pay_secret)
804	}
805}