Fix blinded recipient fail on receive reqs violation
authorValentine Wallace <vwallace@protonmail.com>
Tue, 24 Oct 2023 20:45:24 +0000 (16:45 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Tue, 12 Dec 2023 23:38:59 +0000 (18:38 -0500)
If a blinded HTLC does not satisfy the receiver's requirements, e.g. bad CLTV
or amount, they should malformed-fail backwards with error code
INVALID_ONION_BLINDING and a zeroed out onion hash per BOLt 4.

lightning/src/ln/blinded_payment_tests.rs
lightning/src/ln/channelmanager.rs

index 2ac66d5e8261237390424815c538893b89eba535..72df4e158519988980f3355e6a75403d878ffe51 100644 (file)
@@ -464,12 +464,16 @@ enum ReceiveCheckFail {
        RecipientFail,
        // Failure to decode the recipient's onion payload.
        OnionDecodeFail,
+       // The incoming HTLC did not satisfy our requirements; in this case it underpaid us according to
+       // the expected receive amount in the onion.
+       ReceiveRequirements,
 }
 
 #[test]
 fn multi_hop_receiver_fail() {
        do_multi_hop_receiver_fail(ReceiveCheckFail::RecipientFail);
        do_multi_hop_receiver_fail(ReceiveCheckFail::OnionDecodeFail);
+       do_multi_hop_receiver_fail(ReceiveCheckFail::ReceiveRequirements);
 }
 
 fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
@@ -554,7 +558,14 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
                        nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), update_add);
                        check_added_monitors!(nodes[2], 0);
                        do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true);
-               }
+               },
+               ReceiveCheckFail::ReceiveRequirements => {
+                       let update_add = &mut payment_event_1_2.msgs[0];
+                       update_add.amount_msat -= 1;
+                       nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), update_add);
+                       check_added_monitors!(nodes[2], 0);
+                       do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true);
+               },
        }
 
        let updates_2_1 = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
index bf02015faf5f137f7db51364224c8a63e0602d6f..153e39911990eabde70278fa59f87a65ec94785a 100644 (file)
@@ -3192,6 +3192,16 @@ where
                                {
                                        let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id));
                                        log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg);
+                                       if msg.blinding_point.is_some() {
+                                               return PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed(
+                                                       msgs::UpdateFailMalformedHTLC {
+                                                               channel_id: msg.channel_id,
+                                                               htlc_id: msg.htlc_id,
+                                                               sha256_of_onion: [0; 32],
+                                                               failure_code: INVALID_ONION_BLINDING,
+                                                       }
+                                               ))
+                                       }
                                        return PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
                                                channel_id: msg.channel_id,
                                                htlc_id: msg.htlc_id,