+ /// 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>), HandleError> {
+ if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
+ return Err(HandleError{err: "Peer sent a loose channel_reestablish not after reconnect", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent a loose channel_reestablish not after reconnect".to_string(), channel_id: msg.channel_id}})});
+ }
+
+ 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(HandleError{err: "Peer send garbage channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer send garbage channel_reestablish".to_string(), channel_id: msg.channel_id}})});
+ }
+
+ // 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(HandleError{err: "Peer attempted to reestablish channel with a very old local commitment transaction", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer attempted to reestablish channel with a very old remote commitment transaction".to_string(), channel_id: msg.channel_id}})});
+ }
+
+ 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 {
+ } else if let &Some(msgs::ErrorAction::SendErrorMessage{msg: _}) = &e.action {
+ } else {
+ panic!("Got non-channel-failing result from free_holding_cell_htlcs");
+ }
+ return Err(e);
+ },
+ 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(HandleError{err: "Peer attempted to reestablish channel with a very old remote commitment transaction", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer attempted to reestablish channel with a very old remote commitment transaction".to_string(), channel_id: msg.channel_id}})});
+ }
+ }
+
+ 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}})});
+ }
+ if self.channel_state < ChannelState::FundingSent as u32 {
+ self.channel_state = ChannelState::ShutdownComplete as u32;
+ self.channel_update_count += 1;
+ return Ok((None, None, Vec::new()));
+ }
+ for htlc in self.pending_inbound_htlcs.iter() {
+ if htlc.state == InboundHTLCState::RemoteAnnounced {
+ return Err(HandleError{err: "Got shutdown with remote pending HTLCs", action: None});
+ }
+ }
+ if (self.channel_state & ChannelState::RemoteShutdownSent as u32) == ChannelState::RemoteShutdownSent as u32 {
+ return Err(HandleError{err: "Remote peer sent duplicate shutdown message", action: None});
+ }
+ assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
+
+ // BOLT 2 says we must only send a scriptpubkey of certain standard forms, which are up to
+ // 34 bytes in length, so dont let the remote peer feed us some super fee-heavy script.
+ if self.channel_outbound && msg.scriptpubkey.len() > 34 {
+ return Err(HandleError{err: "Got shutdown_scriptpubkey of absurd length from remote peer", action: None});
+ }
+
+ //Check shutdown_scriptpubkey form as BOLT says we must
+ if !(msg.scriptpubkey.is_p2pkh()) && !(msg.scriptpubkey.is_p2sh())
+ && !(msg.scriptpubkey.is_v0_p2wpkh()) && !(msg.scriptpubkey.is_v0_p2wsh()){
+ return Err(HandleError{err: "Got an invalid scriptpubkey from remote peer", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
+ }
+
+ if self.their_shutdown_scriptpubkey.is_some() {
+ if Some(&msg.scriptpubkey) != self.their_shutdown_scriptpubkey.as_ref() {
+ return Err(HandleError{err: "Got shutdown request with a scriptpubkey which did not match their previous scriptpubkey", action: None});
+ }
+ } else {
+ self.their_shutdown_scriptpubkey = Some(msg.scriptpubkey.clone());
+ }
+
+ let our_closing_script = self.get_closing_scriptpubkey();
+
+ let (proposed_feerate, proposed_fee, our_sig) = if self.channel_outbound && self.pending_inbound_htlcs.is_empty() && self.pending_outbound_htlcs.is_empty() {
+ let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
+ if self.feerate_per_kw > proposed_feerate {
+ proposed_feerate = self.feerate_per_kw;
+ }
+ let tx_weight = Self::get_closing_transaction_weight(&our_closing_script, &msg.scriptpubkey);
+ let proposed_total_fee_satoshis = proposed_feerate * tx_weight / 1000;
+
+ let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false);
+ let funding_redeemscript = self.get_funding_redeemscript();
+ let sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
+
+ (Some(proposed_feerate), Some(total_fee_satoshis), Some(self.secp_ctx.sign(&sighash, &self.local_keys.funding_key)))
+ } else { (None, None, None) };
+
+ // From here on out, we may not fail!
+
+ self.channel_state |= ChannelState::RemoteShutdownSent 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, ref source, .. } => {
+ dropped_outbound_htlcs.push((source.clone(), payment_hash.clone()));
+ false
+ },
+ _ => true
+ }
+ });
+ for htlc in self.pending_outbound_htlcs.iter() {
+ if htlc.state == OutboundHTLCState::LocalAnnounced {
+ return Ok((None, None, dropped_outbound_htlcs));
+ }
+ }
+
+ let our_shutdown = if (self.channel_state & ChannelState::LocalShutdownSent as u32) == ChannelState::LocalShutdownSent as u32 {
+ None
+ } else {
+ Some(msgs::Shutdown {
+ channel_id: self.channel_id,
+ scriptpubkey: our_closing_script,
+ })
+ };
+
+ self.channel_state |= ChannelState::LocalShutdownSent as u32;
+ self.channel_update_count += 1;
+ if self.pending_inbound_htlcs.is_empty() && self.pending_outbound_htlcs.is_empty() && self.channel_outbound {
+ // There are no more HTLCs and we're the funder, this means we start the closing_signed
+ // dance with an initial fee proposal!
+ self.last_sent_closing_fee = Some((proposed_feerate.unwrap(), proposed_fee.unwrap()));
+ Ok((our_shutdown, Some(msgs::ClosingSigned {
+ channel_id: self.channel_id,
+ fee_satoshis: proposed_fee.unwrap(),
+ signature: our_sig.unwrap(),
+ }), dropped_outbound_htlcs))
+ } else {
+ Ok((our_shutdown, None, dropped_outbound_htlcs))
+ }
+ }
+
+ pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), HandleError> {
+ if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
+ return Err(HandleError{err: "Remote end sent us a closing_signed before both sides provided a shutdown", action: None});
+ }
+ if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
+ return Err(HandleError{err: "Peer sent closing_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent closing_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
+ }
+ if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() {
+ return Err(HandleError{err: "Remote end sent us a closing_signed while there were still pending HTLCs", action: None});
+ }
+ if msg.fee_satoshis > 21000000 * 10000000 { //this is required to stop potential overflow in build_closing_transaction
+ return Err(HandleError{err: "Remote tried to send us a closing tx with > 21 million BTC fee", action: None});
+ }
+
+ let funding_redeemscript = self.get_funding_redeemscript();
+ let (mut closing_tx, used_total_fee) = self.build_closing_transaction(msg.fee_satoshis, false);
+ if used_total_fee != msg.fee_satoshis {
+ return Err(HandleError{err: "Remote sent us a closing_signed with a fee greater than the value they can claim", action: None});
+ }
+ let mut sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
+
+ match self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()) {
+ Ok(_) => {},
+ Err(_e) => {
+ // The remote end may have decided to revoke their output due to inconsistent dust
+ // limits, so check for that case by re-checking the signature here.
+ closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
+ sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
+ secp_call!(self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid closing tx signature from peer", self.channel_id());
+ },
+ };
+
+ if let Some((_, last_fee)) = self.last_sent_closing_fee {
+ if last_fee == msg.fee_satoshis {
+ self.sign_commitment_transaction(&mut closing_tx, &msg.signature);
+ self.channel_state = ChannelState::ShutdownComplete as u32;
+ self.channel_update_count += 1;
+ return Ok((None, Some(closing_tx)));
+ }
+ }
+
+ macro_rules! propose_new_feerate {
+ ($new_feerate: expr) => {
+ let closing_tx_max_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.their_shutdown_scriptpubkey.as_ref().unwrap());
+ let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate * closing_tx_max_weight / 1000, false);
+ sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
+ let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key);
+ self.last_sent_closing_fee = Some(($new_feerate, used_total_fee));
+ return Ok((Some(msgs::ClosingSigned {
+ channel_id: self.channel_id,
+ fee_satoshis: used_total_fee,
+ signature: our_sig,
+ }), None))
+ }
+ }
+
+ let proposed_sat_per_kw = msg.fee_satoshis * 1000 / closing_tx.get_weight();
+ if self.channel_outbound {
+ let our_max_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
+ if proposed_sat_per_kw > our_max_feerate {
+ if let Some((last_feerate, _)) = self.last_sent_closing_fee {
+ if our_max_feerate <= last_feerate {
+ return Err(HandleError{err: "Unable to come to consensus about closing feerate, remote wanted something higher than our Normal feerate", action: None});
+ }
+ }
+ propose_new_feerate!(our_max_feerate);
+ }
+ } else {
+ let our_min_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
+ if proposed_sat_per_kw < our_min_feerate {
+ if let Some((last_feerate, _)) = self.last_sent_closing_fee {
+ if our_min_feerate >= last_feerate {
+ return Err(HandleError{err: "Unable to come to consensus about closing feerate, remote wanted something lower than our Background feerate", action: None});
+ }
+ }
+ propose_new_feerate!(our_min_feerate);
+ }
+ }
+
+ let our_sig = self.sign_commitment_transaction(&mut closing_tx, &msg.signature);
+ self.channel_state = ChannelState::ShutdownComplete as u32;
+ self.channel_update_count += 1;
+
+ Ok((Some(msgs::ClosingSigned {
+ channel_id: self.channel_id,
+ fee_satoshis: msg.fee_satoshis,
+ signature: our_sig,
+ }), Some(closing_tx)))
+ }
+