/// 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 {
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 {
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 {