+ /// May panic if some calls other than message-handling calls (which will all Err immediately)
+ /// have been called between remove_uncommitted_htlcs_and_mark_paused and this call.
+ pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option<msgs::FundingLocked>, Option<msgs::RevokeAndACK>, Option<msgs::CommitmentUpdate>, Option<ChannelMonitor>), ChannelError> {
+ if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
+ // While BOLT 2 doesn't indicate explicitly we should error this channel here, it
+ // almost certainly indicates we are going to end up out-of-sync in some way, so we
+ // just close here instead of trying to recover.
+ return Err(ChannelError::Close("Peer sent a loose channel_reestablish not after reconnect"));
+ }
+
+ if msg.next_local_commitment_number == 0 || msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER ||
+ msg.next_remote_commitment_number == 0 || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER {
+ return Err(ChannelError::Close("Peer send garbage channel_reestablish"));
+ }
+
+ // Go ahead and unmark PeerDisconnected as various calls we may make check for it (and all
+ // remaining cases either succeed or ErrorMessage-fail).
+ self.channel_state &= !(ChannelState::PeerDisconnected as u32);
+
+ let mut required_revoke = None;
+ if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number {
+ // Remote isn't waiting on any RevokeAndACK from us!
+ // Note that if we need to repeat our FundingLocked we'll do that in the next if block.
+ } else if msg.next_remote_commitment_number == (INITIAL_COMMITMENT_NUMBER - 1) - self.cur_local_commitment_transaction_number {
+ let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number));
+ let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 2);
+ required_revoke = Some(msgs::RevokeAndACK {
+ channel_id: self.channel_id,
+ per_commitment_secret,
+ next_per_commitment_point,
+ });
+ } else {
+ return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old local commitment transaction"));
+ }
+
+ if msg.next_local_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_remote_commitment_transaction_number {
+ if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number {
+ log_debug!(self, "Reconnected channel {} with no lost commitment txn", log_bytes!(self.channel_id()));
+ if msg.next_local_commitment_number == 1 && msg.next_remote_commitment_number == 1 {
+ let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
+ let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret);
+ return Ok((Some(msgs::FundingLocked {
+ channel_id: self.channel_id(),
+ next_per_commitment_point: next_per_commitment_point,
+ }), None, None, None));
+ }
+ }
+
+ if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
+ // We're up-to-date and not waiting on a remote revoke (if we are our
+ // channel_reestablish should result in them sending a revoke_and_ack), but we may
+ // have received some updates while we were disconnected. Free the holding cell
+ // now!
+ match self.free_holding_cell_htlcs() {
+ Err(e) => {
+ if let &Some(msgs::ErrorAction::DisconnectPeer{msg: Some(_)}) = &e.action {
+ return Err(ChannelError::Close(e.err));
+ } else if let &Some(msgs::ErrorAction::SendErrorMessage{msg: _}) = &e.action {
+ return Err(ChannelError::Close(e.err));
+ } else {
+ panic!("Got non-channel-failing result from free_holding_cell_htlcs");
+ }
+ },
+ Ok(Some((commitment_update, channel_monitor))) => return Ok((None, required_revoke, Some(commitment_update), Some(channel_monitor))),
+ Ok(None) => return Ok((None, required_revoke, None, None)),
+ }
+ } else {
+ return Ok((None, required_revoke, None, None));
+ }
+ } else if msg.next_local_commitment_number == (INITIAL_COMMITMENT_NUMBER - 1) - self.cur_remote_commitment_transaction_number {
+ return Ok((None, required_revoke,
+ Some(msgs::CommitmentUpdate {
+ update_add_htlcs: Vec::new(),
+ update_fulfill_htlcs: Vec::new(),
+ update_fail_htlcs: Vec::new(),
+ update_fail_malformed_htlcs: Vec::new(),
+ update_fee: None,
+ commitment_signed: self.send_commitment_no_state_update().expect("It looks like we failed to re-generate a commitment_signed we had previously sent?").0,
+ }), None));
+ } else {
+ return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction"));
+ }
+ }
+
+ pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, [u8; 32])>), HandleError> {
+ if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
+ return Err(HandleError{err: "Peer sent shutdown when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent shutdown when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
+ }