1 //! Utilities for channelmanager.rs
3 //! Includes a public [`peel_payment_onion`] function for use by external projects or libraries.
5 use bitcoin::hashes::Hash;
6 use bitcoin::hashes::sha256::Hash as Sha256;
7 use bitcoin::secp256k1::{self, Secp256k1, PublicKey};
9 use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
10 use crate::ln::PaymentHash;
11 use crate::ln::channelmanager::{CLTV_FAR_FAR_AWAY, HTLCFailureMsg, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting};
13 use crate::ln::onion_utils;
14 use crate::ln::onion_utils::HTLCFailReason;
15 use crate::sign::{NodeSigner, Recipient};
16 use crate::util::logger::Logger;
18 use crate::prelude::*;
21 /// Invalid inbound onion payment.
22 pub struct InboundOnionErr {
23 /// BOLT 4 error code.
25 /// Data attached to this error.
26 pub err_data: Vec<u8>,
27 /// Error message text.
28 pub msg: &'static str,
31 pub(super) fn create_fwd_pending_htlc_info(
32 msg: &msgs::UpdateAddHTLC, hop_data: msgs::InboundOnionPayload, hop_hmac: [u8; 32],
33 new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32],
34 next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
35 ) -> Result<PendingHTLCInfo, InboundOnionErr> {
36 debug_assert!(next_packet_pubkey_opt.is_some());
37 let outgoing_packet = msgs::OnionPacket {
39 public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
40 hop_data: new_packet_bytes,
44 let (short_channel_id, amt_to_forward, outgoing_cltv_value) = match hop_data {
45 msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } =>
46 (short_channel_id, amt_to_forward, outgoing_cltv_value),
47 msgs::InboundOnionPayload::Receive { .. } | msgs::InboundOnionPayload::BlindedReceive { .. } =>
48 return Err(InboundOnionErr {
49 msg: "Final Node OnionHopData provided for us as an intermediary node",
50 err_code: 0x4000 | 22,
56 routing: PendingHTLCRouting::Forward {
57 onion_packet: outgoing_packet,
61 payment_hash: msg.payment_hash,
62 incoming_shared_secret: shared_secret,
63 incoming_amt_msat: Some(msg.amount_msat),
64 outgoing_amt_msat: amt_to_forward,
66 skimmed_fee_msat: None,
70 pub(super) fn create_recv_pending_htlc_info(
71 hop_data: msgs::InboundOnionPayload, shared_secret: [u8; 32], payment_hash: PaymentHash,
72 amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool,
73 counterparty_skimmed_fee_msat: Option<u64>, current_height: u32, accept_mpp_keysend: bool,
74 ) -> Result<PendingHTLCInfo, InboundOnionErr> {
75 let (payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, outgoing_cltv_value, payment_metadata) = match hop_data {
76 msgs::InboundOnionPayload::Receive {
77 payment_data, keysend_preimage, custom_tlvs, amt_msat, outgoing_cltv_value, payment_metadata, ..
79 (payment_data, keysend_preimage, custom_tlvs, amt_msat, outgoing_cltv_value, payment_metadata),
80 msgs::InboundOnionPayload::BlindedReceive {
81 amt_msat, total_msat, outgoing_cltv_value, payment_secret, ..
83 let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
84 (Some(payment_data), None, Vec::new(), amt_msat, outgoing_cltv_value, None)
86 msgs::InboundOnionPayload::Forward { .. } => {
87 return Err(InboundOnionErr {
90 msg: "Got non final data with an HMAC of 0",
94 // final_incorrect_cltv_expiry
95 if outgoing_cltv_value > cltv_expiry {
96 return Err(InboundOnionErr {
97 msg: "Upstream node set CLTV to less than the CLTV set by the sender",
99 err_data: cltv_expiry.to_be_bytes().to_vec()
102 // final_expiry_too_soon
103 // We have to have some headroom to broadcast on chain if we have the preimage, so make sure
104 // we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
106 // Also, ensure that, in the case of an unknown preimage for the received payment hash, our
107 // payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
108 // channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
109 if cltv_expiry <= current_height + HTLC_FAIL_BACK_BUFFER + 1 {
110 let mut err_data = Vec::with_capacity(12);
111 err_data.extend_from_slice(&amt_msat.to_be_bytes());
112 err_data.extend_from_slice(¤t_height.to_be_bytes());
113 return Err(InboundOnionErr {
114 err_code: 0x4000 | 15, err_data,
115 msg: "The final CLTV expiry is too soon to handle",
118 if (!allow_underpay && onion_amt_msat > amt_msat) ||
119 (allow_underpay && onion_amt_msat >
120 amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0)))
122 return Err(InboundOnionErr {
124 err_data: amt_msat.to_be_bytes().to_vec(),
125 msg: "Upstream node sent less than we were supposed to receive in payment",
129 let routing = if let Some(payment_preimage) = keysend_preimage {
130 // We need to check that the sender knows the keysend preimage before processing this
131 // payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
132 // could discover the final destination of X, by probing the adjacent nodes on the route
133 // with a keysend payment of identical payment hash to X and observing the processing
134 // time discrepancies due to a hash collision with X.
135 let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array());
136 if hashed_preimage != payment_hash {
137 return Err(InboundOnionErr {
139 err_data: Vec::new(),
140 msg: "Payment preimage didn't match payment hash",
143 if !accept_mpp_keysend && payment_data.is_some() {
144 return Err(InboundOnionErr {
146 err_data: Vec::new(),
147 msg: "We don't support MPP keysend payments",
150 PendingHTLCRouting::ReceiveKeysend {
154 incoming_cltv_expiry: outgoing_cltv_value,
157 } else if let Some(data) = payment_data {
158 PendingHTLCRouting::Receive {
161 incoming_cltv_expiry: outgoing_cltv_value,
162 phantom_shared_secret,
166 return Err(InboundOnionErr {
167 err_code: 0x4000|0x2000|3,
168 err_data: Vec::new(),
169 msg: "We require payment_secrets",
175 incoming_shared_secret: shared_secret,
176 incoming_amt_msat: Some(amt_msat),
177 outgoing_amt_msat: onion_amt_msat,
179 skimmed_fee_msat: counterparty_skimmed_fee_msat,
183 /// Peel one layer off an incoming onion, returning [`PendingHTLCInfo`] (either Forward or Receive).
184 /// This does all the relevant context-free checks that LDK requires for payment relay or
185 /// acceptance. If the payment is to be received, and the amount matches the expected amount for
186 /// a given invoice, this indicates the [`msgs::UpdateAddHTLC`], once fully committed in the
187 /// channel, will generate an [`Event::PaymentClaimable`].
189 /// [`Event::PaymentClaimable`]: crate::events::Event::PaymentClaimable
190 pub fn peel_payment_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
191 msg: &msgs::UpdateAddHTLC, node_signer: &NS, logger: &L, secp_ctx: &Secp256k1<T>,
192 cur_height: u32, accept_mpp_keysend: bool,
193 ) -> Result<PendingHTLCInfo, InboundOnionErr>
195 NS::Target: NodeSigner,
198 let (hop, shared_secret, next_packet_details_opt) =
199 decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx
201 let (err_code, err_data) = match e {
202 HTLCFailureMsg::Malformed(m) => (m.failure_code, Vec::new()),
203 HTLCFailureMsg::Relay(r) => (0x4000 | 22, r.reason.data),
205 let msg = "Failed to decode update add htlc onion";
206 InboundOnionErr { msg, err_code, err_data }
209 onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
210 let NextPacketDetails {
211 next_packet_pubkey, outgoing_amt_msat: _, outgoing_scid: _, outgoing_cltv_value
212 } = match next_packet_details_opt {
213 Some(next_packet_details) => next_packet_details,
214 // Forward should always include the next hop details
215 None => return Err(InboundOnionErr {
216 msg: "Failed to decode update add htlc onion",
217 err_code: 0x4000 | 22,
218 err_data: Vec::new(),
222 if let Err((err_msg, code)) = check_incoming_htlc_cltv(
223 cur_height, outgoing_cltv_value, msg.cltv_expiry
225 return Err(InboundOnionErr {
228 err_data: Vec::new(),
231 create_fwd_pending_htlc_info(
232 msg, next_hop_data, next_hop_hmac, new_packet_bytes, shared_secret,
233 Some(next_packet_pubkey)
236 onion_utils::Hop::Receive(received_data) => {
237 create_recv_pending_htlc_info(
238 received_data, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
239 None, false, msg.skimmed_fee_msat, cur_height, accept_mpp_keysend,
245 pub(super) struct NextPacketDetails {
246 pub(super) next_packet_pubkey: Result<PublicKey, secp256k1::Error>,
247 pub(super) outgoing_scid: u64,
248 pub(super) outgoing_amt_msat: u64,
249 pub(super) outgoing_cltv_value: u32,
252 pub(super) fn decode_incoming_update_add_htlc_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
253 msg: &msgs::UpdateAddHTLC, node_signer: &NS, logger: &L, secp_ctx: &Secp256k1<T>,
254 ) -> Result<(onion_utils::Hop, [u8; 32], Option<NextPacketDetails>), HTLCFailureMsg>
256 NS::Target: NodeSigner,
259 macro_rules! return_malformed_err {
260 ($msg: expr, $err_code: expr) => {
262 log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg);
263 return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
264 channel_id: msg.channel_id,
265 htlc_id: msg.htlc_id,
266 sha256_of_onion: Sha256::hash(&msg.onion_routing_packet.hop_data).to_byte_array(),
267 failure_code: $err_code,
273 if let Err(_) = msg.onion_routing_packet.public_key {
274 return_malformed_err!("invalid ephemeral pubkey", 0x8000 | 0x4000 | 6);
277 let shared_secret = node_signer.ecdh(
278 Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), None
279 ).unwrap().secret_bytes();
281 if msg.onion_routing_packet.version != 0 {
282 //TODO: Spec doesn't indicate if we should only hash hop_data here (and in other
283 //sha256_of_onion error data packets), or the entire onion_routing_packet. Either way,
284 //the hash doesn't really serve any purpose - in the case of hashing all data, the
285 //receiving node would have to brute force to figure out which version was put in the
286 //packet by the node that send us the message, in the case of hashing the hop_data, the
287 //node knows the HMAC matched, so they already know what is there...
288 return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4);
290 macro_rules! return_err {
291 ($msg: expr, $err_code: expr, $data: expr) => {
293 log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg);
294 return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
295 channel_id: msg.channel_id,
296 htlc_id: msg.htlc_id,
297 reason: HTLCFailReason::reason($err_code, $data.to_vec())
298 .get_encrypted_failure_packet(&shared_secret, &None),
304 let next_hop = match onion_utils::decode_next_payment_hop(
305 shared_secret, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac,
306 msg.payment_hash, node_signer
309 Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
310 return_malformed_err!(err_msg, err_code);
312 Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code }) => {
313 return_err!(err_msg, err_code, &[0; 0]);
317 let next_packet_details = match next_hop {
318 onion_utils::Hop::Forward {
319 next_hop_data: msgs::InboundOnionPayload::Forward {
320 short_channel_id, amt_to_forward, outgoing_cltv_value
323 let next_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx,
324 msg.onion_routing_packet.public_key.unwrap(), &shared_secret);
326 next_packet_pubkey, outgoing_scid: short_channel_id,
327 outgoing_amt_msat: amt_to_forward, outgoing_cltv_value
330 onion_utils::Hop::Receive { .. } => return Ok((next_hop, shared_secret, None)),
331 onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionPayload::Receive { .. }, .. } |
332 onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionPayload::BlindedReceive { .. }, .. } =>
334 return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0; 0]);
338 Ok((next_hop, shared_secret, Some(next_packet_details)))
341 pub(super) fn check_incoming_htlc_cltv(
342 cur_height: u32, outgoing_cltv_value: u32, cltv_expiry: u32
343 ) -> Result<(), (&'static str, u16)> {
344 if (cltv_expiry as u64) < (outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 {
346 "Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
347 0x1000 | 13, // incorrect_cltv_expiry
350 // Theoretically, channel counterparty shouldn't send us a HTLC expiring now,
351 // but we want to be robust wrt to counterparty packet sanitization (see
352 // HTLC_FAIL_BACK_BUFFER rationale).
353 if cltv_expiry <= cur_height + HTLC_FAIL_BACK_BUFFER as u32 { // expiry_too_soon
354 return Err(("CLTV expiry is too close", 0x1000 | 14));
356 if cltv_expiry > cur_height + CLTV_FAR_FAR_AWAY as u32 { // expiry_too_far
357 return Err(("CLTV expiry is too far in the future", 21));
359 // If the HTLC expires ~now, don't bother trying to forward it to our
360 // counterparty. They should fail it anyway, but we don't want to bother with
361 // the round-trips or risk them deciding they definitely want the HTLC and
362 // force-closing to ensure they get it if we're offline.
363 // We previously had a much more aggressive check here which tried to ensure
364 // our counterparty receives an HTLC which has *our* risk threshold met on it,
365 // but there is no need to do that, and since we're a bit conservative with our
366 // risk threshold it just results in failing to forward payments.
367 if (outgoing_cltv_value) as u64 <= (cur_height + LATENCY_GRACE_PERIOD_BLOCKS) as u64 {
368 return Err(("Outgoing CLTV value is too soon", 0x1000 | 14));
376 use bitcoin::hashes::Hash;
377 use bitcoin::hashes::sha256::Hash as Sha256;
378 use bitcoin::secp256k1::{PublicKey, SecretKey};
379 use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
380 use crate::ln::ChannelId;
381 use crate::ln::channelmanager::RecipientOnionFields;
382 use crate::ln::features::{ChannelFeatures, NodeFeatures};
384 use crate::ln::onion_utils::create_payment_onion;
385 use crate::routing::router::{Path, RouteHop};
386 use crate::util::test_utils;
389 fn test_peel_payment_onion() {
391 let secp_ctx = Secp256k1::new();
393 let bob = crate::sign::KeysManager::new(&[2; 32], 42, 42);
394 let bob_pk = PublicKey::from_secret_key(&secp_ctx, &bob.get_node_secret_key());
395 let charlie = crate::sign::KeysManager::new(&[3; 32], 42, 42);
396 let charlie_pk = PublicKey::from_secret_key(&secp_ctx, &charlie.get_node_secret_key());
398 let (session_priv, total_amt_msat, cur_height, recipient_onion, preimage, payment_hash,
399 prng_seed, hops, recipient_amount, pay_secret) = payment_onion_args(bob_pk, charlie_pk);
406 let (onion, amount_msat, cltv_expiry) = create_payment_onion(
407 &secp_ctx, &path, &session_priv, total_amt_msat, recipient_onion, cur_height,
408 &payment_hash, &Some(preimage), prng_seed
411 let msg = make_update_add_msg(amount_msat, cltv_expiry, payment_hash, onion);
412 let logger = test_utils::TestLogger::with_id("bob".to_string());
414 let peeled = peel_payment_onion(&msg, &&bob, &&logger, &secp_ctx, cur_height, true)
415 .map_err(|e| e.msg).unwrap();
417 let next_onion = match peeled.routing {
418 PendingHTLCRouting::Forward { onion_packet, .. } => {
421 _ => panic!("expected a forwarded onion"),
424 let msg2 = make_update_add_msg(amount_msat, cltv_expiry, payment_hash, next_onion);
425 let peeled2 = peel_payment_onion(&msg2, &&charlie, &&logger, &secp_ctx, cur_height, true)
426 .map_err(|e| e.msg).unwrap();
428 match peeled2.routing {
429 PendingHTLCRouting::ReceiveKeysend { payment_preimage, payment_data, incoming_cltv_expiry, .. } => {
430 assert_eq!(payment_preimage, preimage);
431 assert_eq!(peeled2.outgoing_amt_msat, recipient_amount);
432 assert_eq!(incoming_cltv_expiry, peeled2.outgoing_cltv_value);
433 let msgs::FinalOnionHopData{total_msat, payment_secret} = payment_data.unwrap();
434 assert_eq!(total_msat, total_amt_msat);
435 assert_eq!(payment_secret, pay_secret);
437 _ => panic!("expected a received keysend"),
441 fn make_update_add_msg(
442 amount_msat: u64, cltv_expiry: u32, payment_hash: PaymentHash,
443 onion_routing_packet: msgs::OnionPacket
444 ) -> msgs::UpdateAddHTLC {
445 msgs::UpdateAddHTLC {
446 channel_id: ChannelId::from_bytes([0; 32]),
451 onion_routing_packet,
452 skimmed_fee_msat: None,
453 blinding_point: None,
457 fn payment_onion_args(hop_pk: PublicKey, recipient_pk: PublicKey) -> (
458 SecretKey, u64, u32, RecipientOnionFields, PaymentPreimage, PaymentHash, [u8; 32],
459 Vec<RouteHop>, u64, PaymentSecret,
461 let session_priv_bytes = [42; 32];
462 let session_priv = SecretKey::from_slice(&session_priv_bytes).unwrap();
463 let total_amt_msat = 1000;
464 let cur_height = 1000;
465 let pay_secret = PaymentSecret([99; 32]);
466 let recipient_onion = RecipientOnionFields::secret_only(pay_secret);
467 let preimage_bytes = [43; 32];
468 let preimage = PaymentPreimage(preimage_bytes);
469 let rhash_bytes = Sha256::hash(&preimage_bytes).to_byte_array();
470 let payment_hash = PaymentHash(rhash_bytes);
471 let prng_seed = [44; 32];
473 // make a route alice -> bob -> charlie
475 let recipient_amount = total_amt_msat - hop_fee;
480 cltv_expiry_delta: 42,
482 node_features: NodeFeatures::empty(),
483 channel_features: ChannelFeatures::empty(),
484 maybe_announced_channel: false,
487 pubkey: recipient_pk,
488 fee_msat: recipient_amount,
489 cltv_expiry_delta: 42,
491 node_features: NodeFeatures::empty(),
492 channel_features: ChannelFeatures::empty(),
493 maybe_announced_channel: false,
497 (session_priv, total_amt_msat, cur_height, recipient_onion, preimage, payment_hash,
498 prng_seed, hops, recipient_amount, pay_secret)