+
+ /// 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) -> Result<(msgs::Shutdown, Vec<[u8; 32]>), HandleError> {
+ for htlc in self.pending_htlcs.iter() {
+ if htlc.state == HTLCState::LocalAnnounced {
+ return Err(HandleError{err: "Cannot begin shutdown with pending HTLCs, call send_commitment first", action: None});
+ }
+ }
+ if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != 0 {
+ return Err(HandleError{err: "Shutdown already in progress", action: None});
+ }
+ assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
+
+ let our_closing_script = self.get_closing_scriptpubkey();
+
+ // From here on out, we may not fail!
+ if self.channel_state < ChannelState::FundingSent as u32 {
+ self.channel_state = ChannelState::ShutdownComplete as u32;
+ } else {
+ self.channel_state |= ChannelState::LocalShutdownSent as u32;
+ }
+ self.channel_update_count += 1;
+
+ // We can't send our shutdown until we've committed all of our pending HTLCs, but the
+ // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding
+ // cell HTLCs and return them to fail the payment.
+ let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len());
+ self.holding_cell_htlc_updates.retain(|htlc_update| {
+ match htlc_update {
+ &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, .. } => {
+ dropped_outbound_htlcs.push(payment_hash.clone());
+ false
+ },
+ _ => true
+ }
+ });
+
+ Ok((msgs::Shutdown {
+ channel_id: self.channel_id,
+ scriptpubkey: our_closing_script,
+ }, dropped_outbound_htlcs))
+ }
+
+ /// Gets the latest commitment transaction and any dependant transactions for relay (forcing
+ /// shutdown of this channel - no more calls into this Channel may be made afterwards except
+ /// those explicitly stated to be allowed after shutdown completes, eg some simple getters).
+ /// Also returns the list of payment_hashes for channels which we can safely fail backwards
+ /// immediately (others we will have to allow to time out).
+ pub fn force_shutdown(&mut self) -> (Vec<Transaction>, Vec<[u8; 32]>) {
+ assert!(self.channel_state != ChannelState::ShutdownComplete as u32);
+
+ // We go ahead and "free" any holding cell HTLCs or HTLCs we haven't yet committed to and
+ // return them to fail the payment.
+ let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len());
+ for htlc_update in self.holding_cell_htlc_updates.drain(..) {
+ match htlc_update {
+ HTLCUpdateAwaitingACK::AddHTLC { payment_hash, .. } => {
+ dropped_outbound_htlcs.push(payment_hash);
+ },
+ _ => {}
+ }
+ }
+
+ for htlc in self.pending_htlcs.drain(..) {
+ if htlc.state == HTLCState::LocalAnnounced {
+ dropped_outbound_htlcs.push(htlc.payment_hash);
+ }
+ //TODO: Do something with the remaining HTLCs
+ //(we need to have the ChannelManager monitor them so we can claim the inbound HTLCs
+ //which correspond)
+ }
+
+ self.channel_state = ChannelState::ShutdownComplete as u32;
+ self.channel_update_count += 1;
+ let mut res = Vec::new();
+ mem::swap(&mut res, &mut self.last_local_commitment_txn);
+ (res, dropped_outbound_htlcs)
+ }