Support failing blinded non-intro HTLCs after RAA processing.
[rust-lightning] / lightning / src / ln / onion_utils.rs
index 08fe7a73ae6f225df9ca9f873e8da1407689c3d1..b7da2fd882d516d559e5f6e3e8a26ffe379eeddb 100644 (file)
@@ -242,6 +242,8 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o
 /// the hops can be of variable length.
 pub(crate) const ONION_DATA_LEN: usize = 20*65;
 
+pub(super) const INVALID_ONION_BLINDING: u16 = 0x8000 | 0x4000 | 24;
+
 #[inline]
 fn shift_slice_right(arr: &mut [u8], amt: usize) {
        for i in (amt..arr.len()).rev() {
@@ -502,8 +504,21 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(
                                Some(hop) => hop,
                                None => {
                                        // The failing hop is within a multi-hop blinded path.
-                                       error_code_ret = Some(BADONION | PERM | 24); // invalid_onion_blinding
-                                       error_packet_ret = Some(vec![0; 32]);
+                                       #[cfg(not(test))] {
+                                               error_code_ret = Some(BADONION | PERM | 24); // invalid_onion_blinding
+                                               error_packet_ret = Some(vec![0; 32]);
+                                       }
+                                       #[cfg(test)] {
+                                               // Actually parse the onion error data in tests so we can check that blinded hops fail
+                                               // back correctly.
+                                               let err_packet = decrypt_onion_error_packet(
+                                                       &mut encrypted_packet, shared_secret
+                                               ).unwrap();
+                                               error_code_ret =
+                                                       Some(u16::from_be_bytes(err_packet.failuremsg.get(0..2).unwrap().try_into().unwrap()));
+                                               error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
+                                       }
+
                                        res = Some(FailureLearnings {
                                                network_update: None, short_channel_id: None, payment_failed_permanently: false
                                        });
@@ -725,9 +740,11 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(
 }
 
 #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
+#[cfg_attr(test, derive(PartialEq))]
 pub(super) struct HTLCFailReason(HTLCFailReasonRepr);
 
 #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
+#[cfg_attr(test, derive(PartialEq))]
 enum HTLCFailReasonRepr {
        LightningError {
                err: msgs::OnionErrorPacket,
@@ -923,9 +940,11 @@ pub(crate) enum OnionDecodeErr {
 
 pub(crate) fn decode_next_payment_hop<NS: Deref>(
        shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: PaymentHash,
-       node_signer: &NS,
+       blinding_point: Option<PublicKey>, node_signer: &NS,
 ) -> Result<Hop, OnionDecodeErr> where NS::Target: NodeSigner {
-       match decode_next_hop(shared_secret, hop_data, hmac_bytes, Some(payment_hash), node_signer) {
+       match decode_next_hop(
+               shared_secret, hop_data, hmac_bytes, Some(payment_hash), (blinding_point, node_signer)
+       ) {
                Ok((next_hop_data, None)) => Ok(Hop::Receive(next_hop_data)),
                Ok((next_hop_data, Some((next_hop_hmac, FixedSizeOnionPacket(new_packet_bytes))))) => {
                        Ok(Hop::Forward {