From: Jeffrey Czyz Date: Fri, 30 Jul 2021 19:28:17 +0000 (-0500) Subject: f - Check BOLT2 compatibility in close_channel X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=d7ff37edb4fc52023d7e96b725fa586d2f64e179;p=rust-lightning f - Check BOLT2 compatibility in close_channel --- diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index cfd0bec3d..94ce779ff 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -4451,7 +4451,7 @@ impl Channel { /// Begins the shutdown process, getting a message for the remote peer and returning all /// holding cell HTLCs for payment failure. - pub fn get_shutdown(&mut self, keys_provider: &K) -> Result<(msgs::Shutdown, Option, Vec<(HTLCSource, PaymentHash)>), APIError> + pub fn get_shutdown(&mut self, keys_provider: &K, their_features: &InitFeatures) -> Result<(msgs::Shutdown, Option, Vec<(HTLCSource, PaymentHash)>), APIError> where K::Target: KeysInterface { for htlc in self.pending_outbound_htlcs.iter() { if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { @@ -4471,16 +4471,30 @@ impl Channel { 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 { diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 971b4bc22..40ea3e784 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -1261,9 +1261,15 @@ impl 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 {