f - Check BOLT2 compatibility in close_channel
authorJeffrey Czyz <jkczyz@gmail.com>
Fri, 30 Jul 2021 19:28:17 +0000 (14:28 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Sat, 31 Jul 2021 05:13:36 +0000 (00:13 -0500)
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs

index cfd0bec3d13cac4c8958ebf6ed247c7698d60ac4..94ce779ff895f15ffc3836025d03b9fb607d1f65 100644 (file)
@@ -4451,7 +4451,7 @@ impl<Signer: Sign> Channel<Signer> {
 
        /// Begins the shutdown process, getting a message for the remote peer and returning all
        /// holding cell HTLCs for payment failure.
-       pub fn get_shutdown<K: Deref>(&mut self, keys_provider: &K) -> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
+       pub fn get_shutdown<K: Deref>(&mut self, keys_provider: &K, their_features: &InitFeatures) -> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
        where K::Target: KeysInterface<Signer = Signer> {
                for htlc in self.pending_outbound_htlcs.iter() {
                        if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
@@ -4471,16 +4471,30 @@ impl<Signer: Sign> Channel<Signer> {
                        return Err(APIError::ChannelUnavailable{err: "Cannot begin shutdown while peer is disconnected or we're waiting on a monitor update, maybe force-close instead?".to_owned()});
                }
 
-               let monitor_update = if self.shutdown_scriptpubkey.is_none() {
-                       self.shutdown_scriptpubkey = Some(keys_provider.get_shutdown_scriptpubkey());
-                       self.latest_monitor_update_id += 1;
-                       Some(ChannelMonitorUpdate {
-                               update_id: self.latest_monitor_update_id,
-                               updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
-                                       scriptpubkey: self.get_closing_scriptpubkey(),
-                               }],
-                       })
-               } else { None };
+               let shutdown_scriptpubkey = match self.shutdown_scriptpubkey {
+                       Some(_) => None,
+                       None => {
+                               let shutdown_scriptpubkey = keys_provider.get_shutdown_scriptpubkey();
+                               if !shutdown_scriptpubkey.is_compatible(their_features) {
+                                       return Err(APIError::APIMisuseError { err: format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex()) });
+                               }
+                               Some(shutdown_scriptpubkey)
+                       },
+               };
+
+               let monitor_update = match shutdown_scriptpubkey {
+                       Some(shutdown_scriptpubkey) => {
+                               self.shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
+                               self.latest_monitor_update_id += 1;
+                               Some(ChannelMonitorUpdate {
+                                       update_id: self.latest_monitor_update_id,
+                                       updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
+                                               scriptpubkey: self.get_closing_scriptpubkey(),
+                                       }],
+                               })
+                       },
+                       None => None,
+               };
 
                // From here on out, we may not fail!
                if self.channel_state < ChannelState::FundingSent as u32 {
index 971b4bc22ac2964657ee0d3eda26c41f538e80ce..40ea3e7849eb6ee0291b7793863c6e5687e7be48 100644 (file)
@@ -1261,9 +1261,15 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                        let channel_state = &mut *channel_state_lock;
                        match channel_state.by_id.entry(channel_id.clone()) {
                                hash_map::Entry::Occupied(mut chan_entry) => {
-                                       let (shutdown_msg, monitor_update, failed_htlcs) = chan_entry.get_mut().get_shutdown(&self.keys_manager)?;
+                                       let counterparty_node_id = chan_entry.get().get_counterparty_node_id();
+                                       let their_features = {
+                                               let per_peer_state = self.per_peer_state.read().unwrap();
+                                               let peer_state = per_peer_state.get(&counterparty_node_id).unwrap().lock().unwrap();
+                                               peer_state.latest_features.clone()
+                                       };
+                                       let (shutdown_msg, monitor_update, failed_htlcs) = chan_entry.get_mut().get_shutdown(&self.keys_manager, &their_features)?;
                                        channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
-                                               node_id: chan_entry.get().get_counterparty_node_id(),
+                                               node_id: counterparty_node_id,
                                                msg: shutdown_msg
                                        });
                                        if let Some(monitor_update) = monitor_update {