+ /// Returns true if this channel is fully shut down. True here implies that no further actions
+ /// may/will be taken on this channel, and thus this object should be freed. Any future changes
+ /// will be handled appropriately by the chain monitor.
+ pub fn is_shutdown(&self) -> bool {
+ if (self.context.channel_state & ChannelState::ShutdownComplete as u32) == ChannelState::ShutdownComplete as u32 {
+ assert!(self.context.channel_state == ChannelState::ShutdownComplete as u32);
+ true
+ } else { false }
+ }
+
+ pub fn channel_update_status(&self) -> ChannelUpdateStatus {
+ self.context.channel_update_status
+ }
+
+ pub fn set_channel_update_status(&mut self, status: ChannelUpdateStatus) {
+ self.context.update_time_counter += 1;
+ self.context.channel_update_status = status;
+ }
+
+ fn check_get_channel_ready(&mut self, height: u32) -> Option<msgs::ChannelReady> {
+ // Called:
+ // * always when a new block/transactions are confirmed with the new height
+ // * when funding is signed with a height of 0
+ if self.context.funding_tx_confirmation_height == 0 && self.context.minimum_depth != Some(0) {
+ return None;
+ }
+
+ let funding_tx_confirmations = height as i64 - self.context.funding_tx_confirmation_height as i64 + 1;
+ if funding_tx_confirmations <= 0 {
+ self.context.funding_tx_confirmation_height = 0;
+ }
+
+ if funding_tx_confirmations < self.context.minimum_depth.unwrap_or(0) as i64 {
+ return None;
+ }
+
+ let non_shutdown_state = self.context.channel_state & (!MULTI_STATE_FLAGS);
+ let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 {
+ self.context.channel_state |= ChannelState::OurChannelReady as u32;
+ true
+ } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirChannelReady as u32) {
+ self.context.channel_state = ChannelState::ChannelReady as u32 | (self.context.channel_state & MULTI_STATE_FLAGS);
+ self.context.update_time_counter += 1;
+ true
+ } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurChannelReady as u32) {
+ // We got a reorg but not enough to trigger a force close, just ignore.
+ false
+ } else {
+ if self.context.funding_tx_confirmation_height != 0 && self.context.channel_state < ChannelState::ChannelReady as u32 {
+ // We should never see a funding transaction on-chain until we've received
+ // funding_signed (if we're an outbound channel), or seen funding_generated (if we're
+ // an inbound channel - before that we have no known funding TXID). The fuzzer,
+ // however, may do this and we shouldn't treat it as a bug.
+ #[cfg(not(fuzzing))]
+ panic!("Started confirming a channel in a state pre-FundingSent: {}.\n\
+ Do NOT broadcast a funding transaction manually - let LDK do it for you!",
+ self.context.channel_state);
+ }
+ // We got a reorg but not enough to trigger a force close, just ignore.
+ false
+ };
+
+ if need_commitment_update {
+ if self.context.channel_state & (ChannelState::MonitorUpdateInProgress as u32) == 0 {
+ if self.context.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
+ let next_per_commitment_point =
+ self.context.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.context.secp_ctx);
+ return Some(msgs::ChannelReady {
+ channel_id: self.context.channel_id,
+ next_per_commitment_point,
+ short_channel_id_alias: Some(self.context.outbound_scid_alias),
+ });
+ }
+ } else {
+ self.context.monitor_pending_channel_ready = true;
+ }
+ }
+ None
+ }
+
+ /// When a transaction is confirmed, we check whether it is or spends the funding transaction
+ /// In the first case, we store the confirmation height and calculating the short channel id.
+ /// In the second, we simply return an Err indicating we need to be force-closed now.
+ pub fn transactions_confirmed<NS: Deref, L: Deref>(
+ &mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData,
+ genesis_block_hash: BlockHash, node_signer: &NS, user_config: &UserConfig, logger: &L
+ ) -> Result<(Option<msgs::ChannelReady>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
+ if let Some(funding_txo) = self.context.get_funding_txo() {
+ for &(index_in_block, tx) in txdata.iter() {
+ // Check if the transaction is the expected funding transaction, and if it is,
+ // check that it pays the right amount to the right script.
+ if self.context.funding_tx_confirmation_height == 0 {
+ if tx.txid() == funding_txo.txid {
+ let txo_idx = funding_txo.index as usize;
+ if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_v0_p2wsh() ||
+ tx.output[txo_idx].value != self.context.channel_value_satoshis {
+ if self.context.is_outbound() {
+ // If we generated the funding transaction and it doesn't match what it
+ // should, the client is really broken and we should just panic and
+ // tell them off. That said, because hash collisions happen with high
+ // probability in fuzzing mode, if we're fuzzing we just close the
+ // channel and move on.
+ #[cfg(not(fuzzing))]
+ panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
+ }
+ self.context.update_time_counter += 1;
+ let err_reason = "funding tx had wrong script/value or output index";
+ return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
+ } else {
+ if self.context.is_outbound() {
+ for input in tx.input.iter() {
+ if input.witness.is_empty() {
+ // We generated a malleable funding transaction, implying we've
+ // just exposed ourselves to funds loss to our counterparty.
+ #[cfg(not(fuzzing))]
+ panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
+ }
+ }
+ }
+ self.context.funding_tx_confirmation_height = height;
+ self.context.funding_tx_confirmed_in = Some(*block_hash);
+ self.context.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) {
+ Ok(scid) => Some(scid),
+ Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"),
+ }
+ }
+ }
+ // If we allow 1-conf funding, we may need to check for channel_ready here and
+ // send it immediately instead of waiting for a best_block_updated call (which
+ // may have already happened for this block).
+ if let Some(channel_ready) = self.check_get_channel_ready(height) {
+ log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.context.channel_id));
+ let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger);
+ return Ok((Some(channel_ready), announcement_sigs));
+ }
+ }
+ for inp in tx.input.iter() {
+ if inp.previous_output == funding_txo.into_bitcoin_outpoint() {
+ log_info!(logger, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(self.context.channel_id()));
+ return Err(ClosureReason::CommitmentTxConfirmed);
+ }
+ }
+ }
+ }
+ Ok((None, None))
+ }
+
+ /// When a new block is connected, we check the height of the block against outbound holding
+ /// cell HTLCs in case we need to give up on them prematurely and time them out. Everything
+ /// else (e.g. commitment transaction broadcasts, HTLC transaction broadcasting, etc) is
+ /// handled by the ChannelMonitor.
+ ///
+ /// If we return Err, the channel may have been closed, at which point the standard
+ /// requirements apply - no calls may be made except those explicitly stated to be allowed
+ /// post-shutdown.
+ ///
+ /// May return some HTLCs (and their payment_hash) which have timed out and should be failed
+ /// back.
+ pub fn best_block_updated<NS: Deref, L: Deref>(
+ &mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash,
+ node_signer: &NS, user_config: &UserConfig, logger: &L
+ ) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
+ self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_signer, user_config)), logger)
+ }
+
+ fn do_best_block_updated<NS: Deref, L: Deref>(
+ &mut self, height: u32, highest_header_time: u32,
+ genesis_node_signer: Option<(BlockHash, &NS, &UserConfig)>, logger: &L
+ ) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
+ let mut timed_out_htlcs = Vec::new();
+ // This mirrors the check in ChannelManager::decode_update_add_htlc_onion, refusing to
+ // forward an HTLC when our counterparty should almost certainly just fail it for expiring
+ // ~now.
+ let unforwarded_htlc_cltv_limit = height + LATENCY_GRACE_PERIOD_BLOCKS;
+ self.context.holding_cell_htlc_updates.retain(|htlc_update| {
+ match htlc_update {
+ &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, .. } => {
+ if *cltv_expiry <= unforwarded_htlc_cltv_limit {
+ timed_out_htlcs.push((source.clone(), payment_hash.clone()));
+ false
+ } else { true }
+ },
+ _ => true
+ }
+ });
+
+ self.context.update_time_counter = cmp::max(self.context.update_time_counter, highest_header_time);
+
+ if let Some(channel_ready) = self.check_get_channel_ready(height) {
+ let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer {
+ self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger)
+ } else { None };
+ log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.context.channel_id));
+ return Ok((Some(channel_ready), timed_out_htlcs, announcement_sigs));
+ }
+
+ let non_shutdown_state = self.context.channel_state & (!MULTI_STATE_FLAGS);
+ if non_shutdown_state >= ChannelState::ChannelReady as u32 ||
+ (non_shutdown_state & ChannelState::OurChannelReady as u32) == ChannelState::OurChannelReady as u32 {
+ let mut funding_tx_confirmations = height as i64 - self.context.funding_tx_confirmation_height as i64 + 1;
+ if self.context.funding_tx_confirmation_height == 0 {
+ // Note that check_get_channel_ready may reset funding_tx_confirmation_height to
+ // zero if it has been reorged out, however in either case, our state flags
+ // indicate we've already sent a channel_ready
+ funding_tx_confirmations = 0;
+ }
+
+ // If we've sent channel_ready (or have both sent and received channel_ready), and
+ // the funding transaction has become unconfirmed,
+ // close the channel and hope we can get the latest state on chain (because presumably
+ // the funding transaction is at least still in the mempool of most nodes).
+ //
+ // Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf or
+ // 0-conf channel, but not doing so may lead to the
+ // `ChannelManager::short_to_chan_info` map being inconsistent, so we currently have
+ // to.
+ if funding_tx_confirmations == 0 && self.context.funding_tx_confirmed_in.is_some() {
+ let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.",
+ self.context.minimum_depth.unwrap(), funding_tx_confirmations);
+ return Err(ClosureReason::ProcessingError { err: err_reason });
+ }
+ } else if !self.context.is_outbound() && self.context.funding_tx_confirmed_in.is_none() &&
+ height >= self.context.channel_creation_height + FUNDING_CONF_DEADLINE_BLOCKS {
+ log_info!(logger, "Closing channel {} due to funding timeout", log_bytes!(self.context.channel_id));
+ // If funding_tx_confirmed_in is unset, the channel must not be active
+ assert!(non_shutdown_state <= ChannelState::ChannelReady as u32);
+ assert_eq!(non_shutdown_state & ChannelState::OurChannelReady as u32, 0);
+ return Err(ClosureReason::FundingTimedOut);
+ }
+
+ let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer {
+ self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger)
+ } else { None };
+ Ok((None, timed_out_htlcs, announcement_sigs))
+ }
+
+ /// Indicates the funding transaction is no longer confirmed in the main chain. This may
+ /// force-close the channel, but may also indicate a harmless reorganization of a block or two
+ /// before the channel has reached channel_ready and we can just wait for more blocks.
+ pub fn funding_transaction_unconfirmed<L: Deref>(&mut self, logger: &L) -> Result<(), ClosureReason> where L::Target: Logger {
+ if self.context.funding_tx_confirmation_height != 0 {
+ // We handle the funding disconnection by calling best_block_updated with a height one
+ // below where our funding was connected, implying a reorg back to conf_height - 1.
+ let reorg_height = self.context.funding_tx_confirmation_height - 1;
+ // We use the time field to bump the current time we set on channel updates if its
+ // larger. If we don't know that time has moved forward, we can just set it to the last
+ // time we saw and it will be ignored.
+ let best_time = self.context.update_time_counter;
+ match self.do_best_block_updated(reorg_height, best_time, None::<(BlockHash, &&NodeSigner, &UserConfig)>, logger) {
+ Ok((channel_ready, timed_out_htlcs, announcement_sigs)) => {
+ assert!(channel_ready.is_none(), "We can't generate a funding with 0 confirmations?");
+ assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?");
+ assert!(announcement_sigs.is_none(), "We can't generate an announcement_sigs with 0 confirmations?");
+ Ok(())
+ },
+ Err(e) => Err(e)
+ }
+ } else {
+ // We never learned about the funding confirmation anyway, just ignore
+ Ok(())
+ }
+ }
+
+ // Methods to get unprompted messages to send to the remote end (or where we already returned
+ // something in the handler for the message that prompted this message):
+
+ /// Gets an UnsignedChannelAnnouncement for this channel. The channel must be publicly
+ /// announceable and available for use (have exchanged ChannelReady messages in both
+ /// directions). Should be used for both broadcasted announcements and in response to an
+ /// AnnouncementSignatures message from the remote peer.
+ ///
+ /// Will only fail if we're not in a state where channel_announcement may be sent (including
+ /// closing).
+ ///
+ /// This will only return ChannelError::Ignore upon failure.
+ fn get_channel_announcement<NS: Deref>(
+ &self, node_signer: &NS, chain_hash: BlockHash, user_config: &UserConfig,
+ ) -> Result<msgs::UnsignedChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
+ if !self.context.config.announced_channel {
+ return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned()));
+ }
+ if !self.context.is_usable() {
+ return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned()));
+ }
+
+ let node_id = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node)
+ .map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?);
+ let counterparty_node_id = NodeId::from_pubkey(&self.context.get_counterparty_node_id());
+ let were_node_one = node_id.as_slice() < counterparty_node_id.as_slice();
+
+ let msg = msgs::UnsignedChannelAnnouncement {
+ features: channelmanager::provided_channel_features(&user_config),
+ chain_hash,
+ short_channel_id: self.context.get_short_channel_id().unwrap(),
+ node_id_1: if were_node_one { node_id } else { counterparty_node_id },
+ node_id_2: if were_node_one { counterparty_node_id } else { node_id },
+ bitcoin_key_1: NodeId::from_pubkey(if were_node_one { &self.context.get_holder_pubkeys().funding_pubkey } else { self.context.counterparty_funding_pubkey() }),
+ bitcoin_key_2: NodeId::from_pubkey(if were_node_one { self.context.counterparty_funding_pubkey() } else { &self.context.get_holder_pubkeys().funding_pubkey }),
+ excess_data: Vec::new(),
+ };
+
+ Ok(msg)
+ }
+
+ fn get_announcement_sigs<NS: Deref, L: Deref>(
+ &mut self, node_signer: &NS, genesis_block_hash: BlockHash, user_config: &UserConfig,
+ best_block_height: u32, logger: &L
+ ) -> Option<msgs::AnnouncementSignatures>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
+ if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height {
+ return None;
+ }
+
+ if !self.context.is_usable() {
+ return None;
+ }
+
+ if self.context.channel_state & ChannelState::PeerDisconnected as u32 != 0 {
+ log_trace!(logger, "Cannot create an announcement_signatures as our peer is disconnected");
+ return None;
+ }
+
+ if self.context.announcement_sigs_state != AnnouncementSigsState::NotSent {
+ return None;
+ }
+
+ log_trace!(logger, "Creating an announcement_signatures message for channel {}", log_bytes!(self.context.channel_id()));
+ let announcement = match self.get_channel_announcement(node_signer, genesis_block_hash, user_config) {
+ Ok(a) => a,
+ Err(e) => {
+ log_trace!(logger, "{:?}", e);
+ return None;
+ }
+ };
+ let our_node_sig = match node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) {
+ Err(_) => {
+ log_error!(logger, "Failed to generate node signature for channel_announcement. Channel will not be announced!");
+ return None;
+ },
+ Ok(v) => v
+ };
+ let our_bitcoin_sig = match self.context.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.context.secp_ctx) {
+ Err(_) => {
+ log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!");
+ return None;
+ },
+ Ok(v) => v
+ };
+ self.context.announcement_sigs_state = AnnouncementSigsState::MessageSent;
+
+ Some(msgs::AnnouncementSignatures {
+ channel_id: self.context.channel_id(),
+ short_channel_id: self.context.get_short_channel_id().unwrap(),
+ node_signature: our_node_sig,
+ bitcoin_signature: our_bitcoin_sig,
+ })
+ }
+
+ /// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are
+ /// available.
+ fn sign_channel_announcement<NS: Deref>(
+ &self, node_signer: &NS, announcement: msgs::UnsignedChannelAnnouncement
+ ) -> Result<msgs::ChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
+ if let Some((their_node_sig, their_bitcoin_sig)) = self.context.announcement_sigs {
+ let our_node_key = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node)
+ .map_err(|_| ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()))?);
+ let were_node_one = announcement.node_id_1 == our_node_key;
+
+ let our_node_sig = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement))
+ .map_err(|_| ChannelError::Ignore("Failed to generate node signature for channel_announcement".to_owned()))?;
+ let our_bitcoin_sig = self.context.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.context.secp_ctx)
+ .map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?;
+ Ok(msgs::ChannelAnnouncement {
+ node_signature_1: if were_node_one { our_node_sig } else { their_node_sig },
+ node_signature_2: if were_node_one { their_node_sig } else { our_node_sig },
+ bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { their_bitcoin_sig },
+ bitcoin_signature_2: if were_node_one { their_bitcoin_sig } else { our_bitcoin_sig },
+ contents: announcement,
+ })
+ } else {
+ Err(ChannelError::Ignore("Attempted to sign channel announcement before we'd received announcement_signatures".to_string()))
+ }