Merge pull request #132 from TheBlueMatt/2018-08-bolt-4-spec-return-fail
[rust-lightning] / src / ln / channelmanager.rs
index 3a98cd5a17647fb5a4a036abf5814411018bed22..6275713b589043142626fd2cbd582b0a3e456cee 100644 (file)
@@ -50,11 +50,17 @@ mod channel_held_info {
                pub(super) outgoing_cltv_value: u32,
        }
 
+       #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
+       pub enum HTLCFailureMsg {
+               Relay(msgs::UpdateFailHTLC),
+               Malformed(msgs::UpdateFailMalformedHTLC),
+       }
+
        /// Stores whether we can't forward an HTLC or relevant forwarding info
        #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
        pub enum PendingHTLCStatus {
                Forward(PendingForwardHTLCInfo),
-               Fail(msgs::UpdateFailHTLC),
+               Fail(HTLCFailureMsg),
        }
 
        #[cfg(feature = "fuzztarget")]
@@ -619,7 +625,7 @@ impl ChannelManager {
 
                Ok(msgs::OnionPacket{
                        version: 0,
-                       public_key: onion_keys.first().unwrap().ephemeral_pubkey,
+                       public_key: Ok(onion_keys.first().unwrap().ephemeral_pubkey),
                        hop_data: packet_data,
                        hmac: hmac_res,
                })
@@ -675,10 +681,7 @@ impl ChannelManager {
                ChannelManager::encrypt_failure_packet(shared_secret, &failure_packet.encode()[..])
        }
 
-       fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, SharedSecret, MutexGuard<ChannelHolder>) {
-               let shared_secret = SharedSecret::new(&self.secp_ctx, &msg.onion_routing_packet.public_key, &self.our_network_key);
-               let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret);
-
+       fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, Option<SharedSecret>, MutexGuard<ChannelHolder>) {
                macro_rules! get_onion_hash {
                        () => {
                                {
@@ -691,6 +694,19 @@ impl ChannelManager {
                        }
                }
 
+               if let Err(_) = msg.onion_routing_packet.public_key {
+                       log_info!(self, "Failed to accept/forward incoming HTLC with invalid ephemeral pubkey");
+                       return (PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
+                               channel_id: msg.channel_id,
+                               htlc_id: msg.htlc_id,
+                               sha256_of_onion: get_onion_hash!(),
+                               failure_code: 0x8000 | 0x4000 | 6,
+                       })), None, self.channel_state.lock().unwrap());
+               }
+
+               let shared_secret = SharedSecret::new(&self.secp_ctx, &msg.onion_routing_packet.public_key.unwrap(), &self.our_network_key);
+               let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret);
+
                let mut channel_state = None;
                macro_rules! return_err {
                        ($msg: expr, $err_code: expr, $data: expr) => {
@@ -699,11 +715,11 @@ impl ChannelManager {
                                        if channel_state.is_none() {
                                                channel_state = Some(self.channel_state.lock().unwrap());
                                        }
-                                       return (PendingHTLCStatus::Fail(msgs::UpdateFailHTLC {
+                                       return (PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
                                                channel_id: msg.channel_id,
                                                htlc_id: msg.htlc_id,
                                                reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, $err_code, $data),
-                                       }), shared_secret, channel_state.unwrap());
+                                       })), Some(shared_secret), channel_state.unwrap());
                                }
                        }
                }
@@ -770,7 +786,7 @@ impl ChannelManager {
                                chacha.process(&msg.onion_routing_packet.hop_data[65..], &mut new_packet_data[0..19*65]);
                                chacha.process(&ChannelManager::ZERO[0..65], &mut new_packet_data[19*65..]);
 
-                               let mut new_pubkey = msg.onion_routing_packet.public_key.clone();
+                               let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap();
 
                                let blinding_factor = {
                                        let mut sha = Sha256::new();
@@ -780,26 +796,19 @@ impl ChannelManager {
                                        sha.result(&mut res);
                                        match SecretKey::from_slice(&self.secp_ctx, &res) {
                                                Err(_) => {
-                                                       // Return temporary node failure as its technically our issue, not the
-                                                       // channel's issue.
-                                                       return_err!("Blinding factor is an invalid private key", 0x2000 | 2, &[0;0]);
+                                                       return_err!("Blinding factor is an invalid private key", 0x8000 | 0x4000 | 6, &get_onion_hash!());
                                                },
                                                Ok(key) => key
                                        }
                                };
 
-                               match new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor) {
-                                       Err(_) => {
-                                               // Return temporary node failure as its technically our issue, not the
-                                               // channel's issue.
-                                               return_err!("New blinding factor is an invalid private key", 0x2000 | 2, &[0;0]);
-                                       },
-                                       Ok(_) => {}
-                               };
+                               if let Err(_) = new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor) {
+                                       return_err!("New blinding factor is an invalid private key", 0x8000 | 0x4000 | 6, &get_onion_hash!());
+                               }
 
                                let outgoing_packet = msgs::OnionPacket {
                                        version: 0,
-                                       public_key: new_pubkey,
+                                       public_key: Ok(new_pubkey),
                                        hop_data: new_packet_data,
                                        hmac: next_hop_data.hmac.clone(),
                                };
@@ -846,7 +855,7 @@ impl ChannelManager {
                        }
                }
 
-               (pending_forward_info, shared_secret, channel_state.unwrap())
+               (pending_forward_info, Some(shared_secret), channel_state.unwrap())
        }
 
        /// only fails if the channel does not yet have an assigned short_id
@@ -958,6 +967,7 @@ impl ChannelManager {
                                update_add_htlcs: vec![update_add],
                                update_fulfill_htlcs: Vec::new(),
                                update_fail_htlcs: Vec::new(),
+                               update_fail_malformed_htlcs: Vec::new(),
                                commitment_signed,
                        },
                });
@@ -1102,6 +1112,7 @@ impl ChannelManager {
                                                                update_add_htlcs: add_htlc_msgs,
                                                                update_fulfill_htlcs: Vec::new(),
                                                                update_fail_htlcs: Vec::new(),
+                                                               update_fail_malformed_htlcs: Vec::new(),
                                                                commitment_signed: commitment_msg,
                                                        },
                                                }));
@@ -1225,6 +1236,7 @@ impl ChannelManager {
                                                                update_add_htlcs: Vec::new(),
                                                                update_fulfill_htlcs: Vec::new(),
                                                                update_fail_htlcs: vec![msg],
+                                                               update_fail_malformed_htlcs: Vec::new(),
                                                                commitment_signed: commitment_msg,
                                                        },
                                                });
@@ -1324,6 +1336,7 @@ impl ChannelManager {
                                                        update_add_htlcs: Vec::new(),
                                                        update_fulfill_htlcs: vec![msg],
                                                        update_fail_htlcs: Vec::new(),
+                                                       update_fail_malformed_htlcs: Vec::new(),
                                                        commitment_signed: commitment_msg,
                                                }
                                        });
@@ -1722,11 +1735,11 @@ impl ChannelMessageHandler for ChannelManager {
                                }
                                if !acceptable_cycle {
                                        log_info!(self, "Failed to accept incoming HTLC: Payment looped through us twice");
-                                       pending_forward_info = PendingHTLCStatus::Fail(msgs::UpdateFailHTLC {
+                                       pending_forward_info = PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
                                                channel_id: msg.channel_id,
                                                htlc_id: msg.htlc_id,
-                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x4000 | 0x2000 | 2, &[0;0]),
-                                       });
+                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret.unwrap(), 0x4000 | 0x2000 | 2, &[0;0]),
+                                       }));
                                } else {
                                        will_forward = true;
                                }
@@ -1764,7 +1777,7 @@ impl ChannelMessageHandler for ChannelManager {
                                        };
                                        *outbound_route = PendingOutboundHTLC::CycledRoute {
                                                source_short_channel_id,
-                                               incoming_packet_shared_secret: shared_secret,
+                                               incoming_packet_shared_secret: shared_secret.unwrap(),
                                                route,
                                                session_priv,
                                        };
@@ -1772,7 +1785,7 @@ impl ChannelMessageHandler for ChannelManager {
                                hash_map::Entry::Vacant(e) => {
                                        e.insert(PendingOutboundHTLC::IntermediaryHopData {
                                                source_short_channel_id,
-                                               incoming_packet_shared_secret: shared_secret,
+                                               incoming_packet_shared_secret: shared_secret.unwrap(),
                                        });
                                }
                        }
@@ -2487,9 +2500,10 @@ mod tests {
        impl SendEvent {
                fn from_event(event: Event) -> SendEvent {
                        match event {
-                               Event::UpdateHTLCs { node_id, updates: msgs::CommitmentUpdate { update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, commitment_signed } } => {
+                               Event::UpdateHTLCs { node_id, updates: msgs::CommitmentUpdate { update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs, commitment_signed } } => {
                                        assert!(update_fulfill_htlcs.is_empty());
                                        assert!(update_fail_htlcs.is_empty());
+                                       assert!(update_fail_malformed_htlcs.is_empty());
                                        SendEvent { node_id: node_id, msgs: update_add_htlcs, commitment_msg: commitment_signed }
                                },
                                _ => panic!("Unexpected event type!"),
@@ -2646,10 +2660,11 @@ mod tests {
                        let events = node.node.get_and_clear_pending_events();
                        assert_eq!(events.len(), 1);
                        match events[0] {
-                               Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref commitment_signed } } => {
+                               Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed } } => {
                                        assert!(update_add_htlcs.is_empty());
                                        assert_eq!(update_fulfill_htlcs.len(), 1);
                                        assert!(update_fail_htlcs.is_empty());
+                                       assert!(update_fail_malformed_htlcs.is_empty());
                                        expected_next_node = node_id.clone();
                                        next_msgs = Some((update_fulfill_htlcs[0].clone(), commitment_signed.clone()));
                                },
@@ -2770,10 +2785,11 @@ mod tests {
                        let events = node.node.get_and_clear_pending_events();
                        assert_eq!(events.len(), 1);
                        match events[0] {
-                               Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref commitment_signed } } => {
+                               Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed } } => {
                                        assert!(update_add_htlcs.is_empty());
                                        assert!(update_fulfill_htlcs.is_empty());
                                        assert_eq!(update_fail_htlcs.len(), 1);
+                                       assert!(update_fail_malformed_htlcs.is_empty());
                                        expected_next_node = node_id.clone();
                                        next_msgs = Some((update_fail_htlcs[0].clone(), commitment_signed.clone()));
                                },