1use super::msgs::OnionErrorPacket;
11use crate::blinded_path::BlindedHop;
12use crate::crypto::chacha20::ChaCha20;
13use crate::crypto::streams::ChaChaReader;
14use crate::events::HTLCHandlingFailureReason;
15use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS;
16use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
17use crate::ln::msgs::{self, DecodeError};
18use crate::offers::invoice_request::InvoiceRequest;
19use crate::routing::gossip::NetworkUpdate;
20use crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters, TrampolineHop};
21use crate::sign::{NodeSigner, Recipient};
22use crate::types::features::{ChannelFeatures, NodeFeatures};
23use crate::types::payment::{PaymentHash, PaymentPreimage};
24use crate::util::errors::APIError;
25use crate::util::logger::Logger;
26use crate::util::ser::{
27 LengthCalculatingWriter, Readable, ReadableArgs, VecWriter, Writeable, Writer,
28};
29
30use bitcoin::hashes::cmp::fixed_time_eq;
31use bitcoin::hashes::hmac::{Hmac, HmacEngine};
32use bitcoin::hashes::sha256::Hash as Sha256;
33use bitcoin::hashes::{Hash, HashEngine};
34
35use bitcoin::secp256k1;
36use bitcoin::secp256k1::ecdh::SharedSecret;
37use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
38
39use crate::io::{Cursor, Read};
40use core::ops::Deref;
41
42#[allow(unused_imports)]
43use crate::prelude::*;
44
45const DEFAULT_MIN_FAILURE_PACKET_LEN: usize = 256;
46
47pub(crate) const HOLD_TIME_UNIT_MILLIS: u128 = 100;
49
50pub(crate) struct OnionKeys {
51 #[cfg(test)]
52 pub(crate) shared_secret: SharedSecret,
53 #[cfg(test)]
54 pub(crate) blinding_factor: [u8; 32],
55 pub(crate) ephemeral_pubkey: PublicKey,
56 pub(crate) rho: [u8; 32],
57 pub(crate) mu: [u8; 32],
58}
59
60#[inline]
61pub(crate) fn gen_rho_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] {
62 assert_eq!(shared_secret.len(), 32);
63 let mut hmac = HmacEngine::<Sha256>::new(b"rho");
64 hmac.input(&shared_secret);
65 Hmac::from_engine(hmac).to_byte_array()
66}
67
68#[inline]
69pub(crate) fn gen_rho_mu_from_shared_secret(shared_secret: &[u8]) -> ([u8; 32], [u8; 32]) {
70 assert_eq!(shared_secret.len(), 32);
71 let mut engine_rho = HmacEngine::<Sha256>::new(b"rho");
72 engine_rho.input(&shared_secret);
73 let hmac_rho = Hmac::from_engine(engine_rho).to_byte_array();
74
75 let mut engine_mu = HmacEngine::<Sha256>::new(b"mu");
76 engine_mu.input(&shared_secret);
77 let hmac_mu = Hmac::from_engine(engine_mu).to_byte_array();
78
79 (hmac_rho, hmac_mu)
80}
81
82#[inline]
83pub(super) fn gen_um_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] {
84 assert_eq!(shared_secret.len(), 32);
85 let mut hmac = HmacEngine::<Sha256>::new(b"um");
86 hmac.input(&shared_secret);
87 Hmac::from_engine(hmac).to_byte_array()
88}
89
90#[inline]
91pub(super) fn gen_ammag_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] {
92 assert_eq!(shared_secret.len(), 32);
93 let mut hmac = HmacEngine::<Sha256>::new(b"ammag");
94 hmac.input(&shared_secret);
95 Hmac::from_engine(hmac).to_byte_array()
96}
97
98#[inline]
99pub(super) fn gen_ammagext_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] {
100 assert_eq!(shared_secret.len(), 32);
101 let mut hmac = HmacEngine::<Sha256>::new(b"ammagext");
102 hmac.input(&shared_secret);
103 Hmac::from_engine(hmac).to_byte_array()
104}
105
106#[cfg(test)]
107#[inline]
108pub(super) fn gen_pad_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] {
109 assert_eq!(shared_secret.len(), 32);
110 let mut hmac = HmacEngine::<Sha256>::new(b"pad");
111 hmac.input(&shared_secret);
112 Hmac::from_engine(hmac).to_byte_array()
113}
114
115pub(crate) fn next_hop_pubkey<T: secp256k1::Verification>(
117 secp_ctx: &Secp256k1<T>, curr_pubkey: PublicKey, shared_secret: &[u8],
118) -> Result<PublicKey, secp256k1::Error> {
119 let blinding_factor = {
120 let mut sha = Sha256::engine();
121 sha.input(&curr_pubkey.serialize()[..]);
122 sha.input(shared_secret);
123 Sha256::from_engine(sha).to_byte_array()
124 };
125
126 curr_pubkey.mul_tweak(secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap())
127}
128
129trait HopInfo {
130 fn node_pubkey(&self) -> &PublicKey;
131}
132
133trait PathHop {
134 type HopId;
135 fn hop_id(&self) -> Self::HopId;
136 fn fee_msat(&self) -> u64;
137 fn cltv_expiry_delta(&self) -> u32;
138}
139
140impl HopInfo for RouteHop {
141 fn node_pubkey(&self) -> &PublicKey {
142 &self.pubkey
143 }
144}
145
146impl<'a> PathHop for &'a RouteHop {
147 type HopId = u64; fn hop_id(&self) -> Self::HopId {
150 self.short_channel_id
151 }
152
153 fn fee_msat(&self) -> u64 {
154 self.fee_msat
155 }
156
157 fn cltv_expiry_delta(&self) -> u32 {
158 self.cltv_expiry_delta
159 }
160}
161
162impl HopInfo for TrampolineHop {
163 fn node_pubkey(&self) -> &PublicKey {
164 &self.pubkey
165 }
166}
167
168impl<'a> PathHop for &'a TrampolineHop {
169 type HopId = PublicKey;
170
171 fn hop_id(&self) -> Self::HopId {
172 self.pubkey
173 }
174
175 fn fee_msat(&self) -> u64 {
176 self.fee_msat
177 }
178
179 fn cltv_expiry_delta(&self) -> u32 {
180 self.cltv_expiry_delta
181 }
182}
183
184trait OnionPayload<'a, 'b> {
185 type PathHopForId: PathHop + 'b;
186 type ReceiveType: OnionPayload<'a, 'b>;
187 fn new_forward(
188 hop_id: <<Self as OnionPayload<'a, 'b>>::PathHopForId as PathHop>::HopId,
189 amt_to_forward: u64, outgoing_cltv_value: u32,
190 ) -> Self;
191 fn new_receive(
192 recipient_onion: &'a RecipientOnionFields, keysend_preimage: Option<PaymentPreimage>,
193 sender_intended_htlc_amt_msat: u64, total_msat: u64, cltv_expiry_height: u32,
194 ) -> Result<Self::ReceiveType, APIError>;
195 fn new_blinded_forward(
196 encrypted_tlvs: &'a Vec<u8>, intro_node_blinding_point: Option<PublicKey>,
197 ) -> Self;
198 fn new_blinded_receive(
199 sender_intended_htlc_amt_msat: u64, total_msat: u64, cltv_expiry_height: u32,
200 encrypted_tlvs: &'a Vec<u8>, intro_node_blinding_point: Option<PublicKey>,
201 keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<&'a InvoiceRequest>,
202 custom_tlvs: &'a Vec<(u64, Vec<u8>)>,
203 ) -> Self;
204 fn new_trampoline_entry(
205 total_msat: u64, amt_to_forward: u64, outgoing_cltv_value: u32,
206 recipient_onion: &'a RecipientOnionFields, packet: msgs::TrampolineOnionPacket,
207 ) -> Result<Self::ReceiveType, APIError>;
208}
209impl<'a, 'b> OnionPayload<'a, 'b> for msgs::OutboundOnionPayload<'a> {
210 type PathHopForId = &'b RouteHop;
211 type ReceiveType = msgs::OutboundOnionPayload<'a>;
212 fn new_forward(short_channel_id: u64, amt_to_forward: u64, outgoing_cltv_value: u32) -> Self {
213 Self::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value }
214 }
215 fn new_receive(
216 recipient_onion: &'a RecipientOnionFields, keysend_preimage: Option<PaymentPreimage>,
217 sender_intended_htlc_amt_msat: u64, total_msat: u64, cltv_expiry_height: u32,
218 ) -> Result<Self::ReceiveType, APIError> {
219 Ok(Self::Receive {
220 payment_data: recipient_onion
221 .payment_secret
222 .map(|payment_secret| msgs::FinalOnionHopData { payment_secret, total_msat }),
223 payment_metadata: recipient_onion.payment_metadata.as_ref(),
224 keysend_preimage,
225 custom_tlvs: &recipient_onion.custom_tlvs,
226 sender_intended_htlc_amt_msat,
227 cltv_expiry_height,
228 })
229 }
230 fn new_blinded_forward(
231 encrypted_tlvs: &'a Vec<u8>, intro_node_blinding_point: Option<PublicKey>,
232 ) -> Self {
233 Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point }
234 }
235 fn new_blinded_receive(
236 sender_intended_htlc_amt_msat: u64, total_msat: u64, cltv_expiry_height: u32,
237 encrypted_tlvs: &'a Vec<u8>, intro_node_blinding_point: Option<PublicKey>,
238 keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<&'a InvoiceRequest>,
239 custom_tlvs: &'a Vec<(u64, Vec<u8>)>,
240 ) -> Self {
241 Self::BlindedReceive {
242 sender_intended_htlc_amt_msat,
243 total_msat,
244 cltv_expiry_height,
245 encrypted_tlvs,
246 intro_node_blinding_point,
247 keysend_preimage,
248 invoice_request,
249 custom_tlvs,
250 }
251 }
252
253 fn new_trampoline_entry(
254 total_msat: u64, amt_to_forward: u64, outgoing_cltv_value: u32,
255 recipient_onion: &'a RecipientOnionFields, packet: msgs::TrampolineOnionPacket,
256 ) -> Result<Self, APIError> {
257 Ok(Self::TrampolineEntrypoint {
258 amt_to_forward,
259 outgoing_cltv_value,
260 multipath_trampoline_data: recipient_onion
261 .payment_secret
262 .map(|payment_secret| msgs::FinalOnionHopData { payment_secret, total_msat }),
263 trampoline_packet: packet,
264 })
265 }
266}
267impl<'a, 'b> OnionPayload<'a, 'b> for msgs::OutboundTrampolinePayload<'a> {
268 type PathHopForId = &'b TrampolineHop;
269 type ReceiveType = msgs::OutboundTrampolinePayload<'a>;
270 fn new_forward(
271 outgoing_node_id: PublicKey, amt_to_forward: u64, outgoing_cltv_value: u32,
272 ) -> Self {
273 Self::Forward { outgoing_node_id, amt_to_forward, outgoing_cltv_value }
274 }
275 fn new_receive(
276 _recipient_onion: &'a RecipientOnionFields, _keysend_preimage: Option<PaymentPreimage>,
277 _sender_intended_htlc_amt_msat: u64, _total_msat: u64, _cltv_expiry_height: u32,
278 ) -> Result<Self::ReceiveType, APIError> {
279 Err(APIError::InvalidRoute {
280 err: "Unblinded receiving is not supported for Trampoline!".to_string(),
281 })
282 }
283 fn new_blinded_forward(
284 encrypted_tlvs: &'a Vec<u8>, intro_node_blinding_point: Option<PublicKey>,
285 ) -> Self {
286 Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point }
287 }
288 fn new_blinded_receive(
289 sender_intended_htlc_amt_msat: u64, total_msat: u64, cltv_expiry_height: u32,
290 encrypted_tlvs: &'a Vec<u8>, intro_node_blinding_point: Option<PublicKey>,
291 keysend_preimage: Option<PaymentPreimage>, _invoice_request: Option<&'a InvoiceRequest>,
292 custom_tlvs: &'a Vec<(u64, Vec<u8>)>,
293 ) -> Self {
294 Self::BlindedReceive {
295 sender_intended_htlc_amt_msat,
296 total_msat,
297 cltv_expiry_height,
298 encrypted_tlvs,
299 intro_node_blinding_point,
300 keysend_preimage,
301 custom_tlvs,
302 }
303 }
304
305 fn new_trampoline_entry(
306 _total_msat: u64, _amt_to_forward: u64, _outgoing_cltv_value: u32,
307 _recipient_onion: &'a RecipientOnionFields, _packet: msgs::TrampolineOnionPacket,
308 ) -> Result<Self::ReceiveType, APIError> {
309 Err(APIError::InvalidRoute {
310 err: "Trampoline onions cannot contain Trampoline entrypoints!".to_string(),
311 })
312 }
313}
314
315fn construct_onion_keys_generic<'a, T, H>(
316 secp_ctx: &'a Secp256k1<T>, hops: &'a [H], blinded_tail: Option<&'a BlindedTail>,
317 session_priv: &SecretKey,
318) -> impl Iterator<Item = (SharedSecret, [u8; 32], PublicKey, Option<&'a H>, usize)> + 'a
319where
320 T: secp256k1::Signing,
321 H: HopInfo,
322{
323 let mut blinded_priv = session_priv.clone();
324 let mut blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv);
325
326 let unblinded_hops = hops.iter().map(|h| (h.node_pubkey(), Some(h)));
327 let blinded_pubkeys = blinded_tail
328 .map(|t| t.hops.iter())
329 .unwrap_or([].iter())
330 .skip(1) .map(|h| (&h.blinded_node_id, None));
332
333 unblinded_hops.chain(blinded_pubkeys).enumerate().map(move |(idx, (pubkey, route_hop_opt))| {
334 let shared_secret = SharedSecret::new(pubkey, &blinded_priv);
335
336 let mut sha = Sha256::engine();
337 sha.input(&blinded_pub.serialize()[..]);
338 sha.input(shared_secret.as_ref());
339 let blinding_factor = Sha256::from_engine(sha).to_byte_array();
340
341 let ephemeral_pubkey = blinded_pub;
342
343 blinded_priv = blinded_priv
344 .mul_tweak(&Scalar::from_be_bytes(blinding_factor).expect("You broke SHA-256"))
345 .expect("Blinding are never invalid as we picked the starting private key randomly");
346 blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv);
347
348 (shared_secret, blinding_factor, ephemeral_pubkey, route_hop_opt, idx)
349 })
350}
351
352pub(super) fn construct_onion_keys<T: secp256k1::Signing>(
354 secp_ctx: &Secp256k1<T>, path: &Path, session_priv: &SecretKey,
355) -> Vec<OnionKeys> {
356 let mut res = Vec::with_capacity(path.hops.len());
357
358 let blinded_tail = path.blinded_tail.as_ref().and_then(|t| {
359 if !t.trampoline_hops.is_empty() {
360 return None;
361 }
362 Some(t)
363 });
364 let iter = construct_onion_keys_generic(secp_ctx, &path.hops, blinded_tail, session_priv);
365 for (shared_secret, _blinding_factor, ephemeral_pubkey, _, _) in iter {
366 let (rho, mu) = gen_rho_mu_from_shared_secret(shared_secret.as_ref());
367
368 res.push(OnionKeys {
369 #[cfg(test)]
370 shared_secret,
371 #[cfg(test)]
372 blinding_factor: _blinding_factor,
373 ephemeral_pubkey,
374 rho,
375 mu,
376 });
377 }
378
379 res
380}
381
382pub(super) fn construct_trampoline_onion_keys<T: secp256k1::Signing>(
384 secp_ctx: &Secp256k1<T>, blinded_tail: &BlindedTail, session_priv: &SecretKey,
385) -> Vec<OnionKeys> {
386 let mut res = Vec::with_capacity(blinded_tail.trampoline_hops.len());
387
388 let hops = &blinded_tail.trampoline_hops;
389 let iter = construct_onion_keys_generic(secp_ctx, &hops, Some(blinded_tail), session_priv);
390 for (shared_secret, _blinding_factor, ephemeral_pubkey, _, _) in iter {
391 let (rho, mu) = gen_rho_mu_from_shared_secret(shared_secret.as_ref());
392
393 res.push(OnionKeys {
394 #[cfg(test)]
395 shared_secret,
396 #[cfg(test)]
397 blinding_factor: _blinding_factor,
398 ephemeral_pubkey,
399 rho,
400 mu,
401 });
402 }
403
404 res
405}
406
407pub(super) fn build_trampoline_onion_payloads<'a>(
408 blinded_tail: &'a BlindedTail, total_msat: u64, recipient_onion: &'a RecipientOnionFields,
409 starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>,
410) -> Result<(Vec<msgs::OutboundTrampolinePayload<'a>>, u64, u32), APIError> {
411 let mut res: Vec<msgs::OutboundTrampolinePayload> =
412 Vec::with_capacity(blinded_tail.trampoline_hops.len() + blinded_tail.hops.len());
413 let blinded_tail_with_hop_iter = BlindedTailDetails::DirectEntry {
414 hops: blinded_tail.hops.iter(),
415 blinding_point: blinded_tail.blinding_point,
416 final_value_msat: blinded_tail.final_value_msat,
417 excess_final_cltv_expiry_delta: blinded_tail.excess_final_cltv_expiry_delta,
418 };
419
420 let (value_msat, cltv) = build_onion_payloads_callback(
421 blinded_tail.trampoline_hops.iter(),
422 Some(blinded_tail_with_hop_iter),
423 total_msat,
424 recipient_onion,
425 starting_htlc_offset,
426 keysend_preimage,
427 None,
428 |action, payload| match action {
429 PayloadCallbackAction::PushBack => res.push(payload),
430 PayloadCallbackAction::PushFront => res.insert(0, payload),
431 },
432 )?;
433 Ok((res, value_msat, cltv))
434}
435
436pub(super) fn build_onion_payloads<'a>(
438 path: &'a Path, total_msat: u64, recipient_onion: &'a RecipientOnionFields,
439 starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>,
440 invoice_request: Option<&'a InvoiceRequest>,
441 trampoline_packet: Option<msgs::TrampolineOnionPacket>,
442) -> Result<(Vec<msgs::OutboundOnionPayload<'a>>, u64, u32), APIError> {
443 let mut res: Vec<msgs::OutboundOnionPayload> = Vec::with_capacity(
444 path.hops.len() + path.blinded_tail.as_ref().map_or(0, |t| t.hops.len()),
445 );
446
447 let blinded_tail_with_hop_iter = path.blinded_tail.as_ref().map(|bt| {
451 if let Some(trampoline_packet) = trampoline_packet {
452 return BlindedTailDetails::TrampolineEntry {
453 trampoline_packet,
454 final_value_msat: bt.final_value_msat,
455 };
456 }
457 BlindedTailDetails::DirectEntry {
458 hops: bt.hops.iter(),
459 blinding_point: bt.blinding_point,
460 final_value_msat: bt.final_value_msat,
461 excess_final_cltv_expiry_delta: bt.excess_final_cltv_expiry_delta,
462 }
463 });
464
465 let (value_msat, cltv) = build_onion_payloads_callback(
466 path.hops.iter(),
467 blinded_tail_with_hop_iter,
468 total_msat,
469 recipient_onion,
470 starting_htlc_offset,
471 keysend_preimage,
472 invoice_request,
473 |action, payload| match action {
474 PayloadCallbackAction::PushBack => res.push(payload),
475 PayloadCallbackAction::PushFront => res.insert(0, payload),
476 },
477 )?;
478 Ok((res, value_msat, cltv))
479}
480
481enum BlindedTailDetails<'a, I: Iterator<Item = &'a BlindedHop>> {
482 DirectEntry {
483 hops: I,
484 blinding_point: PublicKey,
485 final_value_msat: u64,
486 excess_final_cltv_expiry_delta: u32,
487 },
488 TrampolineEntry {
489 trampoline_packet: msgs::TrampolineOnionPacket,
490 final_value_msat: u64,
491 },
492}
493
494enum PayloadCallbackAction {
495 PushBack,
496 PushFront,
497}
498fn build_onion_payloads_callback<'a, 'b, H, B, F, OP>(
499 hops: H, mut blinded_tail: Option<BlindedTailDetails<'a, B>>, total_msat: u64,
500 recipient_onion: &'a RecipientOnionFields, starting_htlc_offset: u32,
501 keysend_preimage: &Option<PaymentPreimage>, invoice_request: Option<&'a InvoiceRequest>,
502 mut callback: F,
503) -> Result<(u64, u32), APIError>
504where
505 H: DoubleEndedIterator<Item = OP::PathHopForId>,
506 B: ExactSizeIterator<Item = &'a BlindedHop>,
507 F: FnMut(PayloadCallbackAction, OP),
508 OP: OnionPayload<'a, 'b, ReceiveType = OP>,
509{
510 let mut cur_value_msat = 0u64;
511 let mut cur_cltv = starting_htlc_offset;
512 let mut last_hop_id = None;
513
514 for (idx, hop) in hops.rev().enumerate() {
515 let value_msat = if cur_value_msat == 0 { hop.fee_msat() } else { cur_value_msat };
519 let cltv = if cur_cltv == starting_htlc_offset {
520 hop.cltv_expiry_delta().saturating_add(starting_htlc_offset)
521 } else {
522 cur_cltv
523 };
524 if idx == 0 {
525 match blinded_tail.take() {
526 Some(BlindedTailDetails::DirectEntry {
527 blinding_point,
528 hops,
529 final_value_msat,
530 excess_final_cltv_expiry_delta,
531 ..
532 }) => {
533 let mut blinding_point = Some(blinding_point);
534 let hops_len = hops.len();
535 for (i, blinded_hop) in hops.enumerate() {
536 if i == hops_len - 1 {
537 cur_value_msat += final_value_msat;
538 callback(
539 PayloadCallbackAction::PushBack,
540 OP::new_blinded_receive(
541 final_value_msat,
542 total_msat,
543 cur_cltv + excess_final_cltv_expiry_delta,
544 &blinded_hop.encrypted_payload,
545 blinding_point.take(),
546 *keysend_preimage,
547 invoice_request,
548 &recipient_onion.custom_tlvs,
549 ),
550 );
551 } else {
552 callback(
553 PayloadCallbackAction::PushBack,
554 OP::new_blinded_forward(
555 &blinded_hop.encrypted_payload,
556 blinding_point.take(),
557 ),
558 );
559 }
560 }
561 },
562 Some(BlindedTailDetails::TrampolineEntry {
563 trampoline_packet,
564 final_value_msat,
565 }) => {
566 cur_value_msat += final_value_msat;
567 callback(
568 PayloadCallbackAction::PushBack,
569 OP::new_trampoline_entry(
570 total_msat,
571 final_value_msat + hop.fee_msat(),
572 cur_cltv,
573 &recipient_onion,
574 trampoline_packet,
575 )?,
576 );
577 },
578 None => {
579 callback(
580 PayloadCallbackAction::PushBack,
581 OP::new_receive(
582 &recipient_onion,
583 *keysend_preimage,
584 value_msat,
585 total_msat,
586 cltv,
587 )?,
588 );
589 },
590 }
591 } else {
592 let payload = OP::new_forward(
593 last_hop_id.ok_or(APIError::InvalidRoute {
594 err: "Next hop ID must be known for non-final hops".to_string(),
595 })?,
596 value_msat,
597 cltv,
598 );
599 callback(PayloadCallbackAction::PushFront, payload);
600 }
601 cur_value_msat += hop.fee_msat();
602 if cur_value_msat >= 21000000 * 100000000 * 1000 {
603 return Err(APIError::InvalidRoute { err: "Channel fees overflowed?".to_owned() });
604 }
605 cur_cltv = cur_cltv.saturating_add(hop.cltv_expiry_delta() as u32);
606 if cur_cltv >= 500000000 {
607 return Err(APIError::InvalidRoute { err: "Channel CLTV overflowed?".to_owned() });
608 }
609 last_hop_id = Some(hop.hop_id());
610 }
611 Ok((cur_value_msat, cur_cltv))
612}
613
614pub(crate) const MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY: u64 = 100_000_000;
615
616pub(crate) fn set_max_path_length(
617 route_params: &mut RouteParameters, recipient_onion: &RecipientOnionFields,
618 keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<&InvoiceRequest>,
619 best_block_height: u32,
620) -> Result<(), ()> {
621 const PAYLOAD_HMAC_LEN: usize = 32;
622 let unblinded_intermed_payload_len = msgs::OutboundOnionPayload::Forward {
623 short_channel_id: 42,
624 amt_to_forward: TOTAL_BITCOIN_SUPPLY_SATOSHIS,
625 outgoing_cltv_value: route_params.payment_params.max_total_cltv_expiry_delta,
626 }
627 .serialized_length()
628 .saturating_add(PAYLOAD_HMAC_LEN);
629
630 const OVERPAY_ESTIMATE_MULTIPLER: u64 = 3;
631 let final_value_msat_with_overpay_buffer = route_params
632 .final_value_msat
633 .saturating_mul(OVERPAY_ESTIMATE_MULTIPLER)
634 .clamp(MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, 0x1000_0000);
635
636 let blinded_tail_opt = route_params
637 .payment_params
638 .payee
639 .blinded_route_hints()
640 .iter()
641 .max_by_key(|path| path.inner_blinded_path().serialized_length())
642 .map(|largest_path| BlindedTailDetails::DirectEntry {
643 hops: largest_path.blinded_hops().iter(),
644 blinding_point: largest_path.blinding_point(),
645 final_value_msat: final_value_msat_with_overpay_buffer,
646 excess_final_cltv_expiry_delta: 0,
647 });
648
649 let cltv_expiry_delta =
650 core::cmp::min(route_params.payment_params.max_total_cltv_expiry_delta, 0x1000_0000);
651 let unblinded_route_hop = RouteHop {
652 pubkey: PublicKey::from_slice(&[2; 33]).unwrap(),
653 node_features: NodeFeatures::empty(),
654 short_channel_id: 42,
655 channel_features: ChannelFeatures::empty(),
656 fee_msat: final_value_msat_with_overpay_buffer,
657 cltv_expiry_delta,
658 maybe_announced_channel: false,
659 };
660 let mut num_reserved_bytes: usize = 0;
661 let build_payloads_res = build_onion_payloads_callback(
662 core::iter::once(&unblinded_route_hop),
663 blinded_tail_opt,
664 final_value_msat_with_overpay_buffer,
665 &recipient_onion,
666 best_block_height,
667 &keysend_preimage,
668 invoice_request,
669 |_, payload: msgs::OutboundOnionPayload| {
670 num_reserved_bytes = num_reserved_bytes
671 .saturating_add(payload.serialized_length())
672 .saturating_add(PAYLOAD_HMAC_LEN);
673 },
674 );
675 debug_assert!(build_payloads_res.is_ok());
676
677 let max_path_length = 1300usize
678 .checked_sub(num_reserved_bytes)
679 .map(|p| p / unblinded_intermed_payload_len)
680 .and_then(|l| u8::try_from(l.saturating_add(1)).ok())
681 .ok_or(())?;
682
683 route_params.payment_params.max_path_length =
684 core::cmp::min(max_path_length, route_params.payment_params.max_path_length);
685 Ok(())
686}
687
688pub(crate) const ONION_DATA_LEN: usize = 20 * 65;
691
692#[inline]
693fn shift_slice_right(arr: &mut [u8], amt: usize) {
694 for i in (amt..arr.len()).rev() {
695 arr[i] = arr[i - amt];
696 }
697 for i in 0..amt {
698 arr[i] = 0;
699 }
700}
701
702pub(super) fn construct_onion_packet(
703 payloads: Vec<msgs::OutboundOnionPayload>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32],
704 associated_data: &PaymentHash,
705) -> Result<msgs::OnionPacket, ()> {
706 let mut packet_data = [0; ONION_DATA_LEN];
707
708 let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
709 chacha.process(&[0; ONION_DATA_LEN], &mut packet_data);
710
711 debug_assert_eq!(payloads.len(), onion_keys.len(), "Payloads and keys must have equal lengths");
712
713 let packet = FixedSizeOnionPacket(packet_data);
714 construct_onion_packet_with_init_noise::<_, _>(
715 payloads,
716 onion_keys,
717 packet,
718 Some(associated_data),
719 )
720}
721
722pub(super) fn construct_trampoline_onion_packet(
723 payloads: Vec<msgs::OutboundTrampolinePayload>, onion_keys: Vec<OnionKeys>,
724 prng_seed: [u8; 32], associated_data: &PaymentHash, length: Option<u16>,
725) -> Result<msgs::TrampolineOnionPacket, ()> {
726 let minimum_packet_length = payloads.iter().map(|p| p.serialized_length() + 32).sum();
727
728 debug_assert!(
729 minimum_packet_length < ONION_DATA_LEN,
730 "Trampoline onion packet must be smaller than outer onion"
731 );
732 if minimum_packet_length >= ONION_DATA_LEN {
733 return Err(());
734 }
735
736 let packet_length = length.map(|l| usize::from(l)).unwrap_or(minimum_packet_length);
737 debug_assert!(
738 packet_length >= minimum_packet_length,
739 "Packet length cannot be smaller than the payloads require."
740 );
741 if packet_length < minimum_packet_length {
742 return Err(());
743 }
744
745 let mut packet_data = vec![0u8; packet_length];
746 let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
747 chacha.process_in_place(&mut packet_data);
748
749 construct_onion_packet_with_init_noise::<_, _>(
750 payloads,
751 onion_keys,
752 packet_data,
753 Some(associated_data),
754 )
755}
756
757#[cfg(test)]
758pub(super) fn construct_onion_packet_with_writable_hopdata<HD: Writeable>(
761 payloads: Vec<HD>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32],
762 associated_data: &PaymentHash,
763) -> Result<msgs::OnionPacket, ()> {
764 let mut packet_data = [0; ONION_DATA_LEN];
765
766 let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
767 chacha.process(&[0; ONION_DATA_LEN], &mut packet_data);
768
769 let packet = FixedSizeOnionPacket(packet_data);
770 construct_onion_packet_with_init_noise::<_, _>(
771 payloads,
772 onion_keys,
773 packet,
774 Some(associated_data),
775 )
776}
777
778pub(crate) trait Packet {
782 type Data: AsMut<[u8]>;
783 fn new(pubkey: PublicKey, hop_data: Self::Data, hmac: [u8; 32]) -> Self;
784}
785
786pub(crate) struct FixedSizeOnionPacket(pub(crate) [u8; ONION_DATA_LEN]);
789
790impl AsMut<[u8]> for FixedSizeOnionPacket {
791 fn as_mut(&mut self) -> &mut [u8] {
792 &mut self.0
793 }
794}
795
796pub(crate) fn payloads_serialized_length<HD: Writeable>(payloads: &Vec<HD>) -> usize {
797 payloads.iter().map(|p| p.serialized_length() + 32 ).sum()
798}
799
800pub(crate) fn construct_onion_message_packet<HD: Writeable, P: Packet<Data = Vec<u8>>>(
801 payloads: Vec<HD>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32], packet_data_len: usize,
802) -> Result<P, ()> {
803 let mut packet_data = vec![0; packet_data_len];
804
805 let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
806 chacha.process_in_place(&mut packet_data);
807
808 construct_onion_packet_with_init_noise::<_, _>(payloads, onion_keys, packet_data, None)
809}
810
811fn construct_onion_packet_with_init_noise<HD: Writeable, P: Packet>(
812 mut payloads: Vec<HD>, onion_keys: Vec<OnionKeys>, mut packet_data: P::Data,
813 associated_data: Option<&PaymentHash>,
814) -> Result<P, ()> {
815 let filler = {
816 let packet_data = packet_data.as_mut();
817 const ONION_HOP_DATA_LEN: usize = 65; let mut res = Vec::with_capacity(ONION_HOP_DATA_LEN * (payloads.len() - 1));
819
820 let mut pos = 0;
821 for (i, (payload, keys)) in payloads.iter().zip(onion_keys.iter()).enumerate() {
822 let mut chacha = ChaCha20::new(&keys.rho, &[0u8; 8]);
823 for _ in 0..(packet_data.len() - pos) {
825 let mut dummy = [0; 1];
826 chacha.process_in_place(&mut dummy); }
828
829 let mut payload_len = LengthCalculatingWriter(0);
830 payload.write(&mut payload_len).expect("Failed to calculate length");
831 pos += payload_len.0 + 32;
832 if pos > packet_data.len() {
833 return Err(());
834 }
835
836 if i == payloads.len() - 1 {
837 break;
838 }
839
840 res.resize(pos, 0u8);
841 chacha.process_in_place(&mut res);
842 }
843 res
844 };
845
846 let mut hmac_res = [0; 32];
847 for (i, (payload, keys)) in payloads.iter_mut().zip(onion_keys.iter()).rev().enumerate() {
848 let mut payload_len = LengthCalculatingWriter(0);
849 payload.write(&mut payload_len).expect("Failed to calculate length");
850
851 let packet_data = packet_data.as_mut();
852 shift_slice_right(packet_data, payload_len.0 + 32);
853 packet_data[0..payload_len.0].copy_from_slice(&payload.encode()[..]);
854 packet_data[payload_len.0..(payload_len.0 + 32)].copy_from_slice(&hmac_res);
855
856 let mut chacha = ChaCha20::new(&keys.rho, &[0u8; 8]);
857 chacha.process_in_place(packet_data);
858
859 if i == 0 {
860 let stop_index = packet_data.len();
861 let start_index = stop_index.checked_sub(filler.len()).ok_or(())?;
862 packet_data[start_index..stop_index].copy_from_slice(&filler[..]);
863 }
864
865 let mut hmac = HmacEngine::<Sha256>::new(&keys.mu);
866 hmac.input(packet_data);
867 if let Some(associated_data) = associated_data {
868 hmac.input(&associated_data.0[..]);
869 }
870 hmac_res = Hmac::from_engine(hmac).to_byte_array();
871 }
872
873 Ok(P::new(onion_keys.first().unwrap().ephemeral_pubkey, packet_data, hmac_res))
874}
875
876fn crypt_failure_packet(shared_secret: &[u8], packet: &mut OnionErrorPacket) {
878 let ammag = gen_ammag_from_shared_secret(&shared_secret);
879 let mut chacha = ChaCha20::new(&ammag, &[0u8; 8]);
880 chacha.process_in_place(&mut packet.data);
881
882 if let Some(ref mut attribution_data) = packet.attribution_data {
883 attribution_data.crypt(shared_secret);
884 }
885}
886
887#[cfg(test)]
888pub(super) fn test_crypt_failure_packet(shared_secret: &[u8], packet: &mut OnionErrorPacket) {
889 crypt_failure_packet(shared_secret, packet)
890}
891
892fn build_unencrypted_failure_packet(
893 shared_secret: &[u8], failure_reason: LocalHTLCFailureReason, failure_data: &[u8],
894 hold_time: u32, min_packet_len: usize,
895) -> OnionErrorPacket {
896 assert_eq!(shared_secret.len(), 32);
897 assert!(failure_data.len() <= 64531);
898
899 let failure_len = 2 + failure_data.len();
901
902 let pad_len = min_packet_len.saturating_sub(failure_len);
904
905 let total_len = 32 + 2 + failure_len + 2 + pad_len;
907
908 let mut writer = VecWriter(Vec::with_capacity(total_len));
909
910 writer.0.extend_from_slice(&[0; 32]);
912
913 (failure_len as u16).write(&mut writer).unwrap();
915 failure_reason.failure_code().write(&mut writer).unwrap();
916 writer.0.extend_from_slice(&failure_data[..]);
917
918 (pad_len as u16).write(&mut writer).unwrap();
920 writer.0.resize(total_len, 0);
921
922 let um = gen_um_from_shared_secret(&shared_secret);
924 let mut hmac = HmacEngine::<Sha256>::new(&um);
925 hmac.input(&writer.0[32..]);
926 let hmac = Hmac::from_engine(hmac).to_byte_array();
927 writer.0[..32].copy_from_slice(&hmac);
928
929 let mut packet = OnionErrorPacket { data: writer.0, attribution_data: None };
931 update_attribution_data(&mut packet, shared_secret, hold_time);
932
933 packet
934}
935
936fn update_attribution_data(
937 onion_error_packet: &mut OnionErrorPacket, shared_secret: &[u8], hold_time: u32,
938) {
939 let attribution_data =
943 onion_error_packet.attribution_data.get_or_insert(AttributionData::new());
944
945 attribution_data.update(&onion_error_packet.data, shared_secret, hold_time);
946}
947
948pub(super) fn build_failure_packet(
949 shared_secret: &[u8], failure_reason: LocalHTLCFailureReason, failure_data: &[u8],
950 hold_time: u32,
951) -> OnionErrorPacket {
952 let mut onion_error_packet = build_unencrypted_failure_packet(
953 shared_secret,
954 failure_reason,
955 failure_data,
956 hold_time,
957 DEFAULT_MIN_FAILURE_PACKET_LEN,
958 );
959
960 crypt_failure_packet(shared_secret, &mut onion_error_packet);
961
962 onion_error_packet
963}
964
965mod fuzzy_onion_utils {
966 use super::*;
967
968 pub struct DecodedOnionFailure {
969 pub(crate) network_update: Option<NetworkUpdate>,
970 pub(crate) short_channel_id: Option<u64>,
971 pub(crate) payment_failed_permanently: bool,
972 pub(crate) failed_within_blinded_path: bool,
973 #[allow(dead_code)]
974 pub(crate) hold_times: Vec<u32>,
975 #[cfg(any(test, feature = "_test_utils"))]
976 pub(crate) onion_error_code: Option<LocalHTLCFailureReason>,
977 #[cfg(any(test, feature = "_test_utils"))]
978 pub(crate) onion_error_data: Option<Vec<u8>>,
979 #[cfg(test)]
980 pub(crate) attribution_failed_channel: Option<u64>,
981 }
982}
983#[cfg(fuzzing)]
984pub use self::fuzzy_onion_utils::*;
985#[cfg(not(fuzzing))]
986pub(crate) use self::fuzzy_onion_utils::*;
987
988pub fn process_onion_failure<T: secp256k1::Signing, L: Deref>(
989 secp_ctx: &Secp256k1<T>, logger: &L, htlc_source: &HTLCSource,
990 encrypted_packet: OnionErrorPacket,
991) -> DecodedOnionFailure
992where
993 L::Target: Logger,
994{
995 let (path, primary_session_priv) = match htlc_source {
996 HTLCSource::OutboundRoute { ref path, ref session_priv, .. } => (path, session_priv),
997 _ => unreachable!(),
998 };
999
1000 if path.has_trampoline_hops() {
1001 let session_priv_hash = Sha256::hash(&primary_session_priv.secret_bytes()).to_byte_array();
1003 let outer_session_priv =
1004 SecretKey::from_slice(&session_priv_hash[..]).expect("You broke SHA-256!");
1005 process_onion_failure_inner(
1006 secp_ctx,
1007 logger,
1008 path,
1009 &outer_session_priv,
1010 Some(primary_session_priv),
1011 encrypted_packet,
1012 )
1013 } else {
1014 process_onion_failure_inner(
1015 secp_ctx,
1016 logger,
1017 path,
1018 primary_session_priv,
1019 None,
1020 encrypted_packet,
1021 )
1022 }
1023}
1024
1025fn process_onion_failure_inner<T: secp256k1::Signing, L: Deref>(
1028 secp_ctx: &Secp256k1<T>, logger: &L, path: &Path, outer_session_priv: &SecretKey,
1029 inner_session_priv: Option<&SecretKey>, mut encrypted_packet: OnionErrorPacket,
1030) -> DecodedOnionFailure
1031where
1032 L::Target: Logger,
1033{
1034 if encrypted_packet.data.len() < 32 {
1037 log_warn!(
1038 logger,
1039 "Non-attributable failure encountered on route {}",
1040 path.hops.iter().map(|h| h.pubkey.to_string()).collect::<Vec<_>>().join("->")
1041 );
1042
1043 return DecodedOnionFailure {
1046 network_update: None,
1047 short_channel_id: None,
1048 payment_failed_permanently: true,
1049 failed_within_blinded_path: false,
1050 hold_times: Vec::new(),
1051 #[cfg(any(test, feature = "_test_utils"))]
1052 onion_error_code: None,
1053 #[cfg(any(test, feature = "_test_utils"))]
1054 onion_error_data: None,
1055 #[cfg(test)]
1056 attribution_failed_channel: None,
1057 };
1058 }
1059
1060 struct FailureLearnings {
1062 network_update: Option<NetworkUpdate>,
1063 short_channel_id: Option<u64>,
1064 payment_failed_permanently: bool,
1065 failed_within_blinded_path: bool,
1066 }
1067 let mut res: Option<FailureLearnings> = None;
1068 let mut _error_code_ret = None;
1069 let mut _error_packet_ret = None;
1070 let mut is_from_final_non_blinded_node = false;
1071 let mut hop_hold_times: Vec<u32> = Vec::new();
1072
1073 enum ErrorHop<'a> {
1074 RouteHop(&'a RouteHop),
1075 TrampolineHop(&'a TrampolineHop),
1076 }
1077
1078 impl<'a> ErrorHop<'a> {
1079 fn pubkey(&self) -> &PublicKey {
1080 match self {
1081 ErrorHop::RouteHop(rh) => rh.node_pubkey(),
1082 ErrorHop::TrampolineHop(th) => th.node_pubkey(),
1083 }
1084 }
1085
1086 fn short_channel_id(&self) -> Option<u64> {
1087 match self {
1088 ErrorHop::RouteHop(rh) => Some(rh.short_channel_id),
1089 ErrorHop::TrampolineHop(_) => None,
1090 }
1091 }
1092 }
1093
1094 let num_blinded_hops = path.blinded_tail.as_ref().map_or(0, |bt| bt.hops.len());
1095
1096 let nontrampoline_bt =
1098 if path.has_trampoline_hops() { None } else { path.blinded_tail.as_ref() };
1099 let nontrampolines =
1100 construct_onion_keys_generic(secp_ctx, &path.hops, nontrampoline_bt, outer_session_priv)
1101 .map(|(shared_secret, _, _, route_hop_option, _)| {
1102 (route_hop_option.map(|rh| ErrorHop::RouteHop(rh)), shared_secret)
1103 });
1104
1105 let trampolines = if path.has_trampoline_hops() {
1106 let blinded_tail = path.blinded_tail.as_ref();
1108 let hops = &blinded_tail.unwrap().trampoline_hops;
1109 let inner_session_priv =
1110 inner_session_priv.expect("Trampoline hops always have an inner session priv");
1111 Some(construct_onion_keys_generic(secp_ctx, hops, blinded_tail, inner_session_priv).map(
1112 |(shared_secret, _, _, route_hop_option, _)| {
1113 (route_hop_option.map(|tram_hop| ErrorHop::TrampolineHop(tram_hop)), shared_secret)
1114 },
1115 ))
1116 } else {
1117 None
1118 };
1119
1120 let attributable_hop_count = usize::min(path.hops.len(), MAX_HOPS);
1123
1124 let mut attribution_failed_channel = None;
1126
1127 let mut iter = nontrampolines.chain(trampolines.into_iter().flatten()).enumerate().peekable();
1129 while let Some((route_hop_idx, (route_hop_option, shared_secret))) = iter.next() {
1130 let route_hop = match route_hop_option.as_ref() {
1131 Some(hop) => hop,
1132 None => {
1133 _error_code_ret = Some(LocalHTLCFailureReason::InvalidOnionBlinding);
1135 _error_packet_ret = Some(vec![0; 32]);
1136 res = Some(FailureLearnings {
1137 network_update: None,
1138 short_channel_id: None,
1139 payment_failed_permanently: false,
1140 failed_within_blinded_path: true,
1141 });
1142 break;
1143 },
1144 };
1145
1146 let next_hop = iter.peek();
1152 is_from_final_non_blinded_node = next_hop.is_none() && num_blinded_hops <= 1;
1153 let failing_route_hop = if is_from_final_non_blinded_node {
1154 route_hop
1155 } else {
1156 match next_hop {
1157 Some((_, (Some(hop), _))) => hop,
1158 _ => {
1159 #[cfg(not(test))]
1161 {
1162 _error_code_ret = Some(LocalHTLCFailureReason::InvalidOnionBlinding);
1163 _error_packet_ret = Some(vec![0; 32]);
1164 }
1165 #[cfg(test)]
1166 {
1167 crypt_failure_packet(shared_secret.as_ref(), &mut encrypted_packet);
1170 let err_packet = msgs::DecodedOnionErrorPacket::read(&mut Cursor::new(
1171 &encrypted_packet.data,
1172 ))
1173 .unwrap();
1174 _error_code_ret = Some(
1175 u16::from_be_bytes(
1176 err_packet.failuremsg.get(0..2).unwrap().try_into().unwrap(),
1177 )
1178 .into(),
1179 );
1180 _error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
1181 }
1182
1183 res = Some(FailureLearnings {
1184 network_update: None,
1185 short_channel_id: None,
1186 payment_failed_permanently: false,
1187 failed_within_blinded_path: true,
1188 });
1189 break;
1190 },
1191 }
1192 };
1193
1194 crypt_failure_packet(shared_secret.as_ref(), &mut encrypted_packet);
1195
1196 let um = gen_um_from_shared_secret(shared_secret.as_ref());
1197
1198 if attribution_failed_channel.is_none() {
1200 if let Some(ref mut attribution_data) = encrypted_packet.attribution_data {
1202 if route_hop_idx < attributable_hop_count {
1205 let position = attributable_hop_count - route_hop_idx - 1;
1211 let res = attribution_data.verify(
1212 &encrypted_packet.data,
1213 shared_secret.as_ref(),
1214 position,
1215 );
1216 match res {
1217 Ok(hold_time) => {
1218 hop_hold_times.push(hold_time);
1219
1220 log_debug!(
1221 logger,
1222 "Htlc hold time at pos {}: {} ms",
1223 route_hop_idx,
1224 (hold_time as u128) * HOLD_TIME_UNIT_MILLIS
1225 );
1226
1227 attribution_data.shift_left();
1229 },
1230 Err(()) => {
1231 attribution_failed_channel = route_hop.short_channel_id();
1235
1236 log_debug!(
1237 logger,
1238 "Invalid failure HMAC in attribution data for node at pos {}",
1239 route_hop_idx
1240 );
1241 },
1242 }
1243 }
1244 } else {
1245 attribution_failed_channel = route_hop.short_channel_id();
1248 }
1249 }
1250
1251 let mut hmac = HmacEngine::<Sha256>::new(&um);
1253 hmac.input(&encrypted_packet.data[32..]);
1254
1255 if &Hmac::from_engine(hmac).to_byte_array() != &encrypted_packet.data[..32] {
1256 continue;
1257 }
1258
1259 let err_packet =
1260 match msgs::DecodedOnionErrorPacket::read(&mut Cursor::new(&encrypted_packet.data)) {
1261 Ok(p) => p,
1262 Err(_) => {
1263 log_warn!(logger, "Unreadable failure from {}", route_hop.pubkey());
1264
1265 let network_update = Some(NetworkUpdate::NodeFailure {
1266 node_id: *route_hop.pubkey(),
1267 is_permanent: true,
1268 });
1269 let short_channel_id = route_hop.short_channel_id();
1270 res = Some(FailureLearnings {
1271 network_update,
1272 short_channel_id,
1273 payment_failed_permanently: is_from_final_non_blinded_node,
1274 failed_within_blinded_path: false,
1275 });
1276 break;
1277 },
1278 };
1279
1280 let error_code_slice = match err_packet.failuremsg.get(0..2) {
1281 Some(s) => s,
1282 None => {
1283 log_warn!(logger, "Missing error code in failure from {}", route_hop.pubkey());
1286
1287 let network_update = Some(NetworkUpdate::NodeFailure {
1288 node_id: *route_hop.pubkey(),
1289 is_permanent: true,
1290 });
1291 let short_channel_id = route_hop.short_channel_id();
1292 res = Some(FailureLearnings {
1293 network_update,
1294 short_channel_id,
1295 payment_failed_permanently: is_from_final_non_blinded_node,
1296 failed_within_blinded_path: false,
1297 });
1298 break;
1299 },
1300 };
1301
1302 let error_code = u16::from_be_bytes(error_code_slice.try_into().expect("len is 2")).into();
1303 _error_code_ret = Some(error_code);
1304 _error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
1305
1306 let (debug_field, debug_field_size) = error_code.get_onion_debug_field();
1307
1308 let payment_failed = error_code.is_recipient_failure() && is_from_final_non_blinded_node;
1310
1311 let mut network_update = None;
1312 let mut short_channel_id = None;
1313
1314 if error_code.is_badonion() {
1315 if let ErrorHop::RouteHop(failing_route_hop) = failing_route_hop {
1323 network_update = Some(NetworkUpdate::ChannelFailure {
1324 short_channel_id: failing_route_hop.short_channel_id,
1325 is_permanent: true,
1326 });
1327 }
1328 } else if error_code.is_node() {
1329 network_update = Some(NetworkUpdate::NodeFailure {
1330 node_id: *route_hop.pubkey(),
1331 is_permanent: error_code.is_permanent(),
1332 });
1333 short_channel_id = route_hop.short_channel_id();
1334 } else if error_code.is_permanent() {
1335 if !payment_failed {
1336 if let ErrorHop::RouteHop(failing_route_hop) = failing_route_hop {
1337 network_update = Some(NetworkUpdate::ChannelFailure {
1338 short_channel_id: failing_route_hop.short_channel_id,
1339 is_permanent: true,
1340 });
1341 }
1342 short_channel_id = failing_route_hop.short_channel_id();
1343 }
1344 } else if error_code.is_temporary() {
1345 if let Some(update_len_slice) =
1346 err_packet.failuremsg.get(debug_field_size + 2..debug_field_size + 4)
1347 {
1348 let update_len =
1349 u16::from_be_bytes(update_len_slice.try_into().expect("len is 2")) as usize;
1350 if err_packet
1351 .failuremsg
1352 .get(debug_field_size + 4..debug_field_size + 4 + update_len)
1353 .is_some()
1354 {
1355 if let ErrorHop::RouteHop(failing_route_hop) = failing_route_hop {
1356 network_update = Some(NetworkUpdate::ChannelFailure {
1357 short_channel_id: failing_route_hop.short_channel_id,
1358 is_permanent: false,
1359 });
1360 }
1361 short_channel_id = failing_route_hop.short_channel_id();
1362 }
1363 }
1364 if network_update.is_none() {
1365 network_update = Some(NetworkUpdate::NodeFailure {
1368 node_id: *route_hop.pubkey(),
1369 is_permanent: true,
1370 });
1371 }
1372 if short_channel_id.is_none() {
1373 short_channel_id = route_hop.short_channel_id();
1374 }
1375 } else if payment_failed {
1376 short_channel_id = match error_code {
1379 LocalHTLCFailureReason::FinalIncorrectCLTVExpiry
1380 | LocalHTLCFailureReason::FinalIncorrectHTLCAmount => route_hop.short_channel_id(),
1381 _ => None,
1382 };
1383 } else {
1384 network_update = Some(NetworkUpdate::NodeFailure {
1387 node_id: *route_hop.pubkey(),
1388 is_permanent: true,
1389 });
1390 short_channel_id = route_hop.short_channel_id()
1391 }
1392
1393 res = Some(FailureLearnings {
1394 network_update,
1395 short_channel_id,
1396 payment_failed_permanently: error_code.is_permanent() && is_from_final_non_blinded_node,
1397 failed_within_blinded_path: false,
1398 });
1399
1400 if debug_field_size > 0 && err_packet.failuremsg.len() >= 4 + debug_field_size {
1401 log_info!(
1402 logger,
1403 "Onion Error[from {}: {:?}({:#x}) {}({})]",
1404 route_hop.pubkey(),
1405 error_code,
1406 error_code.failure_code(),
1407 debug_field,
1408 log_bytes!(&err_packet.failuremsg[4..4 + debug_field_size]),
1409 );
1410 } else {
1411 log_info!(
1412 logger,
1413 "Onion Error[from {}: {:?}({:#x})]",
1414 route_hop.pubkey(),
1415 error_code,
1416 error_code.failure_code(),
1417 );
1418 }
1419
1420 break;
1421 }
1422
1423 if let Some(FailureLearnings {
1424 network_update,
1425 short_channel_id,
1426 payment_failed_permanently,
1427 failed_within_blinded_path,
1428 }) = res
1429 {
1430 DecodedOnionFailure {
1431 network_update,
1432 short_channel_id,
1433 payment_failed_permanently,
1434 failed_within_blinded_path,
1435 hold_times: hop_hold_times,
1436 #[cfg(any(test, feature = "_test_utils"))]
1437 onion_error_code: _error_code_ret,
1438 #[cfg(any(test, feature = "_test_utils"))]
1439 onion_error_data: _error_packet_ret,
1440 #[cfg(test)]
1441 attribution_failed_channel,
1442 }
1443 } else {
1444 log_warn!(
1447 logger,
1448 "Non-attributable failure encountered on route {}. Attributation data failed for channel {}",
1449 path.hops.iter().map(|h| h.pubkey.to_string()).collect::<Vec<_>>().join("->"),
1450 attribution_failed_channel.unwrap_or_default(),
1451 );
1452
1453 DecodedOnionFailure {
1454 network_update: None,
1455 short_channel_id: None,
1456 payment_failed_permanently: is_from_final_non_blinded_node,
1457 failed_within_blinded_path: false,
1458 hold_times: hop_hold_times,
1459 #[cfg(any(test, feature = "_test_utils"))]
1460 onion_error_code: None,
1461 #[cfg(any(test, feature = "_test_utils"))]
1462 onion_error_data: None,
1463 #[cfg(test)]
1464 attribution_failed_channel,
1465 }
1466 }
1467}
1468
1469pub fn decode_fulfill_attribution_data<T: secp256k1::Signing, L: Deref>(
1471 secp_ctx: &Secp256k1<T>, logger: &L, path: &Path, outer_session_priv: &SecretKey,
1472 mut attribution_data: AttributionData,
1473) -> Vec<u32>
1474where
1475 L::Target: Logger,
1476{
1477 let mut hold_times = Vec::new();
1478
1479 let shared_secrets =
1481 construct_onion_keys_generic(secp_ctx, &path.hops, None, outer_session_priv)
1482 .map(|(shared_secret, _, _, _, _)| shared_secret);
1483
1484 let attributable_hop_count = usize::min(path.hops.len(), MAX_HOPS);
1487
1488 for (route_hop_idx, shared_secret) in shared_secrets.enumerate().take(attributable_hop_count) {
1489 attribution_data.crypt(shared_secret.as_ref());
1490
1491 let position = attributable_hop_count - route_hop_idx - 1;
1495 let res = attribution_data.verify(&Vec::new(), shared_secret.as_ref(), position);
1496 match res {
1497 Ok(hold_time) => {
1498 hold_times.push(hold_time);
1499
1500 attribution_data.shift_left();
1502 },
1503 Err(()) => {
1504 log_debug!(
1506 logger,
1507 "Invalid fulfill HMAC in attribution data for node at pos {}",
1508 route_hop_idx
1509 );
1510
1511 break;
1512 },
1513 }
1514 }
1515
1516 hold_times
1517}
1518
1519const BADONION: u16 = 0x8000;
1520const PERM: u16 = 0x4000;
1521const NODE: u16 = 0x2000;
1522const UPDATE: u16 = 0x1000;
1523
1524#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1536pub enum LocalHTLCFailureReason {
1537 TemporaryNodeFailure,
1539 PermanentNodeFailure,
1541 RequiredNodeFeature,
1545 InvalidOnionVersion,
1547 InvalidOnionHMAC,
1549 InvalidOnionKey,
1551 TemporaryChannelFailure,
1553 PermanentChannelFailure,
1555 RequiredChannelFeature,
1557 UnknownNextPeer,
1559 AmountBelowMinimum,
1563 FeeInsufficient,
1567 IncorrectCLTVExpiry,
1574 CLTVExpiryTooSoon,
1576 IncorrectPaymentDetails,
1579 FinalIncorrectCLTVExpiry,
1584 FinalIncorrectHTLCAmount,
1588 ChannelDisabled,
1590 CLTVExpiryTooFar,
1595 InvalidOnionPayload,
1597 MPPTimeout,
1600 InvalidOnionBlinding,
1606 UnknownFailureCode {
1614 code: u16,
1616 },
1617 ForwardExpiryBuffer,
1621 InvalidTrampolineForward,
1623 PaymentClaimBuffer,
1627 DustLimitHolder,
1631 DustLimitCounterparty,
1635 FeeSpikeBuffer,
1639 PrivateChannelForward,
1642 RealSCIDForward,
1646 ChannelNotReady,
1648 InvalidKeysendPreimage,
1650 InvalidTrampolinePayload,
1652 PaymentSecretRequired,
1655 OutgoingCLTVTooSoon,
1658 ChannelClosed,
1661 OnChainTimeout,
1664 ZeroAmount,
1666 HTLCMinimum,
1672 HTLCMaximum,
1679 PeerOffline,
1681 ChannelBalanceOverdrawn,
1683}
1684
1685impl LocalHTLCFailureReason {
1686 pub(super) fn failure_code(&self) -> u16 {
1687 match self {
1688 Self::TemporaryNodeFailure | Self::ForwardExpiryBuffer => NODE | 2,
1689 Self::PermanentNodeFailure => PERM | NODE | 2,
1690 Self::RequiredNodeFeature | Self::PaymentSecretRequired => PERM | NODE | 3,
1691 Self::InvalidOnionVersion => BADONION | PERM | 4,
1692 Self::InvalidOnionHMAC => BADONION | PERM | 5,
1693 Self::InvalidOnionKey => BADONION | PERM | 6,
1694 Self::TemporaryChannelFailure
1695 | Self::DustLimitHolder
1696 | Self::DustLimitCounterparty
1697 | Self::FeeSpikeBuffer
1698 | Self::ChannelNotReady
1699 | Self::ZeroAmount
1700 | Self::HTLCMinimum
1701 | Self::HTLCMaximum
1702 | Self::PeerOffline
1703 | Self::ChannelBalanceOverdrawn => UPDATE | 7,
1704 Self::PermanentChannelFailure | Self::ChannelClosed | Self::OnChainTimeout => PERM | 8,
1705 Self::RequiredChannelFeature => PERM | 9,
1706 Self::UnknownNextPeer
1707 | Self::PrivateChannelForward
1708 | Self::RealSCIDForward
1709 | Self::InvalidTrampolineForward => PERM | 10,
1710 Self::AmountBelowMinimum => UPDATE | 11,
1711 Self::FeeInsufficient => UPDATE | 12,
1712 Self::IncorrectCLTVExpiry => UPDATE | 13,
1713 Self::CLTVExpiryTooSoon | Self::OutgoingCLTVTooSoon => UPDATE | 14,
1714 Self::IncorrectPaymentDetails
1715 | Self::PaymentClaimBuffer
1716 | Self::InvalidKeysendPreimage => PERM | 15,
1717 Self::FinalIncorrectCLTVExpiry => 18,
1718 Self::FinalIncorrectHTLCAmount => 19,
1719 Self::ChannelDisabled => UPDATE | 20,
1720 Self::CLTVExpiryTooFar => 21,
1721 Self::InvalidOnionPayload | Self::InvalidTrampolinePayload => PERM | 22,
1722 Self::MPPTimeout => 23,
1723 Self::InvalidOnionBlinding => BADONION | PERM | 24,
1724 Self::UnknownFailureCode { code } => *code,
1725 }
1726 }
1727
1728 fn get_onion_debug_field(&self) -> (&'static str, usize) {
1730 match self {
1731 Self::InvalidOnionVersion | Self::InvalidOnionHMAC | Self::InvalidOnionKey => {
1732 ("sha256_of_onion", 32)
1733 },
1734 Self::AmountBelowMinimum | Self::FeeInsufficient => ("htlc_msat", 8),
1735 Self::IncorrectCLTVExpiry | Self::FinalIncorrectCLTVExpiry => ("cltv_expiry", 4),
1736 Self::FinalIncorrectHTLCAmount => ("incoming_htlc_msat", 8),
1737 Self::ChannelDisabled => ("flags", 2),
1738 _ => ("", 0),
1739 }
1740 }
1741
1742 pub(super) fn is_temporary(&self) -> bool {
1743 self.failure_code() & UPDATE == UPDATE
1744 }
1745
1746 pub(super) fn is_permanent(&self) -> bool {
1747 self.failure_code() & PERM == PERM
1748 }
1749
1750 fn is_badonion(&self) -> bool {
1751 self.failure_code() & BADONION == BADONION
1752 }
1753
1754 fn is_node(&self) -> bool {
1755 self.failure_code() & NODE == NODE
1756 }
1757
1758 fn is_recipient_failure(&self) -> bool {
1762 self.failure_code() == LocalHTLCFailureReason::IncorrectPaymentDetails.failure_code()
1763 || *self == LocalHTLCFailureReason::FinalIncorrectCLTVExpiry
1764 || *self == LocalHTLCFailureReason::FinalIncorrectHTLCAmount
1765 || *self == LocalHTLCFailureReason::MPPTimeout
1766 }
1767}
1768
1769macro_rules! impl_from_u16_for_htlc_reason {
1770 ($enum:ident, [$($variant:ident),* $(,)?]) => {
1771 impl From<u16> for $enum {
1772 fn from(value: u16) -> Self {
1773 $(
1774 if value == $enum::$variant.failure_code() {
1775 return $enum::$variant;
1776 }
1777 )*
1778 $enum::UnknownFailureCode { code: value }
1779 }
1780 }
1781 };
1782}
1783
1784impl_from_u16_for_htlc_reason!(
1786 LocalHTLCFailureReason,
1787 [
1788 TemporaryNodeFailure,
1789 PermanentNodeFailure,
1790 RequiredNodeFeature,
1791 InvalidOnionVersion,
1792 InvalidOnionHMAC,
1793 InvalidOnionKey,
1794 TemporaryChannelFailure,
1795 PermanentChannelFailure,
1796 RequiredChannelFeature,
1797 UnknownNextPeer,
1798 AmountBelowMinimum,
1799 FeeInsufficient,
1800 IncorrectCLTVExpiry,
1801 CLTVExpiryTooSoon,
1802 IncorrectPaymentDetails,
1803 FinalIncorrectCLTVExpiry,
1804 FinalIncorrectHTLCAmount,
1805 ChannelDisabled,
1806 CLTVExpiryTooFar,
1807 InvalidOnionPayload,
1808 MPPTimeout,
1809 InvalidOnionBlinding,
1810 ]
1811);
1812
1813macro_rules! ser_failure_reasons {
1814 ($(($idx: expr, $name: ident)),*) => {
1815 impl Readable for LocalHTLCFailureReason {
1816 fn read<R: Read>(r: &mut R) -> Result<LocalHTLCFailureReason, DecodeError> {
1817 let code: u16 = Readable::read(r)?;
1818 let reason: u8 = Readable::read(r)?;
1819 read_tlv_fields!(r, {});
1820 match reason {
1821 $($idx => Ok(LocalHTLCFailureReason::$name),)*
1822 _ => Ok(code.into()),
1823 }
1824 }
1825 }
1826 impl Writeable for LocalHTLCFailureReason {
1827 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), bitcoin::io::Error> {
1828 self.failure_code().write(writer)?;
1829 let reason: u8 = match self {
1830 $(LocalHTLCFailureReason::$name => $idx,)*
1831 LocalHTLCFailureReason::UnknownFailureCode { .. } => 0xff,
1832 };
1833 reason.write(writer)?;
1834 write_tlv_fields!(writer, {});
1835 Ok(())
1836 }
1837 }
1838 }
1839}
1840
1841ser_failure_reasons!(
1842 (1, TemporaryNodeFailure),
1843 (2, PermanentNodeFailure),
1844 (3, RequiredNodeFeature),
1845 (4, InvalidOnionVersion),
1846 (5, InvalidOnionHMAC),
1847 (6, InvalidOnionKey),
1848 (7, TemporaryChannelFailure),
1849 (8, PermanentChannelFailure),
1850 (9, RequiredChannelFeature),
1851 (10, UnknownNextPeer),
1852 (11, AmountBelowMinimum),
1853 (12, FeeInsufficient),
1854 (13, IncorrectCLTVExpiry),
1855 (14, CLTVExpiryTooSoon),
1856 (15, IncorrectPaymentDetails),
1857 (16, FinalIncorrectCLTVExpiry),
1858 (17, FinalIncorrectHTLCAmount),
1859 (18, ChannelDisabled),
1860 (19, CLTVExpiryTooFar),
1861 (20, InvalidOnionPayload),
1862 (21, MPPTimeout),
1863 (22, InvalidOnionBlinding),
1864 (23, ForwardExpiryBuffer),
1865 (24, InvalidTrampolineForward),
1866 (25, PaymentClaimBuffer),
1867 (26, DustLimitHolder),
1868 (27, DustLimitCounterparty),
1869 (28, FeeSpikeBuffer),
1870 (29, PrivateChannelForward),
1871 (30, RealSCIDForward),
1872 (31, ChannelNotReady),
1873 (32, InvalidKeysendPreimage),
1874 (33, InvalidTrampolinePayload),
1875 (34, PaymentSecretRequired),
1876 (35, OutgoingCLTVTooSoon),
1877 (36, ChannelClosed),
1878 (37, OnChainTimeout),
1879 (38, ZeroAmount),
1880 (39, HTLCMinimum),
1881 (40, HTLCMaximum),
1882 (41, PeerOffline),
1883 (42, ChannelBalanceOverdrawn)
1884);
1885
1886impl From<&HTLCFailReason> for HTLCHandlingFailureReason {
1887 fn from(value: &HTLCFailReason) -> Self {
1888 match value.0 {
1889 HTLCFailReasonRepr::LightningError { .. } => HTLCHandlingFailureReason::Downstream,
1890 HTLCFailReasonRepr::Reason { failure_reason, .. } => {
1891 HTLCHandlingFailureReason::Local { reason: failure_reason }
1892 },
1893 }
1894 }
1895}
1896
1897#[derive(Clone)] #[cfg_attr(test, derive(PartialEq))]
1899pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
1900
1901#[derive(Clone)] #[cfg_attr(test, derive(PartialEq))]
1903enum HTLCFailReasonRepr {
1904 LightningError { err: msgs::OnionErrorPacket, hold_time: Option<u32> },
1905 Reason { data: Vec<u8>, failure_reason: LocalHTLCFailureReason },
1906}
1907
1908impl HTLCFailReason {
1909 pub fn set_hold_time(&mut self, hold_time: u32) {
1910 match self.0 {
1911 HTLCFailReasonRepr::LightningError { hold_time: ref mut current_hold_time, .. } => {
1912 *current_hold_time = Some(hold_time);
1913 },
1914 _ => {},
1915 }
1916 }
1917}
1918
1919impl core::fmt::Debug for HTLCFailReason {
1920 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
1921 match self.0 {
1922 HTLCFailReasonRepr::Reason { ref failure_reason, .. } => {
1923 write!(
1924 f,
1925 "HTLC failure {:?} error code {}",
1926 failure_reason,
1927 failure_reason.failure_code()
1928 )
1929 },
1930 HTLCFailReasonRepr::LightningError { .. } => {
1931 write!(f, "pre-built LightningError")
1932 },
1933 }
1934 }
1935}
1936
1937impl Writeable for HTLCFailReason {
1938 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), crate::io::Error> {
1939 self.0.write(writer)
1940 }
1941}
1942impl Readable for HTLCFailReason {
1943 fn read<R: Read>(reader: &mut R) -> Result<Self, msgs::DecodeError> {
1944 Ok(Self(Readable::read(reader)?))
1945 }
1946}
1947
1948impl_writeable_tlv_based_enum!(HTLCFailReasonRepr,
1949 (0, LightningError) => {
1950 (0, data, (legacy, Vec<u8>, |us|
1951 if let &HTLCFailReasonRepr::LightningError { err: msgs::OnionErrorPacket { ref data, .. }, .. } = us {
1952 Some(data)
1953 } else {
1954 None
1955 })
1956 ),
1957 (1, attribution_data, (legacy, AttributionData, |us|
1958 if let &HTLCFailReasonRepr::LightningError { err: msgs::OnionErrorPacket { ref attribution_data, .. }, .. } = us {
1959 attribution_data.as_ref()
1960 } else {
1961 None
1962 })
1963 ),
1964 (3, hold_time, option),
1965 (_unused, err, (static_value, msgs::OnionErrorPacket { data: data.ok_or(DecodeError::InvalidValue)?, attribution_data })),
1966 },
1967 (1, Reason) => {
1968 (0, _failure_code, (legacy, u16,
1969 |r: &HTLCFailReasonRepr| match r {
1970 HTLCFailReasonRepr::LightningError{ .. } => None,
1971 HTLCFailReasonRepr::Reason{ failure_reason, .. } => Some(failure_reason.failure_code())
1972 })),
1973 (1, failure_reason, (default_value, LocalHTLCFailureReason::from(_failure_code.ok_or(DecodeError::InvalidValue)?))),
1976 (2, data, required_vec),
1977 },
1978);
1979
1980impl HTLCFailReason {
1981 pub(super) fn reason(failure_reason: LocalHTLCFailureReason, data: Vec<u8>) -> Self {
1982 match failure_reason {
1983 LocalHTLCFailureReason::TemporaryNodeFailure
1984 | LocalHTLCFailureReason::ForwardExpiryBuffer => debug_assert!(data.is_empty()),
1985 LocalHTLCFailureReason::PermanentNodeFailure => debug_assert!(data.is_empty()),
1986 LocalHTLCFailureReason::RequiredNodeFeature
1987 | LocalHTLCFailureReason::PaymentSecretRequired => debug_assert!(data.is_empty()),
1988 LocalHTLCFailureReason::InvalidOnionVersion => debug_assert_eq!(data.len(), 32),
1989 LocalHTLCFailureReason::InvalidOnionHMAC => debug_assert_eq!(data.len(), 32),
1990 LocalHTLCFailureReason::InvalidOnionKey => debug_assert_eq!(data.len(), 32),
1991 LocalHTLCFailureReason::TemporaryChannelFailure
1992 | LocalHTLCFailureReason::DustLimitHolder
1993 | LocalHTLCFailureReason::DustLimitCounterparty
1994 | LocalHTLCFailureReason::FeeSpikeBuffer
1995 | LocalHTLCFailureReason::ChannelNotReady
1996 | LocalHTLCFailureReason::ZeroAmount
1997 | LocalHTLCFailureReason::HTLCMinimum
1998 | LocalHTLCFailureReason::HTLCMaximum
1999 | LocalHTLCFailureReason::PeerOffline
2000 | LocalHTLCFailureReason::ChannelBalanceOverdrawn => {
2001 debug_assert_eq!(
2002 data.len() - 2,
2003 u16::from_be_bytes(data[0..2].try_into().unwrap()) as usize
2004 )
2005 },
2006 LocalHTLCFailureReason::PermanentChannelFailure
2007 | LocalHTLCFailureReason::OnChainTimeout
2008 | LocalHTLCFailureReason::ChannelClosed => debug_assert!(data.is_empty()),
2009 LocalHTLCFailureReason::RequiredChannelFeature => debug_assert!(data.is_empty()),
2010 LocalHTLCFailureReason::UnknownNextPeer
2011 | LocalHTLCFailureReason::PrivateChannelForward
2012 | LocalHTLCFailureReason::RealSCIDForward
2013 | LocalHTLCFailureReason::InvalidTrampolineForward => debug_assert!(data.is_empty()),
2014 LocalHTLCFailureReason::AmountBelowMinimum => debug_assert_eq!(
2015 data.len() - 2 - 8,
2016 u16::from_be_bytes(data[8..10].try_into().unwrap()) as usize
2017 ),
2018 LocalHTLCFailureReason::FeeInsufficient => debug_assert_eq!(
2019 data.len() - 2 - 8,
2020 u16::from_be_bytes(data[8..10].try_into().unwrap()) as usize
2021 ),
2022 LocalHTLCFailureReason::IncorrectCLTVExpiry => debug_assert_eq!(
2023 data.len() - 2 - 4,
2024 u16::from_be_bytes(data[4..6].try_into().unwrap()) as usize
2025 ),
2026 LocalHTLCFailureReason::CLTVExpiryTooSoon
2027 | LocalHTLCFailureReason::OutgoingCLTVTooSoon => debug_assert_eq!(
2028 data.len() - 2,
2029 u16::from_be_bytes(data[0..2].try_into().unwrap()) as usize
2030 ),
2031 LocalHTLCFailureReason::IncorrectPaymentDetails
2032 | LocalHTLCFailureReason::PaymentClaimBuffer
2033 | LocalHTLCFailureReason::InvalidKeysendPreimage => debug_assert_eq!(data.len(), 12),
2034 LocalHTLCFailureReason::FinalIncorrectCLTVExpiry => debug_assert_eq!(data.len(), 4),
2035 LocalHTLCFailureReason::FinalIncorrectHTLCAmount => debug_assert_eq!(data.len(), 8),
2036 LocalHTLCFailureReason::ChannelDisabled => debug_assert_eq!(
2037 data.len() - 2 - 2,
2038 u16::from_be_bytes(data[2..4].try_into().unwrap()) as usize
2039 ),
2040 LocalHTLCFailureReason::CLTVExpiryTooFar => debug_assert!(data.is_empty()),
2041 LocalHTLCFailureReason::InvalidOnionPayload
2042 | LocalHTLCFailureReason::InvalidTrampolinePayload => debug_assert!(data.len() <= 11),
2043 LocalHTLCFailureReason::MPPTimeout => debug_assert!(data.is_empty()),
2044 LocalHTLCFailureReason::InvalidOnionBlinding => debug_assert_eq!(data.len(), 32),
2045 LocalHTLCFailureReason::UnknownFailureCode { code } => {
2046 if code & BADONION == 0 {
2048 debug_assert!(false, "Unknown failure code: {}", code)
2049 }
2050 },
2051 }
2052
2053 Self(HTLCFailReasonRepr::Reason { data, failure_reason })
2054 }
2055
2056 pub(super) fn from_failure_code(failure_reason: LocalHTLCFailureReason) -> Self {
2057 Self::reason(failure_reason, Vec::new())
2058 }
2059
2060 pub(super) fn from_msg(msg: &msgs::UpdateFailHTLC) -> Self {
2061 Self(HTLCFailReasonRepr::LightningError {
2062 err: OnionErrorPacket {
2063 data: msg.reason.clone(),
2064 attribution_data: msg.attribution_data.clone(),
2065 },
2066 hold_time: None,
2067 })
2068 }
2069
2070 pub(super) fn get_encrypted_failure_packet(
2076 &self, incoming_packet_shared_secret: &[u8; 32], secondary_shared_secret: &Option<[u8; 32]>,
2077 ) -> msgs::OnionErrorPacket {
2078 match self.0 {
2079 HTLCFailReasonRepr::Reason { ref data, ref failure_reason } => {
2080 let hold_time: u32 = 0;
2082
2083 if let Some(secondary_shared_secret) = secondary_shared_secret {
2084 let mut packet = build_failure_packet(
2086 secondary_shared_secret,
2087 *failure_reason,
2088 &data[..],
2089 hold_time,
2090 );
2091
2092 process_failure_packet(&mut packet, incoming_packet_shared_secret, hold_time);
2093 crypt_failure_packet(incoming_packet_shared_secret, &mut packet);
2094
2095 packet
2096 } else {
2097 build_failure_packet(
2098 incoming_packet_shared_secret,
2099 *failure_reason,
2100 &data[..],
2101 hold_time,
2102 )
2103 }
2104 },
2105 HTLCFailReasonRepr::LightningError { ref err, hold_time } => {
2106 let mut err = err.clone();
2107 let hold_time = hold_time.unwrap_or(0);
2108
2109 process_failure_packet(&mut err, incoming_packet_shared_secret, hold_time);
2110 crypt_failure_packet(incoming_packet_shared_secret, &mut err);
2111
2112 err
2113 },
2114 }
2115 }
2116
2117 pub(super) fn decode_onion_failure<T: secp256k1::Signing, L: Deref>(
2118 &self, secp_ctx: &Secp256k1<T>, logger: &L, htlc_source: &HTLCSource,
2119 ) -> DecodedOnionFailure
2120 where
2121 L::Target: Logger,
2122 {
2123 match self.0 {
2124 HTLCFailReasonRepr::LightningError { ref err, .. } => {
2125 process_onion_failure(secp_ctx, logger, &htlc_source, err.clone())
2126 },
2127 #[allow(unused)]
2128 HTLCFailReasonRepr::Reason { ref data, ref failure_reason } => {
2129 if let &HTLCSource::OutboundRoute { ref path, .. } = htlc_source {
2135 DecodedOnionFailure {
2136 network_update: None,
2137 payment_failed_permanently: false,
2138 short_channel_id: Some(path.hops[0].short_channel_id),
2139 failed_within_blinded_path: false,
2140 hold_times: Vec::new(),
2141 #[cfg(any(test, feature = "_test_utils"))]
2142 onion_error_code: Some(*failure_reason),
2143 #[cfg(any(test, feature = "_test_utils"))]
2144 onion_error_data: Some(data.clone()),
2145 #[cfg(test)]
2146 attribution_failed_channel: None,
2147 }
2148 } else {
2149 unreachable!();
2150 }
2151 },
2152 }
2153 }
2154}
2155
2156pub(crate) trait NextPacketBytes: AsMut<[u8]> {
2159 fn new(len: usize) -> Self;
2160}
2161
2162impl NextPacketBytes for FixedSizeOnionPacket {
2163 fn new(_len: usize) -> Self {
2164 Self([0 as u8; ONION_DATA_LEN])
2165 }
2166}
2167
2168impl NextPacketBytes for Vec<u8> {
2169 fn new(len: usize) -> Self {
2170 vec![0 as u8; len]
2171 }
2172}
2173
2174pub(crate) enum Hop {
2176 Forward {
2178 next_hop_data: msgs::InboundOnionForwardPayload,
2180 shared_secret: SharedSecret,
2182 next_hop_hmac: [u8; 32],
2184 new_packet_bytes: [u8; ONION_DATA_LEN],
2186 },
2187 TrampolineForward {
2190 #[allow(unused)]
2191 outer_hop_data: msgs::InboundTrampolineEntrypointPayload,
2192 outer_shared_secret: SharedSecret,
2193 incoming_trampoline_public_key: PublicKey,
2194 trampoline_shared_secret: SharedSecret,
2195 next_trampoline_hop_data: msgs::InboundTrampolineForwardPayload,
2196 next_trampoline_hop_hmac: [u8; 32],
2197 new_trampoline_packet_bytes: Vec<u8>,
2198 },
2199 TrampolineBlindedForward {
2202 outer_hop_data: msgs::InboundTrampolineEntrypointPayload,
2203 outer_shared_secret: SharedSecret,
2204 #[allow(unused)]
2205 incoming_trampoline_public_key: PublicKey,
2206 trampoline_shared_secret: SharedSecret,
2207 next_trampoline_hop_data: msgs::InboundTrampolineBlindedForwardPayload,
2208 next_trampoline_hop_hmac: [u8; 32],
2209 new_trampoline_packet_bytes: Vec<u8>,
2210 },
2211 BlindedForward {
2213 next_hop_data: msgs::InboundOnionBlindedForwardPayload,
2215 shared_secret: SharedSecret,
2217 next_hop_hmac: [u8; 32],
2219 new_packet_bytes: [u8; ONION_DATA_LEN],
2221 },
2222 Receive {
2225 hop_data: msgs::InboundOnionReceivePayload,
2227 shared_secret: SharedSecret,
2229 },
2230 BlindedReceive {
2233 hop_data: msgs::InboundOnionBlindedReceivePayload,
2235 shared_secret: SharedSecret,
2237 },
2238 TrampolineReceive {
2241 #[allow(unused)]
2242 outer_hop_data: msgs::InboundTrampolineEntrypointPayload,
2243 outer_shared_secret: SharedSecret,
2244 trampoline_hop_data: msgs::InboundOnionReceivePayload,
2245 #[allow(unused)]
2246 trampoline_shared_secret: SharedSecret,
2247 },
2248 TrampolineBlindedReceive {
2251 #[allow(unused)]
2252 outer_hop_data: msgs::InboundTrampolineEntrypointPayload,
2253 outer_shared_secret: SharedSecret,
2254 trampoline_hop_data: msgs::InboundOnionBlindedReceivePayload,
2255 #[allow(unused)]
2256 trampoline_shared_secret: SharedSecret,
2257 },
2258}
2259
2260impl Hop {
2261 pub(crate) fn is_intro_node_blinded_forward(&self) -> bool {
2262 match self {
2263 Self::BlindedForward {
2264 next_hop_data:
2265 msgs::InboundOnionBlindedForwardPayload {
2266 intro_node_blinding_point: Some(_), ..
2267 },
2268 ..
2269 } => true,
2270 _ => false,
2271 }
2272 }
2273
2274 pub(crate) fn shared_secret(&self) -> &SharedSecret {
2275 match self {
2276 Hop::Forward { shared_secret, .. } => shared_secret,
2277 Hop::BlindedForward { shared_secret, .. } => shared_secret,
2278 Hop::TrampolineForward { outer_shared_secret, .. } => outer_shared_secret,
2279 Hop::TrampolineBlindedForward { outer_shared_secret, .. } => outer_shared_secret,
2280 Hop::Receive { shared_secret, .. } => shared_secret,
2281 Hop::BlindedReceive { shared_secret, .. } => shared_secret,
2282 Hop::TrampolineReceive { outer_shared_secret, .. } => outer_shared_secret,
2283 Hop::TrampolineBlindedReceive { outer_shared_secret, .. } => outer_shared_secret,
2284 }
2285 }
2286}
2287
2288#[derive(Debug)]
2290pub(crate) enum OnionDecodeErr {
2291 Malformed { err_msg: &'static str, reason: LocalHTLCFailureReason },
2293 Relay {
2298 err_msg: &'static str,
2299 reason: LocalHTLCFailureReason,
2300 shared_secret: SharedSecret,
2301 trampoline_shared_secret: Option<SharedSecret>,
2302 },
2303}
2304
2305pub(crate) fn decode_next_payment_hop<NS: Deref>(
2306 recipient: Recipient, hop_pubkey: &PublicKey, hop_data: &[u8], hmac_bytes: [u8; 32],
2307 payment_hash: PaymentHash, blinding_point: Option<PublicKey>, node_signer: NS,
2308) -> Result<Hop, OnionDecodeErr>
2309where
2310 NS::Target: NodeSigner,
2311{
2312 let blinded_node_id_tweak = blinding_point.map(|bp| {
2313 let blinded_tlvs_ss = node_signer.ecdh(recipient, &bp, None).unwrap().secret_bytes();
2314 let mut hmac = HmacEngine::<Sha256>::new(b"blinded_node_id");
2315 hmac.input(blinded_tlvs_ss.as_ref());
2316 Scalar::from_be_bytes(Hmac::from_engine(hmac).to_byte_array()).unwrap()
2317 });
2318 let shared_secret =
2319 node_signer.ecdh(recipient, hop_pubkey, blinded_node_id_tweak.as_ref()).unwrap();
2320
2321 let decoded_hop: Result<(msgs::InboundOnionPayload, Option<_>), _> = decode_next_hop(
2322 shared_secret.secret_bytes(),
2323 hop_data,
2324 hmac_bytes,
2325 Some(payment_hash),
2326 (blinding_point, &(*node_signer)),
2327 );
2328 match decoded_hop {
2329 Ok((next_hop_data, Some((next_hop_hmac, FixedSizeOnionPacket(new_packet_bytes))))) => {
2330 match next_hop_data {
2331 msgs::InboundOnionPayload::Forward(next_hop_data) => Ok(Hop::Forward {
2332 shared_secret,
2333 next_hop_data,
2334 next_hop_hmac,
2335 new_packet_bytes,
2336 }),
2337 msgs::InboundOnionPayload::BlindedForward(next_hop_data) => {
2338 Ok(Hop::BlindedForward {
2339 shared_secret,
2340 next_hop_data,
2341 next_hop_hmac,
2342 new_packet_bytes,
2343 })
2344 },
2345 _ => {
2346 if blinding_point.is_some() {
2347 return Err(OnionDecodeErr::Malformed {
2348 err_msg:
2349 "Final Node OnionHopData provided for us as an intermediary node",
2350 reason: LocalHTLCFailureReason::InvalidOnionBlinding,
2351 });
2352 }
2353 Err(OnionDecodeErr::Relay {
2354 err_msg: "Final Node OnionHopData provided for us as an intermediary node",
2355 reason: LocalHTLCFailureReason::InvalidOnionPayload,
2356 shared_secret,
2357 trampoline_shared_secret: None,
2358 })
2359 },
2360 }
2361 },
2362 Ok((next_hop_data, None)) => match next_hop_data {
2363 msgs::InboundOnionPayload::Receive(hop_data) => {
2364 Ok(Hop::Receive { shared_secret, hop_data })
2365 },
2366 msgs::InboundOnionPayload::BlindedReceive(hop_data) => {
2367 Ok(Hop::BlindedReceive { shared_secret, hop_data })
2368 },
2369 msgs::InboundOnionPayload::TrampolineEntrypoint(hop_data) => {
2370 let incoming_trampoline_public_key = hop_data.trampoline_packet.public_key;
2371 let trampoline_blinded_node_id_tweak = hop_data.current_path_key.map(|bp| {
2372 let blinded_tlvs_ss =
2373 node_signer.ecdh(recipient, &bp, None).unwrap().secret_bytes();
2374 let mut hmac = HmacEngine::<Sha256>::new(b"blinded_node_id");
2375 hmac.input(blinded_tlvs_ss.as_ref());
2376 Scalar::from_be_bytes(Hmac::from_engine(hmac).to_byte_array()).unwrap()
2377 });
2378 let trampoline_shared_secret = node_signer
2379 .ecdh(
2380 recipient,
2381 &incoming_trampoline_public_key,
2382 trampoline_blinded_node_id_tweak.as_ref(),
2383 )
2384 .unwrap()
2385 .secret_bytes();
2386 let decoded_trampoline_hop: Result<
2387 (msgs::InboundTrampolinePayload, Option<([u8; 32], Vec<u8>)>),
2388 _,
2389 > = decode_next_hop(
2390 trampoline_shared_secret,
2391 &hop_data.trampoline_packet.hop_data,
2392 hop_data.trampoline_packet.hmac,
2393 Some(payment_hash),
2394 (blinding_point, node_signer),
2395 );
2396 match decoded_trampoline_hop {
2397 Ok((
2398 msgs::InboundTrampolinePayload::Forward(trampoline_hop_data),
2399 Some((next_trampoline_hop_hmac, new_trampoline_packet_bytes)),
2400 )) => Ok(Hop::TrampolineForward {
2401 outer_hop_data: hop_data,
2402 outer_shared_secret: shared_secret,
2403 incoming_trampoline_public_key,
2404 trampoline_shared_secret: SharedSecret::from_bytes(
2405 trampoline_shared_secret,
2406 ),
2407 next_trampoline_hop_data: trampoline_hop_data,
2408 next_trampoline_hop_hmac,
2409 new_trampoline_packet_bytes,
2410 }),
2411 Ok((
2412 msgs::InboundTrampolinePayload::BlindedForward(trampoline_hop_data),
2413 Some((next_trampoline_hop_hmac, new_trampoline_packet_bytes)),
2414 )) => Ok(Hop::TrampolineBlindedForward {
2415 outer_hop_data: hop_data,
2416 outer_shared_secret: shared_secret,
2417 incoming_trampoline_public_key,
2418 trampoline_shared_secret: SharedSecret::from_bytes(
2419 trampoline_shared_secret,
2420 ),
2421 next_trampoline_hop_data: trampoline_hop_data,
2422 next_trampoline_hop_hmac,
2423 new_trampoline_packet_bytes,
2424 }),
2425 Ok((msgs::InboundTrampolinePayload::Receive(trampoline_hop_data), None)) => {
2426 Ok(Hop::TrampolineReceive {
2427 outer_hop_data: hop_data,
2428 outer_shared_secret: shared_secret,
2429 trampoline_hop_data,
2430 trampoline_shared_secret: SharedSecret::from_bytes(
2431 trampoline_shared_secret,
2432 ),
2433 })
2434 },
2435 Ok((
2436 msgs::InboundTrampolinePayload::BlindedReceive(trampoline_hop_data),
2437 None,
2438 )) => Ok(Hop::TrampolineBlindedReceive {
2439 outer_hop_data: hop_data,
2440 outer_shared_secret: shared_secret,
2441 trampoline_hop_data,
2442 trampoline_shared_secret: SharedSecret::from_bytes(
2443 trampoline_shared_secret,
2444 ),
2445 }),
2446 Ok((msgs::InboundTrampolinePayload::BlindedForward(hop_data), None)) => {
2447 if hop_data.intro_node_blinding_point.is_some() {
2448 return Err(OnionDecodeErr::Relay {
2449 err_msg: "Non-final intro node Trampoline onion data provided to us as last hop",
2450 reason: LocalHTLCFailureReason::InvalidOnionPayload,
2451 shared_secret,
2452 trampoline_shared_secret: Some(SharedSecret::from_bytes(
2453 trampoline_shared_secret,
2454 )),
2455 });
2456 }
2457 Err(OnionDecodeErr::Malformed {
2458 err_msg: "Non-final Trampoline onion data provided to us as last hop",
2459 reason: LocalHTLCFailureReason::InvalidOnionBlinding,
2460 })
2461 },
2462 Ok((msgs::InboundTrampolinePayload::BlindedReceive(hop_data), Some(_))) => {
2463 if hop_data.intro_node_blinding_point.is_some() {
2464 return Err(OnionDecodeErr::Relay {
2465 err_msg: "Final Trampoline intro node onion data provided to us as intermediate hop",
2466 reason: LocalHTLCFailureReason::InvalidTrampolinePayload,
2467 shared_secret,
2468 trampoline_shared_secret: Some(SharedSecret::from_bytes(
2469 trampoline_shared_secret,
2470 )),
2471 });
2472 }
2473 Err(OnionDecodeErr::Malformed {
2474 err_msg:
2475 "Final Trampoline onion data provided to us as intermediate hop",
2476 reason: LocalHTLCFailureReason::InvalidOnionBlinding,
2477 })
2478 },
2479 Ok((msgs::InboundTrampolinePayload::Forward(_), None)) => {
2480 Err(OnionDecodeErr::Relay {
2481 err_msg: "Non-final Trampoline onion data provided to us as last hop",
2482 reason: LocalHTLCFailureReason::InvalidTrampolinePayload,
2483 shared_secret,
2484 trampoline_shared_secret: Some(SharedSecret::from_bytes(
2485 trampoline_shared_secret,
2486 )),
2487 })
2488 },
2489 Ok((msgs::InboundTrampolinePayload::Receive(_), Some(_))) => {
2490 Err(OnionDecodeErr::Relay {
2491 err_msg:
2492 "Final Trampoline onion data provided to us as intermediate hop",
2493 reason: LocalHTLCFailureReason::InvalidTrampolinePayload,
2494 shared_secret,
2495 trampoline_shared_secret: Some(SharedSecret::from_bytes(
2496 trampoline_shared_secret,
2497 )),
2498 })
2499 },
2500 Err(e) => Err(e),
2501 }
2502 },
2503 _ => {
2504 if blinding_point.is_some() {
2505 return Err(OnionDecodeErr::Malformed {
2506 err_msg: "Intermediate Node OnionHopData provided for us as a final node",
2507 reason: LocalHTLCFailureReason::InvalidOnionBlinding,
2508 });
2509 }
2510 Err(OnionDecodeErr::Relay {
2511 err_msg: "Intermediate Node OnionHopData provided for us as a final node",
2512 reason: LocalHTLCFailureReason::InvalidOnionPayload,
2513 shared_secret,
2514 trampoline_shared_secret: None,
2515 })
2516 },
2517 },
2518 Err(e) => Err(e),
2519 }
2520}
2521
2522pub fn create_payment_onion<T: secp256k1::Signing>(
2525 secp_ctx: &Secp256k1<T>, path: &Path, session_priv: &SecretKey, total_msat: u64,
2526 recipient_onion: &RecipientOnionFields, cur_block_height: u32, payment_hash: &PaymentHash,
2527 keysend_preimage: &Option<PaymentPreimage>, invoice_request: Option<&InvoiceRequest>,
2528 prng_seed: [u8; 32],
2529) -> Result<(msgs::OnionPacket, u64, u32), APIError> {
2530 create_payment_onion_internal(
2531 secp_ctx,
2532 path,
2533 session_priv,
2534 total_msat,
2535 recipient_onion,
2536 cur_block_height,
2537 payment_hash,
2538 keysend_preimage,
2539 invoice_request,
2540 prng_seed,
2541 None,
2542 None,
2543 )
2544}
2545
2546pub(crate) fn create_payment_onion_internal<T: secp256k1::Signing>(
2549 secp_ctx: &Secp256k1<T>, path: &Path, session_priv: &SecretKey, total_msat: u64,
2550 recipient_onion: &RecipientOnionFields, cur_block_height: u32, payment_hash: &PaymentHash,
2551 keysend_preimage: &Option<PaymentPreimage>, invoice_request: Option<&InvoiceRequest>,
2552 prng_seed: [u8; 32], secondary_session_priv: Option<SecretKey>,
2553 secondary_prng_seed: Option<[u8; 32]>,
2554) -> Result<(msgs::OnionPacket, u64, u32), APIError> {
2555 let mut outer_total_msat = total_msat;
2556 let mut outer_starting_htlc_offset = cur_block_height;
2557 let mut outer_session_priv_override = None;
2558 let mut trampoline_packet_option = None;
2559
2560 if let Some(blinded_tail) = &path.blinded_tail {
2561 if !blinded_tail.trampoline_hops.is_empty() {
2562 let trampoline_payloads;
2563 (trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) =
2564 build_trampoline_onion_payloads(
2565 &blinded_tail,
2566 total_msat,
2567 recipient_onion,
2568 cur_block_height,
2569 keysend_preimage,
2570 )?;
2571
2572 let onion_keys =
2573 construct_trampoline_onion_keys(&secp_ctx, &blinded_tail, &session_priv);
2574 let trampoline_packet = construct_trampoline_onion_packet(
2575 trampoline_payloads,
2576 onion_keys,
2577 prng_seed,
2578 payment_hash,
2579 None,
2581 )
2582 .map_err(|_| APIError::InvalidRoute {
2583 err: "Route size too large considering onion data".to_owned(),
2584 })?;
2585
2586 trampoline_packet_option = Some(trampoline_packet);
2587
2588 outer_session_priv_override = Some(secondary_session_priv.unwrap_or_else(|| {
2589 let session_priv_hash = Sha256::hash(&session_priv.secret_bytes()).to_byte_array();
2590 SecretKey::from_slice(&session_priv_hash[..]).expect("You broke SHA-256!")
2591 }));
2592 }
2593 }
2594
2595 let (onion_payloads, htlc_msat, htlc_cltv) = build_onion_payloads(
2596 &path,
2597 outer_total_msat,
2598 recipient_onion,
2599 outer_starting_htlc_offset,
2600 keysend_preimage,
2601 invoice_request,
2602 trampoline_packet_option,
2603 )?;
2604
2605 let outer_session_priv = outer_session_priv_override.as_ref().unwrap_or(session_priv);
2606 let onion_keys = construct_onion_keys(&secp_ctx, &path, outer_session_priv);
2607 let outer_onion_prng_seed = secondary_prng_seed.unwrap_or(prng_seed);
2608 let onion_packet =
2609 construct_onion_packet(onion_payloads, onion_keys, outer_onion_prng_seed, payment_hash)
2610 .map_err(|_| APIError::InvalidRoute {
2611 err: "Route size too large considering onion data".to_owned(),
2612 })?;
2613 Ok((onion_packet, htlc_msat, htlc_cltv))
2614}
2615
2616pub(crate) fn decode_next_untagged_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(
2617 shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], read_args: T,
2618) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> {
2619 decode_next_hop(shared_secret, hop_data, hmac_bytes, None, read_args)
2620}
2621
2622fn decode_next_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(
2623 shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32],
2624 payment_hash: Option<PaymentHash>, read_args: T,
2625) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> {
2626 let (rho, mu) = gen_rho_mu_from_shared_secret(&shared_secret);
2627 let mut hmac = HmacEngine::<Sha256>::new(&mu);
2628 hmac.input(hop_data);
2629 if let Some(tag) = payment_hash {
2630 hmac.input(&tag.0[..]);
2631 }
2632 if !fixed_time_eq(&Hmac::from_engine(hmac).to_byte_array(), &hmac_bytes) {
2633 return Err(OnionDecodeErr::Malformed {
2634 err_msg: "HMAC Check failed",
2635 reason: LocalHTLCFailureReason::InvalidOnionHMAC,
2636 });
2637 }
2638
2639 let mut chacha = ChaCha20::new(&rho, &[0u8; 8]);
2640 let mut chacha_stream = ChaChaReader { chacha: &mut chacha, read: Cursor::new(&hop_data[..]) };
2641 match R::read(&mut chacha_stream, read_args) {
2642 Err(err) => {
2643 let reason = match err {
2644 msgs::DecodeError::UnknownVersion => LocalHTLCFailureReason::InvalidOnionVersion,
2646 msgs::DecodeError::UnknownRequiredFeature
2648 | msgs::DecodeError::InvalidValue
2649 | msgs::DecodeError::ShortRead => LocalHTLCFailureReason::InvalidOnionPayload,
2650 _ => LocalHTLCFailureReason::TemporaryNodeFailure,
2652 };
2653 return Err(OnionDecodeErr::Relay {
2654 err_msg: "Unable to decode our hop data",
2655 reason,
2656 shared_secret: SharedSecret::from_bytes(shared_secret),
2657 trampoline_shared_secret: None,
2658 });
2659 },
2660 Ok(msg) => {
2661 let mut hmac = [0; 32];
2662 if let Err(_) = chacha_stream.read_exact(&mut hmac[..]) {
2663 return Err(OnionDecodeErr::Relay {
2664 err_msg: "Unable to decode our hop data",
2665 reason: LocalHTLCFailureReason::InvalidOnionPayload,
2666 shared_secret: SharedSecret::from_bytes(shared_secret),
2667 trampoline_shared_secret: None,
2668 });
2669 }
2670 if hmac == [0; 32] {
2671 #[cfg(test)]
2672 {
2673 if chacha_stream.read.position() < hop_data.len() as u64 - 64 {
2674 let mut next_bytes = [0; 32];
2682 chacha_stream.read_exact(&mut next_bytes).unwrap();
2683 assert_ne!(next_bytes[..], [0; 32][..]);
2684 chacha_stream.read_exact(&mut next_bytes).unwrap();
2685 assert_ne!(next_bytes[..], [0; 32][..]);
2686 }
2687 }
2688 return Ok((msg, None)); } else {
2690 let mut new_packet_bytes = N::new(hop_data.len());
2691 let read_pos = hop_data.len() - chacha_stream.read.position() as usize;
2692 chacha_stream.read_exact(&mut new_packet_bytes.as_mut()[..read_pos]).unwrap();
2693 #[cfg(debug_assertions)]
2694 {
2695 let mut t = [0; 1];
2700 debug_assert!(chacha_stream.read(&mut t).unwrap() == 0);
2701 }
2702 chacha_stream.chacha.process_in_place(&mut new_packet_bytes.as_mut()[read_pos..]);
2705 return Ok((msg, Some((hmac, new_packet_bytes)))); }
2707 },
2708 }
2709}
2710
2711pub const HOLD_TIME_LEN: usize = 4;
2712pub const MAX_HOPS: usize = 20;
2713pub const HMAC_LEN: usize = 4;
2714
2715pub const HMAC_COUNT: usize = MAX_HOPS * (MAX_HOPS + 1) / 2;
2718
2719#[derive(Clone, Debug, Hash, PartialEq, Eq)]
2720pub struct AttributionData {
2721 pub hold_times: [u8; MAX_HOPS * HOLD_TIME_LEN],
2722 pub hmacs: [u8; HMAC_LEN * HMAC_COUNT],
2723}
2724
2725impl AttributionData {
2726 pub fn new() -> Self {
2727 Self { hold_times: [0; MAX_HOPS * HOLD_TIME_LEN], hmacs: [0; HMAC_LEN * HMAC_COUNT] }
2728 }
2729}
2730
2731impl_writeable!(AttributionData, {
2732 hold_times,
2733 hmacs
2734});
2735
2736impl AttributionData {
2737 pub(crate) fn crypt(&mut self, shared_secret: &[u8]) {
2739 let ammagext = gen_ammagext_from_shared_secret(&shared_secret);
2740 let mut chacha = ChaCha20::new(&ammagext, &[0u8; 8]);
2741 chacha.process_in_place(&mut self.hold_times);
2742 chacha.process_in_place(&mut self.hmacs);
2743 }
2744
2745 pub(crate) fn add_hmacs(&mut self, shared_secret: &[u8], message: &[u8]) {
2747 let um: [u8; 32] = gen_um_from_shared_secret(&shared_secret);
2748
2749 for hmac_idx in 0..MAX_HOPS {
2752 let position: usize = MAX_HOPS - hmac_idx - 1;
2754
2755 let mut hmac_engine = HmacEngine::<Sha256>::new(&um);
2758 hmac_engine.input(&message);
2759 hmac_engine.input(&self.hold_times[..(position + 1) * HOLD_TIME_LEN]);
2760 self.write_downstream_hmacs(position, &mut hmac_engine);
2761
2762 let full_hmac = Hmac::from_engine(hmac_engine).to_byte_array();
2763
2764 let hmac = &full_hmac[..HMAC_LEN];
2767
2768 self.get_hmac_mut(hmac_idx).copy_from_slice(hmac);
2770 }
2771 }
2772
2773 pub fn write_downstream_hmacs(&self, position: usize, w: &mut HmacEngine<Sha256>) {
2776 let mut hmac_idx = MAX_HOPS + MAX_HOPS - position - 1;
2779
2780 for j in 0..position {
2782 w.input(self.get_hmac(hmac_idx));
2783
2784 let block_size = MAX_HOPS - j - 1;
2786
2787 hmac_idx += block_size;
2789 }
2790 }
2791
2792 fn verify(&self, message: &[u8], shared_secret: &[u8], position: usize) -> Result<u32, ()> {
2795 let um = gen_um_from_shared_secret(shared_secret);
2797 let mut hmac = HmacEngine::<Sha256>::new(&um);
2798 hmac.input(&message);
2799 hmac.input(&self.hold_times[..(position + 1) * HOLD_TIME_LEN]);
2800 self.write_downstream_hmacs(position, &mut hmac);
2801 let expected_hmac = &Hmac::from_engine(hmac).to_byte_array()[..HMAC_LEN];
2802
2803 let hmac_idx = MAX_HOPS - position - 1;
2805 let actual_hmac = self.get_hmac(hmac_idx);
2806 if !fixed_time_eq(expected_hmac, actual_hmac) {
2807 return Err(());
2808 }
2809
2810 let hold_time: u32 = u32::from_be_bytes(self.get_hold_time_bytes(0).try_into().unwrap());
2812
2813 Ok(hold_time)
2814 }
2815
2816 fn shift_left(&mut self) {
2819 self.hold_times.copy_within(HOLD_TIME_LEN.., 0);
2821
2822 let mut src_idx = MAX_HOPS;
2824 let mut dest_idx = 1;
2825 let mut copy_len = MAX_HOPS - 1;
2826
2827 for _ in 0..MAX_HOPS - 1 {
2828 self.hmacs.copy_within(
2829 src_idx * HMAC_LEN..(src_idx + copy_len) * HMAC_LEN,
2830 dest_idx * HMAC_LEN,
2831 );
2832
2833 src_idx += copy_len;
2834 dest_idx += copy_len + 1;
2835 copy_len -= 1;
2836 }
2837 }
2838
2839 fn shift_right(&mut self) {
2842 self.hold_times.copy_within(..(MAX_HOPS - 1) * HOLD_TIME_LEN, HOLD_TIME_LEN);
2844
2845 let mut src_idx = HMAC_COUNT - 2;
2848 let mut dest_idx = HMAC_COUNT - 1;
2849 let mut copy_len = 1;
2850
2851 for i in 0..MAX_HOPS - 1 {
2852 self.hmacs.copy_within(
2853 src_idx * HMAC_LEN..(src_idx + copy_len) * HMAC_LEN,
2854 dest_idx * HMAC_LEN,
2855 );
2856
2857 if i == MAX_HOPS - 2 {
2859 break;
2860 }
2861
2862 copy_len += 1;
2863 src_idx -= copy_len + 1;
2864 dest_idx -= copy_len;
2865 }
2866 }
2867
2868 fn get_hmac(&self, idx: usize) -> &[u8] {
2869 &self.hmacs[idx * HMAC_LEN..(idx + 1) * HMAC_LEN]
2870 }
2871
2872 fn get_hmac_mut(&mut self, idx: usize) -> &mut [u8] {
2873 &mut self.hmacs[idx * HMAC_LEN..(idx + 1) * HMAC_LEN]
2874 }
2875
2876 fn get_hold_time_bytes(&self, idx: usize) -> &[u8] {
2877 &self.hold_times[idx * HOLD_TIME_LEN..(idx + 1) * HOLD_TIME_LEN]
2878 }
2879
2880 fn update(&mut self, message: &[u8], shared_secret: &[u8], hold_time: u32) {
2881 let hold_time_bytes: [u8; 4] = hold_time.to_be_bytes();
2882 self.hold_times[..HOLD_TIME_LEN].copy_from_slice(&hold_time_bytes);
2883 self.add_hmacs(shared_secret, message);
2884 }
2885}
2886
2887fn process_failure_packet(
2889 onion_error: &mut OnionErrorPacket, shared_secret: &[u8], hold_time: u32,
2890) {
2891 if let Some(ref mut attribution_data) = onion_error.attribution_data {
2893 attribution_data.shift_right();
2894 }
2895
2896 update_attribution_data(onion_error, shared_secret, hold_time);
2898}
2899
2900pub(crate) fn process_fulfill_attribution_data(
2904 attribution_data: Option<AttributionData>, shared_secret: &[u8], hold_time: u32,
2905) -> AttributionData {
2906 let mut attribution_data =
2907 attribution_data.map_or(AttributionData::new(), |mut attribution_data| {
2908 attribution_data.shift_right();
2910
2911 attribution_data
2912 });
2913
2914 attribution_data.update(&[], &shared_secret, hold_time);
2917 attribution_data.crypt(&shared_secret);
2918
2919 attribution_data
2920}
2921
2922#[cfg(test)]
2923mod tests {
2924 use core::iter;
2925 use std::sync::Arc;
2926
2927 use crate::io;
2928 use crate::ln::channelmanager::PaymentId;
2929 use crate::ln::msgs::{self, UpdateFailHTLC};
2930 use crate::ln::types::ChannelId;
2931 use crate::routing::router::{Path, PaymentParameters, Route, RouteHop};
2932 use crate::types::features::{ChannelFeatures, NodeFeatures};
2933 use crate::types::payment::PaymentHash;
2934 use crate::util::ser::{VecWriter, Writeable, Writer};
2935
2936 #[allow(unused_imports)]
2937 use crate::prelude::*;
2938 use crate::util::test_utils::TestLogger;
2939
2940 use super::*;
2941 use bitcoin::hex::{DisplayHex, FromHex};
2942 use bitcoin::secp256k1::Secp256k1;
2943 use bitcoin::secp256k1::{PublicKey, SecretKey};
2944 use types::features::Features;
2945
2946 fn get_test_session_key() -> SecretKey {
2947 let hex = "4141414141414141414141414141414141414141414141414141414141414141";
2948 SecretKey::from_slice(&<Vec<u8>>::from_hex(hex).unwrap()[..]).unwrap()
2949 }
2950
2951 fn build_test_path() -> Path {
2952 Path {
2953 hops: vec![
2954 RouteHop {
2955 pubkey: PublicKey::from_slice(
2956 &<Vec<u8>>::from_hex(
2957 "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619",
2958 )
2959 .unwrap()[..],
2960 )
2961 .unwrap(),
2962 channel_features: ChannelFeatures::empty(),
2963 node_features: NodeFeatures::empty(),
2964 short_channel_id: 0,
2965 fee_msat: 0,
2966 cltv_expiry_delta: 0,
2967 maybe_announced_channel: true, },
2969 RouteHop {
2970 pubkey: PublicKey::from_slice(
2971 &<Vec<u8>>::from_hex(
2972 "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c",
2973 )
2974 .unwrap()[..],
2975 )
2976 .unwrap(),
2977 channel_features: ChannelFeatures::empty(),
2978 node_features: NodeFeatures::empty(),
2979 short_channel_id: 1,
2980 fee_msat: 0,
2981 cltv_expiry_delta: 0,
2982 maybe_announced_channel: true, },
2984 RouteHop {
2985 pubkey: PublicKey::from_slice(
2986 &<Vec<u8>>::from_hex(
2987 "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007",
2988 )
2989 .unwrap()[..],
2990 )
2991 .unwrap(),
2992 channel_features: ChannelFeatures::empty(),
2993 node_features: NodeFeatures::empty(),
2994 short_channel_id: 2,
2995 fee_msat: 0,
2996 cltv_expiry_delta: 0,
2997 maybe_announced_channel: true, },
2999 RouteHop {
3000 pubkey: PublicKey::from_slice(
3001 &<Vec<u8>>::from_hex(
3002 "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991",
3003 )
3004 .unwrap()[..],
3005 )
3006 .unwrap(),
3007 channel_features: ChannelFeatures::empty(),
3008 node_features: NodeFeatures::empty(),
3009 short_channel_id: 3,
3010 fee_msat: 0,
3011 cltv_expiry_delta: 0,
3012 maybe_announced_channel: true, },
3014 RouteHop {
3015 pubkey: PublicKey::from_slice(
3016 &<Vec<u8>>::from_hex(
3017 "02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145",
3018 )
3019 .unwrap()[..],
3020 )
3021 .unwrap(),
3022 channel_features: ChannelFeatures::empty(),
3023 node_features: NodeFeatures::empty(),
3024 short_channel_id: 4,
3025 fee_msat: 0,
3026 cltv_expiry_delta: 0,
3027 maybe_announced_channel: true, },
3029 ],
3030 blinded_tail: None,
3031 }
3032 }
3033
3034 fn build_test_onion_keys() -> Vec<OnionKeys> {
3035 let secp_ctx = Secp256k1::new();
3037
3038 let path = build_test_path();
3039 let route = Route { paths: vec![path], route_params: None };
3040
3041 let onion_keys =
3042 super::construct_onion_keys(&secp_ctx, &route.paths[0], &get_test_session_key());
3043 assert_eq!(onion_keys.len(), route.paths[0].hops.len());
3044 onion_keys
3045 }
3046
3047 #[test]
3048 fn onion_vectors() {
3049 let onion_keys = build_test_onion_keys();
3050
3051 let hex = "53eb63ea8a3fec3b3cd433b85cd62a4b145e1dda09391b348c4e1cd36a03ea66";
3054 assert_eq!(
3055 onion_keys[0].shared_secret.secret_bytes(),
3056 <Vec<u8>>::from_hex(hex).unwrap()[..]
3057 );
3058
3059 let hex = "2ec2e5da605776054187180343287683aa6a51b4b1c04d6dd49c45d8cffb3c36";
3060 assert_eq!(onion_keys[0].blinding_factor[..], <Vec<u8>>::from_hex(hex).unwrap()[..]);
3061
3062 let hex = "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619";
3063 assert_eq!(
3064 onion_keys[0].ephemeral_pubkey.serialize()[..],
3065 <Vec<u8>>::from_hex(hex).unwrap()[..]
3066 );
3067
3068 let hex = "ce496ec94def95aadd4bec15cdb41a740c9f2b62347c4917325fcc6fb0453986";
3069 assert_eq!(onion_keys[0].rho, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3070
3071 let hex = "b57061dc6d0a2b9f261ac410c8b26d64ac5506cbba30267a649c28c179400eba";
3072 assert_eq!(onion_keys[0].mu, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3073
3074 let hex = "a6519e98832a0b179f62123b3567c106db99ee37bef036e783263602f3488fae";
3075 assert_eq!(
3076 onion_keys[1].shared_secret.secret_bytes(),
3077 <Vec<u8>>::from_hex(hex).unwrap()[..]
3078 );
3079
3080 let hex = "bf66c28bc22e598cfd574a1931a2bafbca09163df2261e6d0056b2610dab938f";
3081 assert_eq!(onion_keys[1].blinding_factor[..], <Vec<u8>>::from_hex(hex).unwrap()[..]);
3082
3083 let hex = "028f9438bfbf7feac2e108d677e3a82da596be706cc1cf342b75c7b7e22bf4e6e2";
3084 assert_eq!(
3085 onion_keys[1].ephemeral_pubkey.serialize()[..],
3086 <Vec<u8>>::from_hex(hex).unwrap()[..]
3087 );
3088
3089 let hex = "450ffcabc6449094918ebe13d4f03e433d20a3d28a768203337bc40b6e4b2c59";
3090 assert_eq!(onion_keys[1].rho, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3091
3092 let hex = "05ed2b4a3fb023c2ff5dd6ed4b9b6ea7383f5cfe9d59c11d121ec2c81ca2eea9";
3093 assert_eq!(onion_keys[1].mu, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3094
3095 let hex = "3a6b412548762f0dbccce5c7ae7bb8147d1caf9b5471c34120b30bc9c04891cc";
3096 assert_eq!(
3097 onion_keys[2].shared_secret.secret_bytes(),
3098 <Vec<u8>>::from_hex(hex).unwrap()[..]
3099 );
3100
3101 let hex = "a1f2dadd184eb1627049673f18c6325814384facdee5bfd935d9cb031a1698a5";
3102 assert_eq!(onion_keys[2].blinding_factor[..], <Vec<u8>>::from_hex(hex).unwrap()[..]);
3103
3104 let hex = "03bfd8225241ea71cd0843db7709f4c222f62ff2d4516fd38b39914ab6b83e0da0";
3105 assert_eq!(
3106 onion_keys[2].ephemeral_pubkey.serialize()[..],
3107 <Vec<u8>>::from_hex(hex).unwrap()[..]
3108 );
3109
3110 let hex = "11bf5c4f960239cb37833936aa3d02cea82c0f39fd35f566109c41f9eac8deea";
3111 assert_eq!(onion_keys[2].rho, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3112
3113 let hex = "caafe2820fa00eb2eeb78695ae452eba38f5a53ed6d53518c5c6edf76f3f5b78";
3114 assert_eq!(onion_keys[2].mu, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3115
3116 let hex = "21e13c2d7cfe7e18836df50872466117a295783ab8aab0e7ecc8c725503ad02d";
3117 assert_eq!(
3118 onion_keys[3].shared_secret.secret_bytes(),
3119 <Vec<u8>>::from_hex(hex).unwrap()[..]
3120 );
3121
3122 let hex = "7cfe0b699f35525029ae0fa437c69d0f20f7ed4e3916133f9cacbb13c82ff262";
3123 assert_eq!(onion_keys[3].blinding_factor[..], <Vec<u8>>::from_hex(hex).unwrap()[..]);
3124
3125 let hex = "031dde6926381289671300239ea8e57ffaf9bebd05b9a5b95beaf07af05cd43595";
3126 assert_eq!(
3127 onion_keys[3].ephemeral_pubkey.serialize()[..],
3128 <Vec<u8>>::from_hex(hex).unwrap()[..]
3129 );
3130
3131 let hex = "cbe784ab745c13ff5cffc2fbe3e84424aa0fd669b8ead4ee562901a4a4e89e9e";
3132 assert_eq!(onion_keys[3].rho, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3133
3134 let hex = "5052aa1b3d9f0655a0932e50d42f0c9ba0705142c25d225515c45f47c0036ee9";
3135 assert_eq!(onion_keys[3].mu, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3136
3137 let hex = "b5756b9b542727dbafc6765a49488b023a725d631af688fc031217e90770c328";
3138 assert_eq!(
3139 onion_keys[4].shared_secret.secret_bytes(),
3140 <Vec<u8>>::from_hex(hex).unwrap()[..]
3141 );
3142
3143 let hex = "c96e00dddaf57e7edcd4fb5954be5b65b09f17cb6d20651b4e90315be5779205";
3144 assert_eq!(onion_keys[4].blinding_factor[..], <Vec<u8>>::from_hex(hex).unwrap()[..]);
3145
3146 let hex = "03a214ebd875aab6ddfd77f22c5e7311d7f77f17a169e599f157bbcdae8bf071f4";
3147 assert_eq!(
3148 onion_keys[4].ephemeral_pubkey.serialize()[..],
3149 <Vec<u8>>::from_hex(hex).unwrap()[..]
3150 );
3151
3152 let hex = "034e18b8cc718e8af6339106e706c52d8df89e2b1f7e9142d996acf88df8799b";
3153 assert_eq!(onion_keys[4].rho, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3154
3155 let hex = "8e45e5c61c2b24cb6382444db6698727afb063adecd72aada233d4bf273d975a";
3156 assert_eq!(onion_keys[4].mu, <Vec<u8>>::from_hex(hex).unwrap()[..]);
3157
3158 let payloads = vec!(
3164 RawOnionHopData::new(msgs::OutboundOnionPayload::Forward {
3165 short_channel_id: 1,
3166 amt_to_forward: 15000,
3167 outgoing_cltv_value: 1500,
3168 }),
3169 RawOnionHopData {
3185 data: <Vec<u8>>::from_hex("52020236b00402057806080000000000000002fd02013c0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f").unwrap(),
3186 },
3187 RawOnionHopData::new(msgs::OutboundOnionPayload::Forward {
3188 short_channel_id: 3,
3189 amt_to_forward: 12500,
3190 outgoing_cltv_value: 1250,
3191 }),
3192 RawOnionHopData::new(msgs::OutboundOnionPayload::Forward {
3193 short_channel_id: 4,
3194 amt_to_forward: 10000,
3195 outgoing_cltv_value: 1000,
3196 }),
3197 RawOnionHopData {
3213 data: <Vec<u8>>::from_hex("fd011002022710040203e8082224a33562c54507a9334e79f0dc4f17d407e6d7c61f0e2f3d0d38599502f617042710fd012de02a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a").unwrap(),
3214 },
3215 );
3216
3217 let mut w = VecWriter(Vec::new());
3219 payloads[0].write(&mut w).unwrap();
3220 let hop_1_serialized_payload = w.0;
3221 let hex = "1202023a98040205dc06080000000000000001";
3222 let expected_serialized_hop_1_payload = &<Vec<u8>>::from_hex(hex).unwrap()[..];
3223 assert_eq!(hop_1_serialized_payload, expected_serialized_hop_1_payload);
3224
3225 w = VecWriter(Vec::new());
3226 payloads[2].write(&mut w).unwrap();
3227 let hop_3_serialized_payload = w.0;
3228 let hex = "12020230d4040204e206080000000000000003";
3229 let expected_serialized_hop_3_payload = &<Vec<u8>>::from_hex(hex).unwrap()[..];
3230 assert_eq!(hop_3_serialized_payload, expected_serialized_hop_3_payload);
3231
3232 w = VecWriter(Vec::new());
3233 payloads[3].write(&mut w).unwrap();
3234 let hop_4_serialized_payload = w.0;
3235 let hex = "1202022710040203e806080000000000000004";
3236 let expected_serialized_hop_4_payload = &<Vec<u8>>::from_hex(hex).unwrap()[..];
3237 assert_eq!(hop_4_serialized_payload, expected_serialized_hop_4_payload);
3238
3239 let pad_keytype_seed =
3240 super::gen_pad_from_shared_secret(&get_test_session_key().secret_bytes());
3241
3242 let packet: msgs::OnionPacket = super::construct_onion_packet_with_writable_hopdata::<_>(
3243 payloads,
3244 onion_keys,
3245 pad_keytype_seed,
3246 &PaymentHash([0x42; 32]),
3247 )
3248 .unwrap();
3249
3250 let hex = "0002EEC7245D6B7D2CCB30380BFBE2A3648CD7A942653F5AA340EDCEA1F283686619F7F3416A5AA36DC7EEB3EC6D421E9615471AB870A33AC07FA5D5A51DF0A8823AABE3FEA3F90D387529D4F72837F9E687230371CCD8D263072206DBED0234F6505E21E282ABD8C0E4F5B9FF8042800BBAB065036EADD0149B37F27DDE664725A49866E052E809D2B0198AB9610FAA656BBF4EC516763A59F8F42C171B179166BA38958D4F51B39B3E98706E2D14A2DAFD6A5DF808093ABFCA5AEAACA16EDED5DB7D21FB0294DD1A163EDF0FB445D5C8D7D688D6DD9C541762BF5A5123BF9939D957FE648416E88F1B0928BFA034982B22548E1A4D922690EECF546275AFB233ACF4323974680779F1A964CFE687456035CC0FBA8A5428430B390F0057B6D1FE9A8875BFA89693EEB838CE59F09D207A503EE6F6299C92D6361BC335FCBF9B5CD44747AADCE2CE6069CFDC3D671DAEF9F8AE590CF93D957C9E873E9A1BC62D9640DC8FC39C14902D49A1C80239B6C5B7FD91D05878CBF5FFC7DB2569F47C43D6C0D27C438ABFF276E87364DEB8858A37E5A62C446AF95D8B786EAF0B5FCF78D98B41496794F8DCAAC4EEF34B2ACFB94C7E8C32A9E9866A8FA0B6F2A06F00A1CCDE569F97EEC05C803BA7500ACC96691D8898D73D8E6A47B8F43C3D5DE74458D20EDA61474C426359677001FBD75A74D7D5DB6CB4FEB83122F133206203E4E2D293F838BF8C8B3A29ACB321315100B87E80E0EDB272EE80FDA944E3FB6084ED4D7F7C7D21C69D9DA43D31A90B70693F9B0CC3EAC74C11AB8FF655905688916CFA4EF0BD04135F2E50B7C689A21D04E8E981E74C6058188B9B1F9DFC3EEC6838E9FFBCF22CE738D8A177C19318DFFEF090CEE67E12DE1A3E2A39F61247547BA5257489CBC11D7D91ED34617FCC42F7A9DA2E3CF31A94A210A1018143173913C38F60E62B24BF0D7518F38B5BAB3E6A1F8AEB35E31D6442C8ABB5178EFC892D2E787D79C6AD9E2FC271792983FA9955AC4D1D84A36C024071BC6E431B625519D556AF38185601F70E29035EA6A09C8B676C9D88CF7E05E0F17098B584C4168735940263F940033A220F40BE4C85344128B14BEB9E75696DB37014107801A59B13E89CD9D2258C169D523BE6D31552C44C82FF4BB18EC9F099F3BF0E5B1BB2BA9A87D7E26F98D294927B600B5529C47E04D98956677CBCEE8FA2B60F49776D8B8C367465B7C626DA53700684FB6C918EAD0EAB8360E4F60EDD25B4F43816A75ECF70F909301825B512469F8389D79402311D8AECB7B3EF8599E79485A4388D87744D899F7C47EE644361E17040A7958C8911BE6F463AB6A9B2AFACD688EC55EF517B38F1339EFC54487232798BB25522FF4572FF68567FE830F92F7B8113EFCE3E98C3FFFBAEDCE4FD8B50E41DA97C0C08E423A72689CC68E68F752A5E3A9003E64E35C957CA2E1C48BB6F64B05F56B70B575AD2F278D57850A7AD568C24A4D32A3D74B29F03DC125488BC7C637DA582357F40B0A52D16B3B40BB2C2315D03360BC24209E20972C200566BCF3BBE5C5B0AEDD83132A8A4D5B4242BA370B6D67D9B67EB01052D132C7866B9CB502E44796D9D356E4E3CB47CC527322CD24976FE7C9257A2864151A38E568EF7A79F10D6EF27CC04CE382347A2488B1F404FDBF407FE1CA1C9D0D5649E34800E25E18951C98CAE9F43555EEF65FEE1EA8F15828807366C3B612CD5753BF9FB8FCED08855F742CDDD6F765F74254F03186683D646E6F09AC2805586C7CF11998357CAFC5DF3F285329366F475130C928B2DCEBA4AA383758E7A9D20705C4BB9DB619E2992F608A1BA65DB254BB389468741D0502E2588AEB54390AC600C19AF5C8E61383FC1BEBE0029E4474051E4EF908828DB9CCA13277EF65DB3FD47CCC2179126AAEFB627719F421E20";
3251 assert_eq!(packet.encode(), <Vec<u8>>::from_hex(hex).unwrap());
3252 }
3253
3254 #[test]
3255 fn test_attributable_failure_packet_onion_mutations() {
3256 const FAILURE_MESSAGE_LEN: usize = 1060;
3258
3259 for mutating_node in 0..5 {
3260 let attribution_data_mutations = (0..HOLD_TIME_LEN * MAX_HOPS)
3261 .map(AttributionDataMutationType::HoldTimes)
3262 .chain((0..HMAC_LEN * HMAC_COUNT).map(AttributionDataMutationType::Hmacs));
3263
3264 let failure_mutations = (0..FAILURE_MESSAGE_LEN).map(MutationType::FailureMessage);
3265
3266 for mutation_type in failure_mutations
3267 .chain(attribution_data_mutations.map(MutationType::AttributionData))
3268 .chain(iter::once(MutationType::DropAttributionData))
3269 {
3270 let failure_ok = matches!(mutation_type, MutationType::DropAttributionData)
3273 || matches!(mutation_type, MutationType::AttributionData(_));
3274
3275 let mutation = Mutation { node: mutating_node, mutation_type };
3276 let decrypted_failure =
3277 test_attributable_failure_packet_onion_with_mutation(Some(mutation));
3278
3279 if failure_ok {
3280 assert_eq!(
3281 decrypted_failure.onion_error_code,
3282 Some(LocalHTLCFailureReason::IncorrectPaymentDetails)
3283 );
3284 continue;
3285 }
3286
3287 assert!(decrypted_failure.short_channel_id.is_none());
3290
3291 assert!(decrypted_failure.attribution_failed_channel == Some(mutating_node as u64));
3293
3294 assert_eq!(decrypted_failure.hold_times, [5, 4, 3, 2, 1][..mutating_node]);
3295 }
3296 }
3297 }
3298
3299 #[test]
3300 fn test_attributable_failure_packet_onion_happy() {
3301 let decrypted_failure = test_attributable_failure_packet_onion_with_mutation(None);
3302 assert_eq!(
3303 decrypted_failure.onion_error_code,
3304 Some(LocalHTLCFailureReason::IncorrectPaymentDetails)
3305 );
3306 assert_eq!(decrypted_failure.hold_times, [5, 4, 3, 2, 1]);
3307 }
3308
3309 enum AttributionDataMutationType {
3310 HoldTimes(usize),
3311 Hmacs(usize),
3312 }
3313
3314 enum MutationType {
3315 FailureMessage(usize),
3316 AttributionData(AttributionDataMutationType),
3317 DropAttributionData,
3318 }
3319
3320 struct Mutation {
3321 node: usize,
3322 mutation_type: MutationType,
3323 }
3324
3325 fn test_attributable_failure_packet_onion_with_mutation(
3326 mutation: Option<Mutation>,
3327 ) -> DecodedOnionFailure {
3328 struct ExpectedMessage<'a> {
3329 message: &'a str,
3330 attribution_data: &'a str,
3331 }
3332
3333 impl<'a> ExpectedMessage<'a> {
3334 fn assert_eq(&self, actual: &OnionErrorPacket) {
3335 assert_eq!(actual.data.to_lower_hex_string(), self.message);
3336
3337 let (expected_hold_times, expected_hmacs) =
3338 self.attribution_data.split_at(MAX_HOPS * HOLD_TIME_LEN * 2);
3339 assert_eq!(
3340 actual.attribution_data.as_ref().unwrap().hold_times.to_lower_hex_string(),
3341 expected_hold_times
3342 );
3343 assert_eq!(
3344 actual.attribution_data.as_ref().unwrap().hmacs.to_lower_hex_string(),
3345 expected_hmacs
3346 );
3347 }
3348 }
3349
3350 const FAILURE_DATA: &str = "0000000000000064000c3500fd84d1fd012c808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080";
3351 const EXPECTED_MESSAGES: [ExpectedMessage; 5] = [
3352 ExpectedMessage {
3353 message: "146e94a9086dbbed6a0ab6932d00c118a7195dbf69b7d7a12b0e6956fc54b5e0a989f165b5f12fd45edd73a5b0c48630ff5be69500d3d82a29c0803f0a0679a6a073c33a6fb8250090a3152eba3f11a85184fa87b67f1b0354d6f48e3b342e332a17b7710f342f342a87cf32eccdf0afc2160808d58abb5e5840d2c760c538e63a6f841970f97d2e6fe5b8739dc45e2f7f5f532f227bcc2988ab0f9cc6d3f12909cd5842c37bc8c7608475a5ebbe10626d5ecc1f3388ad5f645167b44a4d166f87863fe34918cea25c18059b4c4d9cb414b59f6bc50c1cea749c80c43e2344f5d23159122ed4ab9722503b212016470d9610b46c35dbeebaf2e342e09770b38392a803bc9d2e7c8d6d384ffcbeb74943fe3f64afb2a543a6683c7db3088441c531eeb4647518cb41992f8954f1269fb969630944928c2d2b45593731b5da0c4e70d04a0a57afe4af42e99912fbb4f8883a5ecb9cb29b883cb6bfa0f4db2279ff8c6d2b56a232f55ba28fe7dfa70a9ab0433a085388f25cce8d53de6a2fbd7546377d6ede9027ad173ba1f95767461a3689ef405ab608a21086165c64b02c1782b04a6dba2361a7784603069124e12f2f6dcb1ec7612a4fbf94c0e14631a2bef6190c3d5f35e0c4b32aa85201f449d830fd8f782ec758b0910428e3ec3ca1dba3b6c7d89f69e1ee1b9df3dfbbf6d361e1463886b38d52e8f43b73a3bd48c6f36f5897f514b93364a31d49d1d506340b1315883d425cb36f4ea553430d538fd6f3596d4afc518db2f317dd051abc0d4bfb0a7870c3db70f19fe78d6604bbf088fcb4613f54e67b038277fedcd9680eb97bdffc3be1ab2cbcbafd625b8a7ac34d8c190f98d3064ecd3b95b8895157c6a37f31ef4de094b2cb9dbf8ff1f419ba0ecacb1bb13df0253b826bec2ccca1e745dd3b3e7cc6277ce284d649e7b8285727735ff4ef6cca6c18e2714f4e2a1ac67b25213d3bb49763b3b94e7ebf72507b71fb2fe0329666477ee7cb7ebd6b88ad5add8b217188b1ca0fa13de1ec09cc674346875105be6e0e0d6c8928eb0df23c39a639e04e4aedf535c4e093f08b2c905a14f25c0c0fe47a5a1535ab9eae0d9d67bdd79de13a08d59ee05385c7ea4af1ad3248e61dd22f8990e9e99897d653dd7b1b1433a6d464ea9f74e377f2d8ce99ba7dbc753297644234d25ecb5bd528e2e2082824681299ac30c05354baaa9c3967d86d7c07736f87fc0f63e5036d47235d7ae12178ced3ae36ee5919c093a02579e4fc9edad2c446c656c790704bfc8e2c491a42500aa1d75c8d4921ce29b753f883e17c79b09ea324f1f32ddf1f3284cd70e847b09d90f6718c42e5c94484cc9cbb0df659d255630a3f5a27e7d5dd14fa6b974d1719aa98f01a20fb4b7b1c77b42d57fab3c724339d459ee4a1c6b5d3bd4e08624c786a257872acc9ad3ff62222f2265a658d9f2a007229a5293b67ec91c84c4b4407c228434bad8a815ca9b256c776bd2c9f",
3354 attribution_data: "d77d0711b5f71d1d1be56bd88b3bb7ebc1792bb739ea7ebc1bc3b031b8bc2df3a50e25aeb99f47d7f7ab39e24187d3f4df9c4333463b053832ee9ac07274a5261b8b2a01fc09ce9ea7cd04d7b585dfb8cf5958e3f3f2a4365d1ec0df1d83c6a6221b5b7d1ff30156a2289a1d3ee559e7c7256bda444bb8e046f860e00b3a59a85e1e1a43de215fd5e6bf646a5deab97b1912c934e31b1cfd344764d6ca7e14ea7b3f2a951aba907c964c0f5d19a44e6d1d7279637321fa598adde927b3087d238f8b426ecde500d318617cdb7a56e6ce3520fc95be41a549973764e4dc483853ecc313947709f1b5199cb077d46e701fa633e11d3e13b03e9212c115ca6fa004b2f3dd912814693b705a561a06da54cdf603677a3abecdc22c7358c2de3cef771b366a568150aeecc86ad1990bb0f4e2865933b03ea0df87901bff467908273dc6cea31cbab0e2b8d398d10b001058c259ed221b7b55762f4c7e49c8c11a45a107b7a2c605c26dc5b0b10d719b1c844670102b2b6a36c43fe4753a78a483fc39166ae28420f112d50c10ee64ca69569a2f690712905236b7c2cb7ac8954f02922d2d918c56d42649261593c47b14b324a65038c3c5be8d3c403ce0c8f19299b1664bf077d7cf1636c4fb9685a8e58b7029fd0939fa07925a60bed339b23f973293598f595e75c8f9d455d7cebe4b5e23357c8bd47d66d6628b39427e37e0aecbabf46c11be6771f7136e108a143ae9bafba0fc47a51b6c7deef4cba54bae906398ee3162a41f2191ca386b628bde7e1dd63d1611aa01a95c456df337c763cb8c3a81a6013aa633739d8cd554c688102211725e6adad165adc1bcd429d020c51b4b25d2117e8bb27eb0cc7020f9070d4ad19ac31a76ebdf5f9246646aeadbfb9a3f1d75bd8237961e786302516a1a781780e8b73f58dc06f307e58bd0eb1d8f5c9111f01312974c1dc777a6a2d3834d8a2a40014e9818d0685cb3919f6b3b788ddc640b0ff9b1854d7098c7dd6f35196e902b26709640bc87935a3914869a807e8339281e9cedaaca99474c3e7bdd35050bb998ab4546f9900904e0e39135e861ff7862049269701081ebce32e4cca992c6967ff0fd239e38233eaf614af31e186635e9439ec5884d798f9174da6ff569d68ed5c092b78bd3f880f5e88a7a8ab36789e1b57b035fb6c32a6358f51f83e4e5f46220bcad072943df8bd9541a61b7dae8f30fa3dd5fb39b1fd9a0b8e802552b78d4ec306ecee15bfe6da14b29ba6d19ce5be4dd478bca74a52429cd5309d404655c3dec85c252"
3355 },
3356 ExpectedMessage {
3357 message: "7512354d6a26781d25e65539772ba049b7ed7c530bf75ab7ef80cf974b978a07a1c3dabc61940011585323f70fa98cfa1d4c868da30b1f751e44a72d9b3f79809c8c51c9f0843daa8fe83587844fedeacb7348362003b31922cbb4d6169b2087b6f8d192d9cfe5363254cd1fde24641bde9e422f170c3eb146f194c48a459ae2889d706dc654235fa9dd20307ea54091d09970bf956c067a3bcc05af03c41e01af949a131533778bf6ee3b546caf2eabe9d53d0fb2e8cc952b7e0f5326a69ed2e58e088729a1d85971c6b2e129a5643f3ac43da031e655b27081f10543262cf9d72d6f64d5d96387ac0d43da3e3a03da0c309af121dcf3e99192efa754eab6960c256ffd4c546208e292e0ab9894e3605db098dc16b40f17c320aa4a0e42fc8b105c22f08c9bc6537182c24e32062c6cd6d7ec7062a0c2c2ecdae1588c82185cdc61d874ee916a7873ac54cddf929354f307e870011704a0e9fbc5c7802d6140134028aca0e78a7e2f3d9e5c7e49e20c3a56b624bfea51196ec9e88e4e56be38ff56031369f45f1e03be826d44a182f270c153ee0d9f8cf9f1f4132f33974e37c7887d5b857365c873cb218cbf20d4be3abdb2a2011b14add0a5672e01e5845421cf6dd6faca1f2f443757aae575c53ab797c2227ecdab03882bbbf4599318cefafa72fa0c9a0f5a51d13c9d0e5d25bfcfb0154ed25895260a9df8743ac188714a3f16960e6e2ff663c08bffda41743d50960ea2f28cda0bc3bd4a180e297b5b41c700b674cb31d99c7f2a1445e121e772984abff2bbe3f42d757ceeda3d03fb1ffe710aecabda21d738b1f4620e757e57b123dbc3c4aa5d9617dfa72f4a12d788ca596af14bea583f502f16fdc13a5e739afb0715424af2767049f6b9aa107f69c5da0e85f6d8c5e46507e14616d5d0b797c3dea8b74a1b12d4e47ba7f57f09d515f6c7314543f78b5e85329d50c5f96ee2f55bbe0df742b4003b24ccbd4598a64413ee4807dc7f2a9c0b92424e4ae1b418a3cdf02ea4da5c3b12139348aa7022cc8272a3a1714ee3e4ae111cffd1bdfd62c503c80bdf27b2feaea0d5ab8fe00f9cec66e570b00fd24b4a2ed9a5f6384f148a4d6325110a41ca5659ebc5b98721d298a52819b6fb150f273383f1c5754d320be428941922da790e17f482989c365c078f7f3ae100965e1b38c052041165295157e1a7c5b7a57671b842d4d85a7d971323ad1f45e17a16c4656d889fc75c12fc3d8033f598306196e29571e414281c5da19c12605f48347ad5b4648e371757cbe1c40adb93052af1d6110cfbf611af5c8fc682b7e2ade3bfca8b5c7717d19fc9f97964ba6025aebbc91a6671e259949dcf40984342118de1f6b514a7786bd4f6598ffbe1604cef476b2a4cb1343db608aca09d1d38fc23e98ee9c65e7f6023a8d1e61fd4f34f753454bd8e858c8ad6be6403edc599c220e03ca917db765980ac781e758179cd93983e9c1e769e4241d47c",
3358 attribution_data: "1571e10db7f8aa9f8e7e99caaf9c892e106c817df1d8e3b7b0e39d1c48f631e473e17e205489dd7b3c634cac3be0825cbf01418cd46e83c24b8d9c207742db9a0f0e5bcd888086498159f08080ba7bf36dee297079eb841391ccd3096da76461e314863b6412efe0ffe228d51c6097db10d3edb2e50ea679820613bfe9db11ba02920ab4c1f2a79890d997f1fc022f3ab78f0029cc6de0c90be74d55f4a99bf77a50e20f8d076fe61776190a61d2f41c408871c0279309cba3b60fcdc7efc4a0e90b47cb4a418fc78f362ecc7f15ebbce9f854c09c7be300ebc1a40a69d4c7cb7a19779b6905e82bec221a709c1dab8cbdcde7b527aca3f54bde651aa9f3f2178829cee3f1c0b9292758a40cc63bd998fcd0d3ed4bdcaf1023267b8f8e44130a63ad15f76145936552381eabb6d684c0a3af6ba8efcf207cebaea5b7acdbb63f8e7221102409d10c23f0514dc9f4d0efb2264161a193a999a23e992632710580a0d320f676d367b9190721194514457761af05207cdab2b6328b1b3767eacb36a7ef4f7bd2e16762d13df188e0898b7410f62459458712a44bf594ae662fd89eb300abb6952ff8ad40164f2bcd7f86db5c7650b654b79046de55d51aa8061ce35f867a3e8f5bf98ad920be827101c64fb871d86e53a4b3c0455bfac5784168218aa72cbee86d9c750a9fa63c363a8b43d7bf4b2762516706a306f0aa3be1ec788b5e13f8b24837e53ac414f211e11c7a093cd9653dfa5fba4e377c79adfa5e841e2ddb6afc054fc715c05ddc6c8fc3e1ee3406e1ffceb2df77dc2f02652614d1bfcfaddebaa53ba919c7051034e2c7b7cfaabdf89f26e7f8e3f956d205dfab747ad0cb505b85b54a68439621b25832cbc2898919d0cd7c0a64cfd235388982dd4dd68240cb668f57e1d2619a656ed326f8c92357ee0d9acead3c20008bc5f04ca8059b55d77861c6d04dfc57cfba57315075acbe1451c96cf28e1e328e142890248d18f53b5d3513ce574dea7156cf596fdb3d909095ec287651f9cf1bcdc791c5938a5dd9b47e84c004d24ab3ae74492c7e8dcc1da15f65324be2672947ec82074cac8ce2b925bc555facbbf1b55d63ea6fbea6a785c97d4caf2e1dad9551b7f66c31caae5ebc7c0047e892f201308fcf452c588be0e63d89152113d87bf0dbd01603b4cdc7f0b724b0714a9851887a01f709408882e18230fe810b9fafa58a666654576d8eba3005f07221f55a6193815a672e5db56204053bc4286fa3db38250396309fd28011b5708a26a2d76c4a333b69b6bfd272fb"
3359 },
3360 ExpectedMessage {
3361 message: "145bc1c63058f7204abbd2320d422e69fb1b3801a14312f81e5e29e6b5f4774cfed8a25241d3dfb7466e749c1b3261559e49090853612e07bd669dfb5f4c54162fa504138dabd6ebcf0db8017840c35f12a2cfb84f89cc7c8959a6d51815b1d2c5136cedec2e4106bb5f2af9a21bd0a02c40b44ded6e6a90a145850614fb1b0eef2a03389f3f2693bc8a755630fc81fff1d87a147052863a71ad5aebe8770537f333e07d841761ec448257f948540d8f26b1d5b66f86e073746106dfdbb86ac9475acf59d95ece037fba360670d924dce53aaa74262711e62a8fc9eb70cd8618fbedae22853d3053c7f10b1a6f75369d7f73c419baa7dbf9f1fc5895362dcc8b6bd60cca4943ef7143956c91992119bccbe1666a20b7de8a2ff30a46112b53a6bb79b763903ecbd1f1f74952fb1d8eb0950c504df31fe702679c23b463f82a921a2c931500ab08e686cffb2d87258d254fb17843959cccd265a57ba26c740f0f231bb76df932b50c12c10be90174b37d454a3f8b284c849e86578a6182c4a7b2e47dd57d44730a1be9fec4ad07287a397e28dce4fda57e9cdfdb2eb5afdf0d38ef19d982341d18d07a556bb16c1416f480a396f278373b8fd9897023a4ac506e65cf4c306377730f9c8ca63cf47565240b59c4861e52f1dab84d938e96fb31820064d534aca05fd3d2600834fe4caea98f2a748eb8f200af77bd9fbf46141952b9ddda66ef0ebea17ea1e7bb5bce65b6e71554c56dd0d4e14f4cf74c77a150776bf31e7419756c71e7421dc22efe9cf01de9e19fc8808d5b525431b944400db121a77994518d6025711cb25a18774068bba7faaa16d8f65c91bec8768848333156dcb4a08dfbbd9fef392da3e4de13d4d74e83a7d6e46cfe530ee7a6f711e2caf8ad5461ba8177b2ef0a518baf9058ff9156e6aa7b08d938bd8d1485a787809d7b4c8aed97be880708470cd2b2cdf8e2f13428cc4b04ef1f2acbc9562f3693b948d0aa94b0e6113cafa684f8e4a67dc431dfb835726874bef1de36f273f52ee694ec46b0700f77f8538067642a552968e866a72a3f2031ad116663ac17b172b446c5bc705b84777363a9a3fdc6443c07b2f4ef58858122168d4ebbaee920cefc312e1cea870ed6e15eec046ab2073bbf08b0a3366f55cfc6ad4681a12ab0946534e7b6f90ea8992d530ec3daa6b523b3cf03101c60cadd914f30dec932c1ef4341b5a8efac3c921e203574cfe0f1f83433fddb8ccfd273f7c3cab7bc27efe3bb61fdccd5146f1185364b9b621e7fb2b74b51f5ee6be72ab6ff46a6359dc2c855e61469724c1dbeb273df9d2e1c1fb74891239c0019dc12d5c7535f7238f963b761d7102b585372cf021b64c4fc85bfb3161e59d2e298bba44cfd34d6859d9dba9dc6271e5047d525468c814f2ae438474b0a977273036da1a2292f88fcfb89574a6bdca1185b40f8aa54026d5926725f99ef028da1be892e3586361efe15f4a148ff1bc9",
3362 attribution_data: "34e34397b8621ec2f2b54dbe6c14073e267324cd60b152bce76aec8729a6ddefb61bc263be4b57bd592aae604a32bea69afe6ef4a6b573c26b17d69381ec1fc9b5aa769d148f2f1f8b5377a73840bb6dc641f68e356323d766fff0aaca5039fe7fc27038195844951a97d5a5b26698a4ca1e9cd4bca1fcca0aac5fee91b18977d2ad0e399ba159733fc98f6e96898ebc39bf0028c9c81619233bab6fad0328aa183a635fac20437fa6e00e899b2527c3697a8ab7342e42d55a679b176ab76671fcd480a9894cb897fa6af0a45b917a162bed6c491972403185df7235502f7ada65769d1bfb12d29f10e25b0d3cc08bbf6de8481ac5c04df32b4533b4f764c2aefb7333202645a629fb16e4a208e9045dc36830759c852b31dd613d8b2b10bbead1ed4eb60c85e8a4517deba5ab53e39867c83c26802beee2ee545bdd713208751added5fc0eb2bc89a5aa2decb18ee37dac39f22a33b60cc1a369d24de9f3d2d8b63c039e248806de4e36a47c7a0aed30edd30c3d62debdf1ad82bf7aedd7edec413850d91c261e12beec7ad1586a9ad25b2db62c58ca17119d61dcc4f3e5c4520c42a8e384a45d8659b338b3a08f9e123a1d3781f5fc97564ccff2c1d97f06fa0150cfa1e20eacabefb0c339ec109336d207cc63d9170752fc58314c43e6d4a528fd0975afa85f3aa186ff1b6b8cb12c97ed4ace295b0ef5f075f0217665b8bb180246b87982d10f43c9866b22878106f5214e99188781180478b07764a5e12876ddcb709e0a0a8dd42cf004c695c6fc1669a6fd0e4a1ca54b024d0d80eac492a9e5036501f36fb25b72a054189294955830e43c18e55668337c8c6733abb09fc2d4ade18d5a853a2b82f7b4d77151a64985004f1d9218f2945b63c56fdebd1e96a2a7e49fa70acb4c39873947b83c191c10e9a8f40f60f3ad5a2be47145c22ea59ed3f5f4e61cb069e875fb67142d281d784bf925cc286eacc2c43e94d08da4924b83e58dbf2e43fa625bdd620eba6d9ce960ff17d14ed1f2dbee7d08eceb540fdc75ff06dabc767267658fad8ce99e2a3236e46d2deedcb51c3c6f81589357edebac9772a70b3d910d83cd1b9ce6534a011e9fa557b891a23b5d88afcc0d9856c6dabeab25eea55e9a248182229e4927f268fe5431672fcce52f434ca3d27d1a2136bae5770bb36920df12fbc01d0e8165610efa04794f414c1417f1d4059435c5385bfe2de83ce0e238d6fd2dbd3c0487c69843298577bfa480fe2a16ab2a0e4bc712cd8b5a14871cda61c993b6835303d9043d7689a"
3363 },
3364 ExpectedMessage {
3365 message: "1b4b09a935ce7af95b336baae307f2b400e3a7e808d9b4cf421cc4b3955620acb69dcdb656128dae8857adbd4e6b37fbb1be9c1f2f02e61e9e59a630c4c77cf383cb37b07413aa4de2f2fbf5b40ae40a91a8f4c6d74aeacef1bb1be4ecbc26ec2c824d2bc45db4b9098e732a769788f1cff3f5b41b0d25c132d40dc5ad045ef0043b15332ca3c5a09de2cdb17455a0f82a8f20da08346282823dab062cdbd2111e238528141d69de13de6d83994fbc711e3e269df63a12d3a4177c5c149150eb4dc2f589cd8acabcddba14dec3b0dada12d663b36176cd3c257c5460bab93981ad99f58660efa9b31d7e63b39915329695b3fa60e0a3bdb93e7e29a54ca6a8f360d3848866198f9c3da3ba958e7730847fe1e6478ce8597848d3412b4ae48b06e05ba9a104e648f6eaf183226b5f63ed2e68f77f7e38711b393766a6fab7921b03eba82b5d7cb78e34dc961948d6161eadd7cf5d95d9c56df2ff5faa6ccf85eacdc9ff2fc3abafe41c365a5bd14fd486d6b5e2f24199319e7813e02e798877ffe31a70ae2398d9e31b9e3727e6c1a3c0d995c67d37bb6e72e9660aaaa9232670f382add2edd468927e3303b6142672546997fe105583e7c5a3c4c2b599731308b5416e6c9a3f3ba55b181ad0439d3535356108b059f2cb8742eed7a58d4eba9fe79eaa77c34b12aff1abdaea93197aabd0e74cb271269ca464b3b06aef1d6573df5e1224179616036b368677f26479376681b772d3760e871d99efd34cca5cd6beca95190d967da820b21e5bec60082ea46d776b0517488c84f26d12873912d1f68fafd67bcf4c298e43cfa754959780682a2db0f75f95f0598c0d04fd014c50e4beb86a9e37d95f2bba7e5065ae052dc306555bca203d104c44a538b438c9762de299e1c4ad30d5b4a6460a76484661fc907682af202cd69b9a4473813b2fdc1142f1403a49b7e69a650b7cde9ff133997dcc6d43f049ecac5fce097a21e2bce49c810346426585e3a5a18569b4cddd5ff6bdec66d0b69fcbc5ab3b137b34cc8aefb8b850a764df0e685c81c326611d901c392a519866e132bbb73234f6a358ba284fbafb21aa3605cacbaf9d0c901390a98b7a7dac9d4f0b405f7291c88b2ff45874241c90ac6c5fc895a440453c344d3a365cb929f9c91b9e39cb98b142444aae03a6ae8284c77eb04b0a163813d4c21883df3c0f398f47bf127b5525f222107a2d8fe55289f0cfd3f4bbad6c5387b0594ef8a966afc9e804ccaf75fe39f35c6446f7ee076d433f2f8a44dba1515acc78e589fa8c71b0a006fe14feebd51d0e0aa4e51110d16759eee86192eee90b34432130f387e0ccd2ee71023f1f641cddb571c690107e08f592039fe36d81336a421e89378f351e633932a2f5f697d25b620ffb8e84bb6478e9bd229bf3b164b48d754ae97bd23f319e3c56b3bcdaaeb3bd7fc02ec02066b324cb72a09b6b43dec1097f49d69d3c138ce6f1a6402898baf7568c",
3366 attribution_data: "74a4ea61339463642a2182758871b2ea724f31f531aa98d80f1c3043febca41d5ee52e8b1e127e61719a0d078db8909748d57839e58424b91f063c4fbc8a221bef261140e66a9b596ca6d420a973ad54fef30646ae53ccf0855b61f291a81e0ec6dc0f6bf69f0ca0e5889b7e23f577ba67d2a7d6a2aa91264ab9b20630ed52f8ed56cc10a869807cd1a4c2cd802d8433fee5685d6a04edb0bff248a480b93b01904bed3bb31705d1ecb7332004290cc0cd9cc2f7907cf9db28eec02985301668f53fbc28c3e095c8f3a6cd8cab28e5e442fd9ba608b8b12e098731bbfda755393bd403c62289093b40390b2bae337fc87d2606ca028311d73a9ffbdffef56020c735ada30f54e577c6a9ec515ae2739290609503404b118d7494499ecf0457d75015bb60a16288a4959d74cf5ac5d8d6c113de39f748a418d2a7083b90c9c0a09a49149fd1f2d2cde4412e5aa2421eca6fd4f6fe6b2c362ff37d1a0608c931c7ca3b8fefcfd4c44ef9c38357a0767b14f83cb49bd1989fb3f8e2ab202ac98bd8439790764a40bf309ea2205c1632610956495720030a25dc7118e0c868fdfa78c3e9ecce58215579a0581b3bafdb7dbbe53be9e904567fdc0ce1236aab5d22f1ebc18997e3ea83d362d891e04c5785fd5238326f767bce499209f8db211a50e1402160486e98e7235cf397dbb9ae19fd9b79ef589c821c6f99f28be33452405a003b33f4540fe0a41dfcc286f4d7cc10b70552ba7850869abadcd4bb7f256823face853633d6e2a999ac9fcd259c71d08e266db5d744e1909a62c0db673745ad9585949d108ab96640d2bc27fb4acac7fa8b170a30055a5ede90e004df9a44bdc29aeb4a6bec1e85dde1de6aaf01c6a5d12405d0bec22f49026cb23264f8c04b8401d3c2ab6f2e109948b6193b3bec27adfe19fb8afb8a92364d6fc5b219e8737d583e7ff3a4bcb75d53edda3bf3f52896ac36d8a877ad9f296ea6c045603fc62ac4ae41272bde85ef7c3b3fd3538aacfd5b025fefbe277c2906821ecb20e6f75ea479fa3280f9100fb0089203455c56b6bc775e5c2f0f58c63edd63fa3eec0b40da4b276d0d41da2ec0ead865a98d12bc694e23d8eaadd2b4d0ee88e9570c88fb878930f492e036d27998d593e47763927ff7eb80b188864a3846dd2238f7f95f4090ed399ae95deaeb37abca1cf37c397cc12189affb42dca46b4ff6988eb8c060691d155302d448f50ff70a794d97c0408f8cee9385d6a71fa412e36edcb22dbf433db9db4779f27b682ee17fc05e70c8e794b9f7f6d1"
3367 },
3368 ExpectedMessage {
3369 message: "2dd2f49c1f5af0fcad371d96e8cddbdcd5096dc309c1d4e110f955926506b3c03b44c192896f45610741c85ed4074212537e0c118d472ff3a559ae244acd9d783c65977765c5d4e00b723d00f12475aafaafff7b31c1be5a589e6e25f8da2959107206dd42bbcb43438129ce6cce2b6b4ae63edc76b876136ca5ea6cd1c6a04ca86eca143d15e53ccdc9e23953e49dc2f87bb11e5238cd6536e57387225b8fff3bf5f3e686fd08458ffe0211b87d64770db9353500af9b122828a006da754cf979738b4374e146ea79dd93656170b89c98c5f2299d6e9c0410c826c721950c780486cd6d5b7130380d7eaff994a8503a8fef3270ce94889fe996da66ed121741987010f785494415ca991b2e8b39ef2df6bde98efd2aec7d251b2772485194c8368451ad49c2354f9d30d95367bde316fec6cbdddc7dc0d25e99d3075e13d3de0822669861dafcd29de74eac48b64411987285491f98d78584d0c2a163b7221ea796f9e8671b2bb91e38ef5e18aaf32c6c02f2fb690358872a1ed28166172631a82c2568d23238017188ebbd48944a147f6cdb3690d5f88e51371cb70adf1fa02afe4ed8b581afc8bcc5104922843a55d52acde09bc9d2b71a663e178788280f3c3eae127d21b0b95777976b3eb17be40a702c244d0e5f833ff49dae6403ff44b131e66df8b88e33ab0a58e379f2c34bf5113c66b9ea8241fc7aa2b1fa53cf4ed3cdd91d407730c66fb039ef3a36d4050dde37d34e80bcfe02a48a6b14ae28227b1627b5ad07608a7763a531f2ffc96dff850e8c583461831b19feffc783bc1beab6301f647e9617d14c92c4b1d63f5147ccda56a35df8ca4806b8884c4aa3c3cc6a174fdc2232404822569c01aba686c1df5eecc059ba97e9688c8b16b70f0d24eacfdba15db1c71f72af1b2af85bd168f0b0800483f115eeccd9b02adf03bdd4a88eab03e43ce342877af2b61f9d3d85497cd1c6b96674f3d4f07f635bb26add1e36835e321d70263b1c04234e222124dad30ffb9f2a138e3ef453442df1af7e566890aedee568093aa922dd62db188aa8361c55503f8e2c2e6ba93de744b55c15260f15ec8e69bb01048ca1fa7bbbd26975bde80930a5b95054688a0ea73af0353cc84b997626a987cc06a517e18f91e02908829d4f4efc011b9867bd9bfe04c5f94e4b9261d30cc39982eb7b250f12aee2a4cce0484ff34eebba89bc6e35bd48d3968e4ca2d77527212017e202141900152f2fd8af0ac3aa456aae13276a13b9b9492a9a636e18244654b3245f07b20eb76b8e1cea8c55e5427f08a63a16b0a633af67c8e48ef8e53519041c9138176eb14b8782c6c2ee76146b8490b97978ee73cd0104e12f483be5a4af414404618e9f6633c55dda6f22252cb793d3d16fae4f0e1431434e7acc8fa2c009d4f6e345ade172313d558a4e61b4377e31b8ed4e28f7cd13a7fe3f72a409bc3bdabfe0ba47a6d861e21f64d2fac706dab18b3e546df4",
3370 attribution_data: "84986c936d26bfd3bb2d34d3ec62cfdb63e0032fdb3d9d75f3e5d456f73dffa7e35aab1db4f1bd3b98ff585caf004f656c51037a3f4e810d275f3f6aea0c8e3a125ebee5f374b6440bcb9bb2955ebf706f42be9999a62ed49c7a81fc73c0b4a16419fd6d334532f40bf179dd19afec21bd8519d5e6ebc3802501ef373bc378eee1f14a6fc5fab5b697c91ce31d5922199d1b0ad5ee12176aacafc7c81d54bc5b8fb7e63f3bfd40a3b6e21f985340cbd1c124c7f85f0369d1aa86ebc66def417107a7861131c8bcd73e8946f4fb54bfac87a2dc15bd7af642f32ae583646141e8875ef81ec9083d7e32d5f135131eab7a43803360434100ff67087762bbe3d6afe2034f5746b8c50e0c3c20dd62a4c174c38b1df7365dccebc7f24f19406649fbf48981448abe5c858bbd4bef6eb983ae7a23e9309fb33b5e7c0522554e88ca04b1d65fc190947dead8c0ccd32932976537d869b5ca53ed4945bccafab2a014ea4cbdc6b0250b25be66ba0afff2ff19c0058c68344fd1b9c472567147525b13b1bc27563e61310110935cf89fda0e34d0575e2389d57bdf2869398ca2965f64a6f04e1d1c2edf2082b97054264a47824dd1a9691c27902b39d57ae4a94dd6481954a9bd1b5cff4ab29ca221fa2bf9b28a362c9661206f896fc7cec563fb80aa5eaccb26c09fa4ef7a981e63028a9c4dac12f82ccb5bea090d56bbb1a4c431e315d9a169299224a8dbd099fb67ea61dfc604edf8a18ee742550b636836bb552dabb28820221bf8546331f32b0c143c1c89310c4fa2e1e0e895ce1a1eb0f43278fdb528131a3e32bfffe0c6de9006418f5309cba773ca38b6ad8507cc59445ccc0257506ebc16a4c01d4cd97e03fcf7a2049fea0db28447858f73b8e9fe98b391b136c9dc510288630a1f0af93b26a8891b857bfe4b818af99a1e011e6dbaa53982d29cf74ae7dffef45545279f19931708ed3eede5e82280eab908e8eb80abff3f1f023ab66869297b40da8496861dc455ac3abe1efa8a6f9e2c4eda48025d43a486a3f26f269743eaa30d6f0e1f48db6287751358a41f5b07aee0f098862e3493731fe2697acce734f004907c6f11eef189424fee52cd30ad708707eaf2e441f52bcf3d0c5440c1742458653c0c8a27b5ade784d9e09c8b47f1671901a29360e7e5e94946b9c75752a1a8d599d2a3e14ac81b84d42115cd688c8383a64fc6e7e1dc5568bb4837358ebe63207a4067af66b2027ad2ce8fb7ae3a452d40723a51fdf9f9c9913e8029a222cf81d12ad41e58860d75deb6de30ad"
3371 }
3372 ];
3373
3374 let failure_data = <Vec<u8>>::from_hex(FAILURE_DATA).unwrap();
3375
3376 let onion_keys = build_test_onion_keys();
3377 let mut onion_error = super::build_unencrypted_failure_packet(
3378 onion_keys[4].shared_secret.as_ref(),
3379 LocalHTLCFailureReason::IncorrectPaymentDetails,
3380 &failure_data,
3381 1,
3382 1024,
3383 );
3384
3385 let logger: Arc<TestLogger> = Arc::new(TestLogger::new());
3386
3387 super::crypt_failure_packet(onion_keys[4].shared_secret.as_ref(), &mut onion_error);
3388 EXPECTED_MESSAGES[0].assert_eq(&onion_error);
3389
3390 let mut mutated = false;
3391 let mutate_packet = |packet: &mut OnionErrorPacket, mutation_type: &MutationType| {
3392 match mutation_type {
3393 MutationType::FailureMessage(i) => {
3394 packet.data[*i] ^= 1;
3396 },
3397 MutationType::AttributionData(AttributionDataMutationType::HoldTimes(i)) => {
3398 packet.attribution_data.as_mut().unwrap().hold_times[*i] ^= 1;
3400 },
3401 MutationType::AttributionData(AttributionDataMutationType::Hmacs(i)) => {
3402 packet.attribution_data.as_mut().unwrap().hmacs[*i] ^= 1;
3404 },
3405 MutationType::DropAttributionData => {
3406 packet.attribution_data = None;
3408 },
3409 }
3410 };
3411
3412 if let Some(Mutation { node, ref mutation_type }) = mutation {
3413 if node == 4 {
3414 mutate_packet(&mut onion_error, mutation_type);
3415 mutated = true;
3416 }
3417 }
3418
3419 for idx in (0..4).rev() {
3420 let shared_secret = onion_keys[idx].shared_secret.as_ref();
3421 let hold_time = (5 - idx) as u32;
3422 process_failure_packet(&mut onion_error, shared_secret, hold_time);
3423 super::crypt_failure_packet(shared_secret, &mut onion_error);
3424
3425 if let Some(Mutation { node, ref mutation_type }) = mutation {
3426 if node == idx {
3427 mutate_packet(&mut onion_error, mutation_type);
3428 mutated = true;
3429 }
3430 }
3431
3432 if !mutated {
3433 let expected_messages = &EXPECTED_MESSAGES[4 - idx];
3434 expected_messages.assert_eq(&onion_error);
3435 }
3436 }
3437
3438 let ctx_full = Secp256k1::new();
3439 let path = build_test_path();
3440 let htlc_source = HTLCSource::OutboundRoute {
3441 path,
3442 session_priv: get_test_session_key(),
3443 first_hop_htlc_msat: 0,
3444 payment_id: PaymentId([1; 32]),
3445 bolt12_invoice: None,
3446 };
3447
3448 process_onion_failure(&ctx_full, &logger, &htlc_source, onion_error)
3449 }
3450
3451 #[test]
3454 fn test_success_hold_times() {
3455 fn assert_data(actual: &AttributionData, expected: &str) {
3456 let (expected_hold_times, expected_hmacs) =
3457 expected.split_at(MAX_HOPS * HOLD_TIME_LEN * 2);
3458
3459 println!(
3460 "{}{}",
3461 actual.hold_times.to_lower_hex_string(),
3462 actual.hmacs.to_lower_hex_string()
3463 );
3464
3465 assert_eq!(actual.hold_times.to_lower_hex_string(), expected_hold_times);
3466 assert_eq!(actual.hmacs.to_lower_hex_string(), expected_hmacs);
3467 }
3468
3469 const EXPECTED_MESSAGES: [&str; 5] = [
3471 "d77d0711b5f71d1d1be56bd88b3bb7ebc1792bb739ea7ebc1bc3b031b8bc2df3a50e25aeb99f47d7f7ab39e24187d3f4df9c4333463b053832ee9ac07274a5261b8b2a01fc09ce9ea7cd04d7b585dfb83299fb6570d71f793c1fcac0ef498766952c8c6840efa02a567d558a3cf6822b12476324b9b9efa03e5f8f26f81fa93daac46cbf00c98e69b6747cf69caaa2a71b025bd18830c4c54cd08f598cfde6197b3f2a951aba907c964c0f5d19a44e6d1d7279637321fa598adde927b3087d238f8b426ecde500d318617cdb7a56e6ce3520fc95be41a549973764e4dc483853ecc313947709f1b5199cb077d46e701fa633e11d3e13b03e9212c115ca6fa004b2f3dd912814693b705a561a06da54cdf603677a3abecdc22c7358c2de3cef771b366a568150aeecc86ad1990bb0f4e2865933b03ea0df87901bff467908273dc6cea31cbab0e2b8d398d10b001058c259ed221b7b55762f4c7e49c8c11a45a107b7a2c605c26dc5b0b10d719b1c844670102b2b6a36c43fe4753a78a483fc39166ae28420f112d50c10ee64ca69569a2f690712905236b7c2cb7ac8954f02922d2d918c56d42649261593c47b14b324a65038c3c5be8d3c403ce0c8f19299b1664bf077d7cf1636c4fb9685a8e58b7029fd0939fa07925a60bed339b23f973293598f595e75c8f9d455d7cebe4b5e23357c8bd47d66d6628b39427e37e0aecbabf46c11be6771f7136e108a143ae9bafba0fc47a51b6c7deef4cba54bae906398ee3162a41f2191ca386b628bde7e1dd63d1611aa01a95c456df337c763cb8c3a81a6013aa633739d8cd554c688102211725e6adad165adc1bcd429d020c51b4b25d2117e8bb27eb0cc7020f9070d4ad19ac31a76ebdf5f9246646aeadbfb9a3f1d75bd8237961e786302516a1a781780e8b73f58dc06f307e58bd0eb1d8f5c9111f01312974c1dc777a6a2d3834d8a2a40014e9818d0685cb3919f6b3b788ddc640b0ff9b1854d7098c7dd6f35196e902b26709640bc87935a3914869a807e8339281e9cedaaca99474c3e7bdd35050bb998ab4546f9900904e0e39135e861ff7862049269701081ebce32e4cca992c6967ff0fd239e38233eaf614af31e186635e9439ec5884d798f9174da6ff569d68ed5c092b78bd3f880f5e88a7a8ab36789e1b57b035fb6c32a6358f51f83e4e5f46220bcad072943df8bd9541a61b7dae8f30fa3dd5fb39b1fd9a0b8e802552b78d4ec306ecee15bfe6da14b29ba6d19ce5be4dd478bca74a52429cd5309d404655c3dec85c252",
3472 "1571e10db7f8aa9f8e7e99caaf9c892e106c817df1d8e3b7b0e39d1c48f631e473e17e205489dd7b3c634cac3be0825cbf01418cd46e83c24b8d9c207742db9a0f0e5bcd888086498159f08080ba7bf3ea029c0b493227c4e75a90f70340d9e21f00979fc7e4fb2078477c1a457ba242ed54b313e590b13a2a13bfeed753dab133c78059f460075b2594b4c31c50f31076f8f1a0f7ad0530d0fadaf2d86e505ff9755940ec0665f9e5bc58cad6e523091f94d0bcd3c6c65ca1a5d401128dcc5e14f9108b32e660017c13de598bcf9d403710857cccb0fb9c2a81bfd66bc4552e1132afa3119203a4aaa1e8839c1dab8cbdcde7b527aca3f54bde651aa9f3f2178829cee3f1c0b9292758a40cc63bd998fcd0d3ed4bdcaf1023267b8f8e44130a63ad15f76145936552381eabb6d684c0a3af6ba8efcf207cebaea5b7acdbb63f8e7221102409d10c23f0514dc9f4d0efb2264161a193a999a23e992632710580a0d320f676d367b9190721194514457761af05207cdab2b6328b1b3767eacb36a7ef4f7bd2e16762d13df188e0898b7410f62459458712a44bf594ae662fd89eb300abb6952ff8ad40164f2bcd7f86db5c7650b654b79046de55d51aa8061ce35f867a3e8f5bf98ad920be827101c64fb871d86e53a4b3c0455bfac5784168218aa72cbee86d9c750a9fa63c363a8b43d7bf4b2762516706a306f0aa3be1ec788b5e13f8b24837e53ac414f211e11c7a093cd9653dfa5fba4e377c79adfa5e841e2ddb6afc054fc715c05ddc6c8fc3e1ee3406e1ffceb2df77dc2f02652614d1bfcfaddebaa53ba919c7051034e2c7b7cfaabdf89f26e7f8e3f956d205dfab747ad0cb505b85b54a68439621b25832cbc2898919d0cd7c0a64cfd235388982dd4dd68240cb668f57e1d2619a656ed326f8c92357ee0d9acead3c20008bc5f04ca8059b55d77861c6d04dfc57cfba57315075acbe1451c96cf28e1e328e142890248d18f53b5d3513ce574dea7156cf596fdb3d909095ec287651f9cf1bcdc791c5938a5dd9b47e84c004d24ab3ae74492c7e8dcc1da15f65324be2672947ec82074cac8ce2b925bc555facbbf1b55d63ea6fbea6a785c97d4caf2e1dad9551b7f66c31caae5ebc7c0047e892f201308fcf452c588be0e63d89152113d87bf0dbd01603b4cdc7f0b724b0714a9851887a01f709408882e18230fe810b9fafa58a666654576d8eba3005f07221f55a6193815a672e5db56204053bc4286fa3db38250396309fd28011b5708a26a2d76c4a333b69b6bfd272fb",
3473 "34e34397b8621ec2f2b54dbe6c14073e267324cd60b152bce76aec8729a6ddefb61bc263be4b57bd592aae604a32bea69afe6ef4a6b573c26b17d69381ec1fc9b5aa769d148f2f1f8b5377a73840bb6dffc324ded0d1c00dc0c99e3dbc13273b2f89510af6410b525dd8836208abbbaae12753ae2276fa0ca49950374f94e187bf65cefcdd9dd9142074edc4bd0052d0eb027cb1ab6182497f9a10f9fe800b3228e3c088dab60081c807b30a67313667ca8c9e77b38b161a037cae8e973038d0fc4a97ea215914c6c4e23baf6ac4f0fb1e7fcc8aac3f6303658dae1f91588b535eb678e2200f45383c2590a55dc181a09f2209da72f79ae6745992c803310d39f960e8ecf327aed706e4b3e2704eeb9b304dc0e0685f5dcd0389ec377bdba37610ad556a0e957a413a56339dd3c40817214bced5802beee2ee545bdd713208751added5fc0eb2bc89a5aa2decb18ee37dac39f22a33b60cc1a369d24de9f3d2d8b63c039e248806de4e36a47c7a0aed30edd30c3d62debdf1ad82bf7aedd7edec413850d91c261e12beec7ad1586a9ad25b2db62c58ca17119d61dcc4f3e5c4520c42a8e384a45d8659b338b3a08f9e123a1d3781f5fc97564ccff2c1d97f06fa0150cfa1e20eacabefb0c339ec109336d207cc63d9170752fc58314c43e6d4a528fd0975afa85f3aa186ff1b6b8cb12c97ed4ace295b0ef5f075f0217665b8bb180246b87982d10f43c9866b22878106f5214e99188781180478b07764a5e12876ddcb709e0a0a8dd42cf004c695c6fc1669a6fd0e4a1ca54b024d0d80eac492a9e5036501f36fb25b72a054189294955830e43c18e55668337c8c6733abb09fc2d4ade18d5a853a2b82f7b4d77151a64985004f1d9218f2945b63c56fdebd1e96a2a7e49fa70acb4c39873947b83c191c10e9a8f40f60f3ad5a2be47145c22ea59ed3f5f4e61cb069e875fb67142d281d784bf925cc286eacc2c43e94d08da4924b83e58dbf2e43fa625bdd620eba6d9ce960ff17d14ed1f2dbee7d08eceb540fdc75ff06dabc767267658fad8ce99e2a3236e46d2deedcb51c3c6f81589357edebac9772a70b3d910d83cd1b9ce6534a011e9fa557b891a23b5d88afcc0d9856c6dabeab25eea55e9a248182229e4927f268fe5431672fcce52f434ca3d27d1a2136bae5770bb36920df12fbc01d0e8165610efa04794f414c1417f1d4059435c5385bfe2de83ce0e238d6fd2dbd3c0487c69843298577bfa480fe2a16ab2a0e4bc712cd8b5a14871cda61c993b6835303d9043d7689a",
3474 "74a4ea61339463642a2182758871b2ea724f31f531aa98d80f1c3043febca41d5ee52e8b1e127e61719a0d078db8909748d57839e58424b91f063c4fbc8a221bef261140e66a9b596ca6d420a973ad5431adfa8280a7355462fe50d4cac15cdfbd7a535c4b72a0b6d7d8a64cff3f719ff9b8be28036826342dc3bf3781efc70063d1e6fc79dff86334ae0564a5ab87bd61f8446465ef6713f8c4ef9d0200ebb375f90ee115216b469af42de554622df222858d30d733af1c9223e327ae09d9126be8baee6dd59a112d83a57cc6e0252104c11bc11705d384220eedd72f1a29a0597d97967e28b2ad13ba28b3d8a53c3613c1bb49fe9700739969ef1f795034ef9e2e983af2d3bbd6c637fb12f2f7dfc3aee85e08711e9b604106e95d7a4974e5b047674a6015792dae5d913681d84f71edd415910582e5d86590df2ecfd561dc6e1cdb08d3e10901312326a45fb0498a177319389809c6ba07a76cfad621e07b9af097730e94df92fbd311b2cb5da32c80ab5f14971b6d40f8e2ab202ac98bd8439790764a40bf309ea2205c1632610956495720030a25dc7118e0c868fdfa78c3e9ecce58215579a0581b3bafdb7dbbe53be9e904567fdc0ce1236aab5d22f1ebc18997e3ea83d362d891e04c5785fd5238326f767bce499209f8db211a50e1402160486e98e7235cf397dbb9ae19fd9b79ef589c821c6f99f28be33452405a003b33f4540fe0a41dfcc286f4d7cc10b70552ba7850869abadcd4bb7f256823face853633d6e2a999ac9fcd259c71d08e266db5d744e1909a62c0db673745ad9585949d108ab96640d2bc27fb4acac7fa8b170a30055a5ede90e004df9a44bdc29aeb4a6bec1e85dde1de6aaf01c6a5d12405d0bec22f49026cb23264f8c04b8401d3c2ab6f2e109948b6193b3bec27adfe19fb8afb8a92364d6fc5b219e8737d583e7ff3a4bcb75d53edda3bf3f52896ac36d8a877ad9f296ea6c045603fc62ac4ae41272bde85ef7c3b3fd3538aacfd5b025fefbe277c2906821ecb20e6f75ea479fa3280f9100fb0089203455c56b6bc775e5c2f0f58c63edd63fa3eec0b40da4b276d0d41da2ec0ead865a98d12bc694e23d8eaadd2b4d0ee88e9570c88fb878930f492e036d27998d593e47763927ff7eb80b188864a3846dd2238f7f95f4090ed399ae95deaeb37abca1cf37c397cc12189affb42dca46b4ff6988eb8c060691d155302d448f50ff70a794d97c0408f8cee9385d6a71fa412e36edcb22dbf433db9db4779f27b682ee17fc05e70c8e794b9f7f6d1",
3475 "84986c936d26bfd3bb2d34d3ec62cfdb63e0032fdb3d9d75f3e5d456f73dffa7e35aab1db4f1bd3b98ff585caf004f656c51037a3f4e810d275f3f6aea0c8e3a125ebee5f374b6440bcb9bb2955ebf70c06d64090f9f6cf098200305f7f4305ba9e1350a0c3f7dab4ccf35b8399b9650d8e363bf83d3a0a09706433f0adae6562eb338b21ea6f21329b3775905e59187c325c9cbf589f5da5e915d9e5ad1d21aa1431f9bdc587185ed8b5d4928e697e67cc96bee6d5354e3764cede3f385588fa665310356b2b1e68f8bd30c75d395405614a40a587031ebd6ace60dfb7c6dd188b572bd8e3e9a47b06c2187b528c5ed35c32da5130a21cd881138a5fcac806858ce6c596d810a7492eb261bcc91cead1dae75075b950c2e81cecf7e5fdb2b51df005d285803201ce914dfbf3218383829a0caa8f15486dd801133f1ed7edec436730b0ec98f48732547927229ac80269fcdc5e4f4db264274e940178732b429f9f0e582c559f994a7cdfb76c93ffc39de91ff936316726cc561a6520d47b2cd487299a96322dadc463ef06127fc63902ff9cc4f265e2fbd9de3fa5e48b7b51aa0850580ef9f3b5ebb60c6c3216c5a75a93e82936113d9cad57ae4a94dd6481954a9bd1b5cff4ab29ca221fa2bf9b28a362c9661206f896fc7cec563fb80aa5eaccb26c09fa4ef7a981e63028a9c4dac12f82ccb5bea090d56bbb1a4c431e315d9a169299224a8dbd099fb67ea61dfc604edf8a18ee742550b636836bb552dabb28820221bf8546331f32b0c143c1c89310c4fa2e1e0e895ce1a1eb0f43278fdb528131a3e32bfffe0c6de9006418f5309cba773ca38b6ad8507cc59445ccc0257506ebc16a4c01d4cd97e03fcf7a2049fea0db28447858f73b8e9fe98b391b136c9dc510288630a1f0af93b26a8891b857bfe4b818af99a1e011e6dbaa53982d29cf74ae7dffef45545279f19931708ed3eede5e82280eab908e8eb80abff3f1f023ab66869297b40da8496861dc455ac3abe1efa8a6f9e2c4eda48025d43a486a3f26f269743eaa30d6f0e1f48db6287751358a41f5b07aee0f098862e3493731fe2697acce734f004907c6f11eef189424fee52cd30ad708707eaf2e441f52bcf3d0c5440c1742458653c0c8a27b5ade784d9e09c8b47f1671901a29360e7e5e94946b9c75752a1a8d599d2a3e14ac81b84d42115cd688c8383a64fc6e7e1dc5568bb4837358ebe63207a4067af66b2027ad2ce8fb7ae3a452d40723a51fdf9f9c9913e8029a222cf81d12ad41e58860d75deb6de30ad",
3476 ];
3477
3478 let onion_keys = build_test_onion_keys();
3479
3480 let mut attribution_data = AttributionData::new();
3481 attribution_data.update(&[], onion_keys[4].shared_secret.as_ref(), 1);
3482
3483 let logger: Arc<TestLogger> = Arc::new(TestLogger::new());
3484
3485 attribution_data.crypt(onion_keys[4].shared_secret.as_ref());
3486
3487 assert_data(&attribution_data, EXPECTED_MESSAGES[0]);
3488
3489 for idx in (0..4).rev() {
3490 let shared_secret = onion_keys[idx].shared_secret.as_ref();
3491 let hold_time = (5 - idx) as u32;
3492
3493 attribution_data.shift_right();
3494 attribution_data.update(&[], shared_secret, hold_time);
3495 attribution_data.crypt(shared_secret);
3496
3497 assert_data(&attribution_data, EXPECTED_MESSAGES[4 - idx]);
3498 }
3499
3500 let ctx_full = Secp256k1::new();
3501 let path = build_test_path();
3502 let hold_times = decode_fulfill_attribution_data(
3503 &ctx_full,
3504 &logger,
3505 &path,
3506 &get_test_session_key(),
3507 attribution_data.clone(),
3508 );
3509
3510 assert_eq!(hold_times, [5, 4, 3, 2, 1])
3511 }
3512
3513 fn build_trampoline_test_path() -> Path {
3514 Path {
3515 hops: vec![
3516 RouteHop {
3518 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()).unwrap(),
3519 node_features: NodeFeatures::empty(),
3520 short_channel_id: 0,
3521 channel_features: ChannelFeatures::empty(),
3522 fee_msat: 3_000,
3523 cltv_expiry_delta: 24,
3524 maybe_announced_channel: false,
3525 },
3526
3527 RouteHop {
3529 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(),
3530 node_features: NodeFeatures::empty(),
3531 short_channel_id: (572330 << 40) + (42 << 16) + 2821,
3532 channel_features: ChannelFeatures::empty(),
3533 fee_msat: 153_000,
3534 cltv_expiry_delta: 0,
3535 maybe_announced_channel: false,
3536 },
3537 ],
3538 blinded_tail: Some(BlindedTail {
3539 trampoline_hops: vec![
3540 TrampolineHop {
3542 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(),
3543 node_features: Features::empty(),
3544 fee_msat: 2_500,
3545 cltv_expiry_delta: 24,
3546 },
3547
3548 TrampolineHop {
3550 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145").unwrap()).unwrap(),
3551 node_features: Features::empty(),
3552 fee_msat: 2_500,
3553 cltv_expiry_delta: 24,
3554 },
3555
3556 TrampolineHop {
3558 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()).unwrap(),
3559 node_features: Features::empty(),
3560 fee_msat: 150_500,
3561 cltv_expiry_delta: 36,
3562 },
3563 ],
3564
3565 hops: vec![
3567 BlindedHop {
3569 blinded_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex("0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be").unwrap()).unwrap(),
3570 encrypted_payload: vec![],
3571 }
3572 ],
3573 blinding_point: PublicKey::from_slice(&<Vec<u8>>::from_hex("02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e").unwrap()).unwrap(),
3574 excess_final_cltv_expiry_delta: 0,
3575 final_value_msat: 150_000_000,
3576 }),
3577 }
3578 }
3579
3580 #[test]
3581 fn test_trampoline_onion_error_cryptography() {
3582 let secp_ctx = Secp256k1::new();
3585 let logger: Arc<TestLogger> = Arc::new(TestLogger::new());
3586 let dummy_amt_msat = 150_000_000;
3587
3588 {
3589 let trampoline_session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
3592 let outer_session_priv = SecretKey::from_slice(&[4; 32]).unwrap();
3593
3594 let error_packet_hex = "f8941a320b8fde4ad7b9b920c69cbf334114737497d93059d77e591eaa78d6334d3e2aeefcb0cc83402eaaf91d07d695cd895d9cad1018abdaf7d2a49d7657b1612729db7f393f0bb62b25afaaaa326d72a9214666025385033f2ec4605dcf1507467b5726d806da180ea224a7d8631cd31b0bdd08eead8bfe14fc8c7475e17768b1321b54dd4294aecc96da391efe0ca5bd267a45ee085c85a60cf9a9ac152fa4795fff8700a3ea4f848817f5e6943e855ab2e86f6929c9e885d8b20c49b14d2512c59ed21f10bd38691110b0d82c00d9fa48a20f10c7550358724c6e8e2b966e56a0aadf458695b273768062fa7c6e60eb72d4cdc67bf525c194e4a17fdcaa0e9d80480b586bf113f14eea530b6728a1c53fe5cee092e24a90f21f4b764015e7ed5e23";
3595 let error_packet = OnionErrorPacket {
3596 data: <Vec<u8>>::from_hex(error_packet_hex).unwrap(),
3597 attribution_data: None,
3598 };
3599 let decrypted_failure = process_onion_failure_inner(
3600 &secp_ctx,
3601 &logger,
3602 &build_trampoline_test_path(),
3603 &outer_session_priv,
3604 Some(&trampoline_session_priv),
3605 error_packet,
3606 );
3607 assert_eq!(
3608 decrypted_failure.onion_error_code,
3609 Some(LocalHTLCFailureReason::IncorrectPaymentDetails),
3610 );
3611 }
3612
3613 {
3614 let session_priv = get_test_session_key();
3616 let path = build_trampoline_test_path();
3617
3618 let trampoline_onion_keys = construct_trampoline_onion_keys(
3619 &secp_ctx,
3620 &path.blinded_tail.as_ref().unwrap(),
3621 &session_priv,
3622 );
3623
3624 let outer_onion_keys = {
3625 let session_priv_hash = Sha256::hash(&session_priv.secret_bytes()).to_byte_array();
3626 let outer_session_priv = SecretKey::from_slice(&session_priv_hash[..]).unwrap();
3627 construct_onion_keys(&Secp256k1::new(), &path, &outer_session_priv)
3628 };
3629
3630 let htlc_source = HTLCSource::OutboundRoute {
3631 path,
3632 session_priv,
3633 first_hop_htlc_msat: dummy_amt_msat,
3634 payment_id: PaymentId([1; 32]),
3635 bolt12_invoice: None,
3636 };
3637
3638 {
3639 let error_code = LocalHTLCFailureReason::TemporaryNodeFailure;
3641 let mut first_hop_error_packet = build_unencrypted_failure_packet(
3642 outer_onion_keys[0].shared_secret.as_ref(),
3643 error_code,
3644 &[0; 0],
3645 0,
3646 DEFAULT_MIN_FAILURE_PACKET_LEN,
3647 );
3648
3649 crypt_failure_packet(
3650 outer_onion_keys[0].shared_secret.as_ref(),
3651 &mut first_hop_error_packet,
3652 );
3653
3654 let decrypted_failure =
3655 process_onion_failure(&secp_ctx, &logger, &htlc_source, first_hop_error_packet);
3656 assert_eq!(decrypted_failure.onion_error_code, Some(error_code));
3657 };
3658
3659 {
3660 let error_code = 0x2003.into();
3662 let mut trampoline_outer_hop_error_packet = build_unencrypted_failure_packet(
3663 outer_onion_keys[1].shared_secret.as_ref(),
3664 error_code,
3665 &[0; 0],
3666 0,
3667 DEFAULT_MIN_FAILURE_PACKET_LEN,
3668 );
3669 trampoline_outer_hop_error_packet.attribution_data = None;
3670
3671 crypt_failure_packet(
3672 outer_onion_keys[1].shared_secret.as_ref(),
3673 &mut trampoline_outer_hop_error_packet,
3674 );
3675
3676 crypt_failure_packet(
3677 outer_onion_keys[0].shared_secret.as_ref(),
3678 &mut trampoline_outer_hop_error_packet,
3679 );
3680
3681 let decrypted_failure = process_onion_failure(
3682 &secp_ctx,
3683 &logger,
3684 &htlc_source,
3685 trampoline_outer_hop_error_packet,
3686 );
3687 assert_eq!(decrypted_failure.onion_error_code, Some(error_code));
3688 };
3689
3690 {
3691 let error_code = 0x2004.into();
3693 let mut trampoline_inner_hop_error_packet = build_unencrypted_failure_packet(
3694 trampoline_onion_keys[0].shared_secret.as_ref(),
3695 error_code,
3696 &[0; 0],
3697 0,
3698 DEFAULT_MIN_FAILURE_PACKET_LEN,
3699 );
3700 trampoline_inner_hop_error_packet.attribution_data = None;
3701
3702 crypt_failure_packet(
3703 trampoline_onion_keys[0].shared_secret.as_ref(),
3704 &mut trampoline_inner_hop_error_packet,
3705 );
3706
3707 crypt_failure_packet(
3708 outer_onion_keys[1].shared_secret.as_ref(),
3709 &mut trampoline_inner_hop_error_packet,
3710 );
3711
3712 crypt_failure_packet(
3713 outer_onion_keys[0].shared_secret.as_ref(),
3714 &mut trampoline_inner_hop_error_packet,
3715 );
3716
3717 let decrypted_failure = process_onion_failure(
3718 &secp_ctx,
3719 &logger,
3720 &htlc_source,
3721 trampoline_inner_hop_error_packet,
3722 );
3723 assert_eq!(decrypted_failure.onion_error_code, Some(error_code));
3724 }
3725
3726 {
3727 let error_code = 0x2005.into();
3729 let mut trampoline_second_hop_error_packet = build_unencrypted_failure_packet(
3730 trampoline_onion_keys[1].shared_secret.as_ref(),
3731 error_code,
3732 &[0; 0],
3733 0,
3734 DEFAULT_MIN_FAILURE_PACKET_LEN,
3735 );
3736 trampoline_second_hop_error_packet.attribution_data = None;
3737
3738 crypt_failure_packet(
3739 trampoline_onion_keys[1].shared_secret.as_ref(),
3740 &mut trampoline_second_hop_error_packet,
3741 );
3742
3743 crypt_failure_packet(
3744 trampoline_onion_keys[0].shared_secret.as_ref(),
3745 &mut trampoline_second_hop_error_packet,
3746 );
3747
3748 crypt_failure_packet(
3749 outer_onion_keys[1].shared_secret.as_ref(),
3750 &mut trampoline_second_hop_error_packet,
3751 );
3752
3753 crypt_failure_packet(
3754 outer_onion_keys[0].shared_secret.as_ref(),
3755 &mut trampoline_second_hop_error_packet,
3756 );
3757
3758 let decrypted_failure = process_onion_failure(
3759 &secp_ctx,
3760 &logger,
3761 &htlc_source,
3762 trampoline_second_hop_error_packet,
3763 );
3764 assert_eq!(decrypted_failure.onion_error_code, Some(error_code));
3765 }
3766 }
3767 }
3768
3769 #[test]
3770 fn test_non_attributable_failure_packet_onion() {
3771 let packet = vec![1u8; 292];
3773 let onion_error_packet =
3774 OnionErrorPacket { data: packet, attribution_data: Some(AttributionData::new()) };
3775
3776 let logger: TestLogger = TestLogger::new();
3778 let decrypted_failure = test_failure_attribution(&logger, onion_error_packet);
3779 assert_eq!(decrypted_failure.attribution_failed_channel, Some(0));
3780 }
3781
3782 #[test]
3783 fn test_long_route_attributable_failure() {
3784 let secp_ctx = Secp256k1::new();
3787 const LEGACY_MAX_HOPS: usize = 27;
3788
3789 let mut hops = Vec::new();
3791 for i in 0..LEGACY_MAX_HOPS {
3792 let mut secret_bytes = [0; 32];
3793 secret_bytes[0] = (i + 1) as u8;
3794 let secret_key = SecretKey::from_slice(&secret_bytes).unwrap();
3795 let pubkey = secret_key.public_key(&secp_ctx);
3796
3797 hops.push(RouteHop {
3798 pubkey,
3799 channel_features: ChannelFeatures::empty(),
3800 node_features: NodeFeatures::empty(),
3801 short_channel_id: i as u64,
3802 fee_msat: 0,
3803 cltv_expiry_delta: 0,
3804 maybe_announced_channel: true,
3805 });
3806 }
3807 let path = Path { hops, blinded_tail: None };
3808
3809 let session_key = get_test_session_key();
3811 let onion_keys: Vec<_> =
3812 construct_onion_keys_generic(&secp_ctx, &path.hops, None, &session_key)
3813 .map(|(key, ..)| key)
3814 .collect();
3815
3816 let logger = TestLogger::new();
3818 let htlc_source = HTLCSource::OutboundRoute {
3819 path,
3820 session_priv: session_key,
3821 first_hop_htlc_msat: 0,
3822 payment_id: PaymentId([1; 32]),
3823 bolt12_invoice: None,
3824 };
3825
3826 for failure_pos in 0..LEGACY_MAX_HOPS {
3828 let packet = vec![1u8; 292];
3830 let mut onion_error =
3831 OnionErrorPacket { data: packet, attribution_data: Some(AttributionData::new()) };
3832
3833 for i in (0..failure_pos).rev() {
3835 let shared_secret = onion_keys[i].secret_bytes();
3836 process_failure_packet(&mut onion_error, &shared_secret, 0);
3837 super::crypt_failure_packet(&shared_secret, &mut onion_error);
3838 }
3839
3840 let decrypted_failure =
3842 process_onion_failure(&secp_ctx, &&logger, &htlc_source, onion_error);
3843
3844 let expected_failed_chan =
3846 if failure_pos < MAX_HOPS { Some(failure_pos as u64) } else { None };
3847 assert_eq!(decrypted_failure.attribution_failed_channel, expected_failed_chan);
3848 }
3849 }
3850
3851 #[test]
3852 fn test_unreadable_failure_packet_onion() {
3853 let onion_keys: Vec<OnionKeys> = build_test_onion_keys();
3855 let shared_secret = onion_keys[0].shared_secret.as_ref();
3856 let um = gen_um_from_shared_secret(&shared_secret);
3857
3858 let mut packet = [0u8; 33];
3860
3861 let mut hmac = HmacEngine::<Sha256>::new(&um);
3862 hmac.input(&packet[32..]);
3863 let hmac = Hmac::from_engine(hmac).to_byte_array();
3864 packet[..32].copy_from_slice(&hmac);
3865
3866 let mut onion_error_packet = OnionErrorPacket {
3867 data: packet.to_vec(),
3868 attribution_data: Some(AttributionData::new()),
3869 };
3870 onion_error_packet
3871 .attribution_data
3872 .as_mut()
3873 .unwrap()
3874 .add_hmacs(shared_secret, &onion_error_packet.data);
3875 crypt_failure_packet(shared_secret, &mut onion_error_packet);
3876
3877 let logger: TestLogger = TestLogger::new();
3879 let decrypted_failure = test_failure_attribution(&logger, onion_error_packet);
3880 assert_eq!(decrypted_failure.short_channel_id, Some(0));
3881
3882 logger.assert_log_contains("lightning::ln::onion_utils", "Unreadable failure", 1);
3883 }
3884
3885 #[test]
3886 fn test_missing_error_code() {
3887 let onion_keys: Vec<OnionKeys> = build_test_onion_keys();
3889 let shared_secret = onion_keys[0].shared_secret.as_ref();
3890 let um = gen_um_from_shared_secret(&shared_secret);
3891
3892 let failuremsg = vec![1];
3893 let pad = Vec::new();
3894 let mut packet = msgs::DecodedOnionErrorPacket { hmac: [0; 32], failuremsg, pad };
3895
3896 let mut hmac = HmacEngine::<Sha256>::new(&um);
3897 hmac.input(&packet.encode()[32..]);
3898 packet.hmac = Hmac::from_engine(hmac).to_byte_array();
3899
3900 let mut onion_error_packet = OnionErrorPacket {
3901 data: packet.encode(),
3902 attribution_data: Some(AttributionData::new()),
3903 };
3904 onion_error_packet
3905 .attribution_data
3906 .as_mut()
3907 .unwrap()
3908 .add_hmacs(shared_secret, &onion_error_packet.data);
3909 crypt_failure_packet(shared_secret, &mut onion_error_packet);
3910
3911 let logger = TestLogger::new();
3912 let decrypted_failure = test_failure_attribution(&logger, onion_error_packet);
3913 assert_eq!(decrypted_failure.short_channel_id, Some(0));
3914
3915 logger.assert_log_contains(
3916 "lightning::ln::onion_utils",
3917 "Missing error code in failure",
3918 1,
3919 );
3920 }
3921
3922 fn test_failure_attribution(
3923 logger: &TestLogger, packet: OnionErrorPacket,
3924 ) -> DecodedOnionFailure {
3925 let ctx_full = Secp256k1::new();
3926 let path = build_test_path();
3927 let htlc_source = HTLCSource::OutboundRoute {
3928 path,
3929 session_priv: get_test_session_key(),
3930 first_hop_htlc_msat: 0,
3931 payment_id: PaymentId([1; 32]),
3932 bolt12_invoice: None,
3933 };
3934
3935 let decrypted_failure = process_onion_failure(&ctx_full, &logger, &htlc_source, packet);
3936
3937 decrypted_failure
3938 }
3939
3940 struct RawOnionHopData {
3941 data: Vec<u8>,
3942 }
3943 impl RawOnionHopData {
3944 fn new(orig: msgs::OutboundOnionPayload) -> Self {
3945 Self { data: orig.encode() }
3946 }
3947 }
3948 impl Writeable for RawOnionHopData {
3949 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
3950 writer.write_all(&self.data[..])
3951 }
3952 }
3953
3954 #[test]
3955 fn max_length_with_no_cltv_limit() {
3956 let recipient = PublicKey::from_slice(&[2; 33]).unwrap();
3959 let mut route_params = RouteParameters {
3960 payment_params: PaymentParameters::for_keysend(recipient, u32::MAX, true),
3961 final_value_msat: u64::MAX,
3962 max_total_routing_fee_msat: Some(u64::MAX),
3963 };
3964 route_params.payment_params.max_total_cltv_expiry_delta = u32::MAX;
3965 let recipient_onion = RecipientOnionFields::spontaneous_empty();
3966 set_max_path_length(&mut route_params, &recipient_onion, None, None, 42).unwrap();
3967 }
3968
3969 #[test]
3970 fn test_failure_packet_max_size() {
3971 let failure_data = vec![0; 64531];
3985
3986 let shared_secret = [0; 32];
3987 let onion_error = super::build_unencrypted_failure_packet(
3988 &shared_secret,
3989 LocalHTLCFailureReason::TemporaryNodeFailure,
3990 &failure_data,
3991 0,
3992 DEFAULT_MIN_FAILURE_PACKET_LEN,
3993 );
3994
3995 let msg = UpdateFailHTLC {
3996 channel_id: ChannelId([0; 32]),
3997 htlc_id: 0,
3998 reason: onion_error.data,
3999 attribution_data: onion_error.attribution_data,
4000 };
4001
4002 let mut buffer = Vec::new();
4003 msg.write(&mut buffer).unwrap();
4004
4005 assert_eq!(buffer.len(), 65535);
4006 }
4007}