X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=4daaf630ac4e57bd7c96ed73e401badf986236d1;hb=ab20284e2673e946ebdffcd5be7388de917a168f;hp=6c610402350211c1d4cf24c85f97ae11edb2aac1;hpb=75ca50f5c0834c01d84826b880f048ca031f08ce;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 6c610402..4daaf630 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -243,7 +243,7 @@ enum HTLCUpdateAwaitingACK { /// There are a few "states" and then a number of flags which can be applied: /// We first move through init with OurInitSent -> TheirInitSent -> FundingCreated -> FundingSent. -/// TheirFundingLocked and OurFundingLocked then get set on FundingSent, and when both are set we +/// TheirChannelReady and OurChannelReady then get set on FundingSent, and when both are set we /// move on to ChannelFunded. /// Note that PeerDisconnected can be set on both ChannelFunded and FundingSent. /// ChannelFunded can then get all remaining flags set on it, until we finish shutdown, then we @@ -258,15 +258,15 @@ enum ChannelState { /// upon receipt of funding_created, so simply skip this state. FundingCreated = 4, /// Set when we have received/sent funding_created and funding_signed and are thus now waiting - /// on the funding transaction to confirm. The FundingLocked flags are set to indicate when we + /// on the funding transaction to confirm. The ChannelReady flags are set to indicate when we /// and our counterparty consider the funding transaction confirmed. FundingSent = 8, - /// Flag which can be set on FundingSent to indicate they sent us a funding_locked message. - /// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded. - TheirFundingLocked = 1 << 4, - /// Flag which can be set on FundingSent to indicate we sent them a funding_locked message. - /// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded. - OurFundingLocked = 1 << 5, + /// Flag which can be set on FundingSent to indicate they sent us a channel_ready message. + /// Once both TheirChannelReady and OurChannelReady are set, state moves on to ChannelFunded. + TheirChannelReady = 1 << 4, + /// Flag which can be set on FundingSent to indicate we sent them a channel_ready message. + /// Once both TheirChannelReady and OurChannelReady are set, state moves on to ChannelFunded. + OurChannelReady = 1 << 5, ChannelFunded = 64, /// Flag which is set on ChannelFunded and FundingSent indicating remote side is considered /// "disconnected" and no updates are allowed until after we've done a channel_reestablish @@ -429,13 +429,13 @@ pub(super) struct MonitorRestoreUpdates { pub failed_htlcs: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, pub finalized_claimed_htlcs: Vec, pub funding_broadcastable: Option, - pub funding_locked: Option, + pub channel_ready: Option, pub announcement_sigs: Option, } /// The return value of `channel_reestablish` pub(super) struct ReestablishResponses { - pub funding_locked: Option, + pub channel_ready: Option, pub raa: Option, pub commitment_update: Option, pub order: RAACommitmentOrder, @@ -543,7 +543,7 @@ pub(super) struct Channel { /// send it first. resend_order: RAACommitmentOrder, - monitor_pending_funding_locked: bool, + monitor_pending_channel_ready: bool, monitor_pending_revoke_and_ack: bool, monitor_pending_commitment_signed: bool, monitor_pending_forwards: Vec<(PendingHTLCInfo, u64)>, @@ -688,12 +688,12 @@ pub(super) struct Channel { /// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed /// they will not send a channel_reestablish until the channel locks in. Then, they will send a - /// funding_locked *before* sending the channel_reestablish (which is clearly a violation of - /// the BOLT specs). We copy c-lightning's workaround here and simply store the funding_locked + /// channel_ready *before* sending the channel_reestablish (which is clearly a violation of + /// the BOLT specs). We copy c-lightning's workaround here and simply store the channel_ready /// message until we receive a channel_reestablish. /// /// See-also - pub workaround_lnd_bug_4006: Option, + pub workaround_lnd_bug_4006: Option, #[cfg(any(test, fuzzing))] // When we receive an HTLC fulfill on an outbound path, we may immediately fulfill the @@ -710,6 +710,11 @@ pub(super) struct Channel { // Our counterparty can offer us SCID aliases which they will map to this channel when routing // outbound payments. These can be used in invoice route hints to avoid explicitly revealing // the channel's funding UTXO. + // + // We also use this when sending our peer a channel_update that isn't to be broadcasted + // publicly - allowing them to re-use their map of SCID -> channel for channel_update -> + // associated channel mapping. + // // We only bother storing the most recent SCID alias at any time, though our counterparty has // to store all of them. latest_inbound_scid_alias: Option, @@ -955,7 +960,7 @@ impl Channel { resend_order: RAACommitmentOrder::CommitmentFirst, - monitor_pending_funding_locked: false, + monitor_pending_channel_ready: false, monitor_pending_revoke_and_ack: false, monitor_pending_commitment_signed: false, monitor_pending_forwards: Vec::new(), @@ -1076,16 +1081,22 @@ impl Channel { if channel_type.supports_any_optional_bits() { return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned())); } - // We currently only allow two channel types, so write it all out here - we allow - // `only_static_remote_key` in all contexts, and further allow - // `static_remote_key|scid_privacy` if the channel is not publicly announced. - let mut allowed_type = ChannelTypeFeatures::only_static_remote_key(); - if *channel_type != allowed_type { - allowed_type.set_scid_privacy_required(); - if *channel_type != allowed_type { + + if channel_type.requires_unknown_bits() { + return Err(ChannelError::Close("Channel Type field contains unknown bits".to_owned())); + } + + // We currently only allow four channel types, so write it all out here - we allow + // `only_static_remote_key` or `static_remote_key | zero_conf` in all contexts, and + // further allow `static_remote_key | scid_privacy` or + // `static_remote_key | scid_privacy | zero_conf`, if the channel is not + // publicly announced. + if *channel_type != ChannelTypeFeatures::only_static_remote_key() { + if !channel_type.requires_scid_privacy() && !channel_type.requires_zero_conf() { return Err(ChannelError::Close("Channel Type was not understood".to_owned())); } - if announced_channel { + + if channel_type.requires_scid_privacy() && announced_channel { return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned())); } } @@ -1272,7 +1283,7 @@ impl Channel { resend_order: RAACommitmentOrder::CommitmentFirst, - monitor_pending_funding_locked: false, + monitor_pending_channel_ready: false, monitor_pending_revoke_and_ack: false, monitor_pending_commitment_signed: false, monitor_pending_forwards: Vec::new(), @@ -1307,7 +1318,7 @@ impl Channel { counterparty_htlc_minimum_msat: msg.htlc_minimum_msat, holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat }, counterparty_max_accepted_htlcs: msg.max_accepted_htlcs, - minimum_depth: Some(config.own_channel_config.minimum_depth), + minimum_depth: Some(cmp::max(config.own_channel_config.minimum_depth, 1)), counterparty_forwarding_info: None, @@ -1703,6 +1714,28 @@ impl Channel { make_funding_redeemscript(&self.get_holder_pubkeys().funding_pubkey, self.counterparty_funding_pubkey()) } + /// Claims an HTLC while we're disconnected from a peer, dropping the [`ChannelMonitorUpdate`] + /// entirely. + /// + /// The [`ChannelMonitor`] for this channel MUST be updated out-of-band with the preimage + /// provided (i.e. without calling [`crate::chain::Watch::update_channel`]). + /// + /// The HTLC claim will end up in the holding cell (because the caller must ensure the peer is + /// disconnected). + pub fn claim_htlc_while_disconnected_dropping_mon_update + (&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) + where L::Target: Logger { + // Assert that we'll add the HTLC claim to the holding cell in `get_update_fulfill_htlc` + // (see equivalent if condition there). + assert!(self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateFailed as u32) != 0); + let mon_update_id = self.latest_monitor_update_id; // Forget the ChannelMonitor update + let fulfill_resp = self.get_update_fulfill_htlc(htlc_id_arg, payment_preimage_arg, logger); + self.latest_monitor_update_id = mon_update_id; + if let UpdateFulfillFetch::NewClaim { msg, .. } = fulfill_resp { + assert!(msg.is_none()); // The HTLC must have ended up in the holding cell. + } + } + fn get_update_fulfill_htlc(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) -> UpdateFulfillFetch where L::Target: Logger { // Either ChannelFunded got set (which means it won't be unset) or there is no way any // caller thought we could have something claimed (cause we wouldn't have accepted in an @@ -1765,6 +1798,10 @@ impl Channel { }; if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateFailed as u32)) != 0 { + // Note that this condition is the same as the assertion in + // `claim_htlc_while_disconnected_dropping_mon_update` and must match exactly - + // `claim_htlc_while_disconnected_dropping_mon_update` would not work correctly if we + // do not not get into this branch. for pending_update in self.holding_cell_htlc_updates.iter() { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { @@ -1987,12 +2024,6 @@ impl Channel { if msg.minimum_depth > peer_limits.max_minimum_depth { return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, msg.minimum_depth))); } - if msg.minimum_depth == 0 { - // Note that if this changes we should update the serialization minimum version to - // indicate to older clients that they don't understand some features of the current - // channel. - return Err(ChannelError::Close("Minimum confirmation depth must be at least 1".to_owned())); - } if let Some(ty) = &msg.channel_type { if *ty != self.channel_type { @@ -2029,7 +2060,12 @@ impl Channel { self.counterparty_selected_channel_reserve_satoshis = Some(msg.channel_reserve_satoshis); self.counterparty_htlc_minimum_msat = msg.htlc_minimum_msat; self.counterparty_max_accepted_htlcs = msg.max_accepted_htlcs; - self.minimum_depth = Some(msg.minimum_depth); + + if peer_limits.trust_own_funding_0conf { + self.minimum_depth = Some(msg.minimum_depth); + } else { + self.minimum_depth = Some(cmp::max(1, msg.minimum_depth)); + } let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: msg.funding_pubkey, @@ -2089,7 +2125,7 @@ impl Channel { &self.get_counterparty_pubkeys().funding_pubkey } - pub fn funding_created(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> where L::Target: Logger { + pub fn funding_created(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor, Option), ChannelError> where L::Target: Logger { if self.is_outbound() { return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned())); } @@ -2164,12 +2200,12 @@ impl Channel { Ok((msgs::FundingSigned { channel_id: self.channel_id, signature - }, channel_monitor)) + }, channel_monitor, self.check_get_channel_ready(0))) } /// Handles a funding_signed message from the remote end. /// If this call is successful, broadcast the funding transaction (and not before!) - pub fn funding_signed(&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, logger: &L) -> Result<(ChannelMonitor, Transaction), ChannelError> where L::Target: Logger { + pub fn funding_signed(&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, logger: &L) -> Result<(ChannelMonitor, Transaction, Option), ChannelError> where L::Target: Logger { if !self.is_outbound() { return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned())); } @@ -2238,16 +2274,16 @@ impl Channel { log_info!(logger, "Received funding_signed from peer for channel {}", log_bytes!(self.channel_id())); - Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap())) + Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap(), self.check_get_channel_ready(0))) } - /// Handles a funding_locked message from our peer. If we've already sent our funding_locked + /// Handles a channel_ready message from our peer. If we've already sent our channel_ready /// and the channel is now usable (and public), this may generate an announcement_signatures to /// reply with. - pub fn funding_locked(&mut self, msg: &msgs::FundingLocked, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block: &BestBlock, logger: &L) -> Result, ChannelError> where L::Target: Logger { + pub fn channel_ready(&mut self, msg: &msgs::ChannelReady, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block: &BestBlock, logger: &L) -> Result, ChannelError> where L::Target: Logger { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { self.workaround_lnd_bug_4006 = Some(msg.clone()); - return Err(ChannelError::Ignore("Peer sent funding_locked when we needed a channel_reestablish. The peer is likely lnd, see https://github.com/lightningnetwork/lnd/issues/4006".to_owned())); + return Err(ChannelError::Ignore("Peer sent channel_ready when we needed a channel_reestablish. The peer is likely lnd, see https://github.com/lightningnetwork/lnd/issues/4006".to_owned())); } if let Some(scid_alias) = msg.short_channel_id_alias { @@ -2262,16 +2298,16 @@ impl Channel { let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); if non_shutdown_state == ChannelState::FundingSent as u32 { - self.channel_state |= ChannelState::TheirFundingLocked as u32; - } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) { + self.channel_state |= ChannelState::TheirChannelReady as u32; + } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurChannelReady as u32) { self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS); self.update_time_counter += 1; } else if self.channel_state & (ChannelState::ChannelFunded as u32) != 0 || - // If we reconnected before sending our funding locked they may still resend theirs: - (self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) == - (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32)) + // If we reconnected before sending our `channel_ready` they may still resend theirs: + (self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::TheirChannelReady as u32) == + (ChannelState::FundingSent as u32 | ChannelState::TheirChannelReady as u32)) { - // They probably disconnected/reconnected and re-sent the funding_locked, which is + // They probably disconnected/reconnected and re-sent the channel_ready, which is // required, or they're sending a fresh SCID alias. let expected_point = if self.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 { @@ -2279,24 +2315,24 @@ impl Channel { // the current one. self.counterparty_cur_commitment_point } else { - // If they have sent updated points, funding_locked is always supposed to match + // If they have sent updated points, channel_ready is always supposed to match // their "first" point, which we re-derive here. Some(PublicKey::from_secret_key(&self.secp_ctx, &SecretKey::from_slice( &self.commitment_secrets.get_secret(INITIAL_COMMITMENT_NUMBER - 1).expect("We should have all prev secrets available") ).expect("We already advanced, so previous secret keys should have been validated already"))) }; if expected_point != Some(msg.next_per_commitment_point) { - return Err(ChannelError::Close("Peer sent a reconnect funding_locked with a different point".to_owned())); + return Err(ChannelError::Close("Peer sent a reconnect channel_ready with a different point".to_owned())); } return Ok(None); } else { - return Err(ChannelError::Close("Peer sent a funding_locked at a strange time".to_owned())); + return Err(ChannelError::Close("Peer sent a channel_ready at a strange time".to_owned())); } self.counterparty_prev_commitment_point = self.counterparty_cur_commitment_point; self.counterparty_cur_commitment_point = Some(msg.next_per_commitment_point); - log_info!(logger, "Received funding_locked from peer for channel {}", log_bytes!(self.channel_id())); + log_info!(logger, "Received channel_ready from peer for channel {}", log_bytes!(self.channel_id())); Ok(self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height(), logger)) } @@ -3540,12 +3576,13 @@ impl Channel { /// monitor update failure must *not* have been sent to the remote end, and must instead /// have been dropped. They will be regenerated when monitor_updating_restored is called. pub fn monitor_update_failed(&mut self, resend_raa: bool, resend_commitment: bool, - mut pending_forwards: Vec<(PendingHTLCInfo, u64)>, + resend_channel_ready: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>, mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, mut pending_finalized_claimed_htlcs: Vec ) { self.monitor_pending_revoke_and_ack |= resend_raa; self.monitor_pending_commitment_signed |= resend_commitment; + self.monitor_pending_channel_ready |= resend_channel_ready; self.monitor_pending_forwards.append(&mut pending_forwards); self.monitor_pending_failures.append(&mut pending_fails); self.monitor_pending_finalized_fulfills.append(&mut pending_finalized_claimed_htlcs); @@ -3559,20 +3596,31 @@ impl Channel { assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32); self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32); - let funding_broadcastable = if self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound() { - self.funding_transaction.take() - } else { None }; + // If we're past (or at) the FundingSent stage on an outbound channel, try to + // (re-)broadcast the funding transaction as we may have declined to broadcast it when we + // first received the funding_signed. + let mut funding_broadcastable = + if self.is_outbound() && self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::FundingSent as u32 { + self.funding_transaction.take() + } else { None }; + // That said, if the funding transaction is already confirmed (ie we're active with a + // minimum_depth over 0) don't bother re-broadcasting the confirmed funding tx. + if self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::ChannelFunded as u32 && self.minimum_depth != Some(0) { + funding_broadcastable = None; + } // We will never broadcast the funding transaction when we're in MonitorUpdateFailed (and // we assume the user never directly broadcasts the funding transaction and waits for us to - // do it). Thus, we can only ever hit monitor_pending_funding_locked when we're an inbound - // channel which failed to persist the monitor on funding_created, and we got the funding - // transaction confirmed before the monitor was persisted. - let funding_locked = if self.monitor_pending_funding_locked { - assert!(!self.is_outbound(), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); - self.monitor_pending_funding_locked = false; + // do it). Thus, we can only ever hit monitor_pending_channel_ready when we're + // * an inbound channel that failed to persist the monitor on funding_created and we got + // the funding transaction confirmed before the monitor was persisted, or + // * a 0-conf channel and intended to send the channel_ready before any broadcast at all. + let channel_ready = if self.monitor_pending_channel_ready { + assert!(!self.is_outbound() || self.minimum_depth == Some(0), + "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); + self.monitor_pending_channel_ready = false; let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); - Some(msgs::FundingLocked { + Some(msgs::ChannelReady { channel_id: self.channel_id(), next_per_commitment_point, short_channel_id_alias: Some(self.outbound_scid_alias), @@ -3593,7 +3641,7 @@ impl Channel { self.monitor_pending_commitment_signed = false; return MonitorRestoreUpdates { raa: None, commitment_update: None, order: RAACommitmentOrder::RevokeAndACKFirst, - accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, funding_locked, announcement_sigs + accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, channel_ready, announcement_sigs }; } @@ -3612,7 +3660,7 @@ impl Channel { if commitment_update.is_some() { "a" } else { "no" }, if raa.is_some() { "an" } else { "no" }, match order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"}); MonitorRestoreUpdates { - raa, commitment_update, order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, funding_locked, announcement_sigs + raa, commitment_update, order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, channel_ready, announcement_sigs } } @@ -3784,15 +3832,15 @@ impl Channel { let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height(), logger); if self.channel_state & (ChannelState::FundingSent as u32) == ChannelState::FundingSent as u32 { - // If we're waiting on a monitor update, we shouldn't re-send any funding_locked's. - if self.channel_state & (ChannelState::OurFundingLocked as u32) == 0 || + // If we're waiting on a monitor update, we shouldn't re-send any channel_ready's. + if self.channel_state & (ChannelState::OurChannelReady as u32) == 0 || self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 { if msg.next_remote_commitment_number != 0 { - return Err(ChannelError::Close("Peer claimed they saw a revoke_and_ack but we haven't sent funding_locked yet".to_owned())); + return Err(ChannelError::Close("Peer claimed they saw a revoke_and_ack but we haven't sent channel_ready yet".to_owned())); } // Short circuit the whole handler as there is nothing we can resend them return Ok(ReestablishResponses { - funding_locked: None, + channel_ready: None, raa: None, commitment_update: None, mon_update: None, order: RAACommitmentOrder::CommitmentFirst, holding_cell_failed_htlcs: Vec::new(), @@ -3800,10 +3848,10 @@ impl Channel { }); } - // We have OurFundingLocked set! + // We have OurChannelReady set! let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); return Ok(ReestablishResponses { - funding_locked: Some(msgs::FundingLocked { + channel_ready: Some(msgs::ChannelReady { channel_id: self.channel_id(), next_per_commitment_point, short_channel_id_alias: Some(self.outbound_scid_alias), @@ -3817,7 +3865,7 @@ impl Channel { let required_revoke = if msg.next_remote_commitment_number + 1 == INITIAL_COMMITMENT_NUMBER - self.cur_holder_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. + // Note that if we need to repeat our ChannelReady we'll do that in the next if block. None } else if msg.next_remote_commitment_number + 1 == (INITIAL_COMMITMENT_NUMBER - 1) - self.cur_holder_commitment_transaction_number { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 { @@ -3836,10 +3884,10 @@ impl Channel { // the corresponding revoke_and_ack back yet. let next_counterparty_commitment_number = INITIAL_COMMITMENT_NUMBER - self.cur_counterparty_commitment_transaction_number + if (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) != 0 { 1 } else { 0 }; - let funding_locked = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number == 1 { - // We should never have to worry about MonitorUpdateFailed resending FundingLocked + let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number == 1 { + // We should never have to worry about MonitorUpdateFailed resending ChannelReady let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); - Some(msgs::FundingLocked { + Some(msgs::ChannelReady { channel_id: self.channel_id(), next_per_commitment_point, short_channel_id_alias: Some(self.outbound_scid_alias), @@ -3864,7 +3912,7 @@ impl Channel { panic!("Got non-channel-failing result from free_holding_cell_htlcs"), Ok((Some((commitment_update, monitor_update)), holding_cell_failed_htlcs)) => { Ok(ReestablishResponses { - funding_locked, shutdown_msg, announcement_sigs, + channel_ready, shutdown_msg, announcement_sigs, raa: required_revoke, commitment_update: Some(commitment_update), order: self.resend_order.clone(), @@ -3874,7 +3922,7 @@ impl Channel { }, Ok((None, holding_cell_failed_htlcs)) => { Ok(ReestablishResponses { - funding_locked, shutdown_msg, announcement_sigs, + channel_ready, shutdown_msg, announcement_sigs, raa: required_revoke, commitment_update: None, order: self.resend_order.clone(), @@ -3885,7 +3933,7 @@ impl Channel { } } else { Ok(ReestablishResponses { - funding_locked, shutdown_msg, announcement_sigs, + channel_ready, shutdown_msg, announcement_sigs, raa: required_revoke, commitment_update: None, order: self.resend_order.clone(), @@ -3903,14 +3951,14 @@ impl Channel { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 { self.monitor_pending_commitment_signed = true; Ok(ReestablishResponses { - funding_locked, shutdown_msg, announcement_sigs, + channel_ready, shutdown_msg, announcement_sigs, commitment_update: None, raa: None, mon_update: None, order: self.resend_order.clone(), holding_cell_failed_htlcs: Vec::new(), }) } else { Ok(ReestablishResponses { - funding_locked, shutdown_msg, announcement_sigs, + channel_ready, shutdown_msg, announcement_sigs, raa: required_revoke, commitment_update: Some(self.get_last_commitment_update(logger)), order: self.resend_order.clone(), @@ -4325,7 +4373,7 @@ impl Channel { &self.channel_type } - /// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus, + /// Guaranteed to be Some after both ChannelReady messages have been exchanged (and, thus, /// is_usable() returns true). /// Allowed in any state (including after shutdown) pub fn get_short_channel_id(&self) -> Option { @@ -4530,7 +4578,7 @@ impl Channel { /// Allowed in any state (including after shutdown) pub fn is_usable(&self) -> bool { let mask = ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK; - (self.channel_state & mask) == (ChannelState::ChannelFunded as u32) && !self.monitor_pending_funding_locked + (self.channel_state & mask) == (ChannelState::ChannelFunded as u32) && !self.monitor_pending_channel_ready } /// Returns true if this channel is currently available for use. This is a superset of @@ -4551,6 +4599,11 @@ impl Channel { self.channel_state >= ChannelState::FundingSent as u32 } + /// Returns true if our channel_ready has been sent + pub fn is_our_channel_ready(&self) -> bool { + (self.channel_state & ChannelState::OurChannelReady as u32) != 0 || self.channel_state >= ChannelState::ChannelFunded as u32 + } + /// Returns true if our peer has either initiated or agreed to shut down the channel. pub fn received_shutdown(&self) -> bool { (self.channel_state & ChannelState::RemoteShutdownSent as u32) != 0 @@ -4580,8 +4633,8 @@ impl Channel { self.channel_update_status = status; } - fn check_get_funding_locked(&mut self, height: u32) -> Option { - if self.funding_tx_confirmation_height == 0 { + fn check_get_channel_ready(&mut self, height: u32) -> Option { + if self.funding_tx_confirmation_height == 0 && self.minimum_depth != Some(0) { return None; } @@ -4596,13 +4649,13 @@ impl Channel { let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 { - self.channel_state |= ChannelState::OurFundingLocked as u32; + self.channel_state |= ChannelState::OurChannelReady as u32; true - } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) { + } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirChannelReady as u32) { self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS); self.update_time_counter += 1; true - } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) { + } 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.channel_state < ChannelState::ChannelFunded as u32 { @@ -4617,14 +4670,14 @@ impl Channel { if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { let next_per_commitment_point = self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.secp_ctx); - return Some(msgs::FundingLocked { + return Some(msgs::ChannelReady { channel_id: self.channel_id, next_per_commitment_point, short_channel_id_alias: Some(self.outbound_scid_alias), }); } } else { - self.monitor_pending_funding_locked = true; + self.monitor_pending_channel_ready = true; } } None @@ -4635,13 +4688,12 @@ impl Channel { /// In the second, we simply return an Err indicating we need to be force-closed now. pub fn transactions_confirmed(&mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L) - -> Result<(Option, Option), ClosureReason> where L::Target: Logger { - let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); + -> Result<(Option, Option), ClosureReason> where L::Target: Logger { if let Some(funding_txo) = self.get_funding_txo() { for &(index_in_block, tx) in txdata.iter() { - // If we haven't yet sent a funding_locked, but are in FundingSent (ignoring - // whether they've sent a funding_locked or not), check if we should send one. - if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 { + // 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.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.get_funding_redeemscript().to_v0_p2wsh() || @@ -4677,13 +4729,13 @@ impl Channel { } } } - // If we allow 1-conf funding, we may need to check for funding_locked here and + // 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(funding_locked) = self.check_get_funding_locked(height) { - log_info!(logger, "Sending a funding_locked to our peer for channel {}", log_bytes!(self.channel_id)); + 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.channel_id)); let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger); - return Ok((Some(funding_locked), announcement_sigs)); + return Ok((Some(channel_ready), announcement_sigs)); } } for inp in tx.input.iter() { @@ -4709,12 +4761,12 @@ impl Channel { /// May return some HTLCs (and their payment_hash) which have timed out and should be failed /// back. pub fn best_block_updated(&mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L) - -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where L::Target: Logger { + -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where L::Target: Logger { self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_pk)), logger) } fn do_best_block_updated(&mut self, height: u32, highest_header_time: u32, genesis_node_pk: Option<(BlockHash, PublicKey)>, logger: &L) - -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where L::Target: Logger { + -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where 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 @@ -4734,33 +4786,33 @@ impl Channel { self.update_time_counter = cmp::max(self.update_time_counter, highest_header_time); - if let Some(funding_locked) = self.check_get_funding_locked(height) { + if let Some(channel_ready) = self.check_get_channel_ready(height) { let announcement_sigs = if let Some((genesis_block_hash, node_pk)) = genesis_node_pk { self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger) } else { None }; - log_info!(logger, "Sending a funding_locked to our peer for channel {}", log_bytes!(self.channel_id)); - return Ok((Some(funding_locked), timed_out_htlcs, announcement_sigs)); + log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.channel_id)); + return Ok((Some(channel_ready), timed_out_htlcs, announcement_sigs)); } let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); if non_shutdown_state >= ChannelState::ChannelFunded as u32 || - (non_shutdown_state & ChannelState::OurFundingLocked as u32) == ChannelState::OurFundingLocked as u32 { + (non_shutdown_state & ChannelState::OurChannelReady as u32) == ChannelState::OurChannelReady as u32 { let mut funding_tx_confirmations = height as i64 - self.funding_tx_confirmation_height as i64 + 1; if self.funding_tx_confirmation_height == 0 { - // Note that check_get_funding_locked may reset funding_tx_confirmation_height to + // 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 funding_locked + // indicate we've already sent a channel_ready funding_tx_confirmations = 0; } - // If we've sent funding_locked (or have both sent and received funding_locked), and + // 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 channel, - // but not doing so may lead to the `ChannelManager::short_to_id` map being - // inconsistent, so we currently have to. + // 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_id` map + // being inconsistent, so we currently have to. if funding_tx_confirmations == 0 && self.funding_tx_confirmed_in.is_some() { let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.", self.minimum_depth.unwrap(), funding_tx_confirmations); @@ -4771,7 +4823,7 @@ impl Channel { log_info!(logger, "Closing channel {} due to funding timeout", log_bytes!(self.channel_id)); // If funding_tx_confirmed_in is unset, the channel must not be active assert!(non_shutdown_state <= ChannelState::ChannelFunded as u32); - assert_eq!(non_shutdown_state & ChannelState::OurFundingLocked as u32, 0); + assert_eq!(non_shutdown_state & ChannelState::OurChannelReady as u32, 0); return Err(ClosureReason::FundingTimedOut); } @@ -4783,7 +4835,7 @@ impl Channel { /// 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 funding_locked and we can just wait for more blocks. + /// before the channel has reached channel_ready and we can just wait for more blocks. pub fn funding_transaction_unconfirmed(&mut self, logger: &L) -> Result<(), ClosureReason> where L::Target: Logger { if self.funding_tx_confirmation_height != 0 { // We handle the funding disconnection by calling best_block_updated with a height one @@ -4794,8 +4846,8 @@ impl Channel { // time we saw and it will be ignored. let best_time = self.update_time_counter; match self.do_best_block_updated(reorg_height, best_time, None, logger) { - Ok((funding_locked, timed_out_htlcs, announcement_sigs)) => { - assert!(funding_locked.is_none(), "We can't generate a funding with 0 confirmations?"); + 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(()) @@ -4857,6 +4909,12 @@ impl Channel { self.inbound_awaiting_accept } + /// Sets this channel to accepting 0conf, must be done before `get_accept_channel` + pub fn set_0conf(&mut self) { + assert!(self.inbound_awaiting_accept); + self.minimum_depth = Some(0); + } + /// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannel`] message which /// should be sent back to the counterparty node. /// @@ -4979,7 +5037,7 @@ impl Channel { } /// Gets an UnsignedChannelAnnouncement for this channel. The channel must be publicly - /// announceable and available for use (have exchanged FundingLocked messages in both + /// 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. /// @@ -5400,7 +5458,7 @@ impl Channel { commitment_txid: counterparty_commitment_txid, htlc_outputs: htlcs.clone(), commitment_number: self.cur_counterparty_commitment_transaction_number, - their_revocation_point: self.counterparty_cur_commitment_point.unwrap() + their_per_commitment_point: self.counterparty_cur_commitment_point.unwrap() }] }; self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32; @@ -5619,7 +5677,7 @@ impl Channel { } const SERIALIZATION_VERSION: u8 = 2; -const MIN_SERIALIZATION_VERSION: u8 = 1; +const MIN_SERIALIZATION_VERSION: u8 = 2; impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,; (0, FailRelay), @@ -5684,12 +5742,10 @@ impl Writeable for Channel { self.user_id.write(writer)?; - // Write out the old serialization for the config object. This is read by version-1 - // deserializers, but we will read the version in the TLV at the end instead. - self.config.forwarding_fee_proportional_millionths.write(writer)?; - self.config.cltv_expiry_delta.write(writer)?; - self.config.announced_channel.write(writer)?; - self.config.commit_upfront_shutdown_pubkey.write(writer)?; + // Version 1 deserializers expected to read parts of the config object here. Version 2 + // deserializers (0.0.99) now read config through TLVs, and as we now require them for + // `minimum_depth` we simply write dummy values here. + writer.write_all(&[0; 8])?; self.channel_id.write(writer)?; (self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?; @@ -5821,7 +5877,7 @@ impl Writeable for Channel { RAACommitmentOrder::RevokeAndACKFirst => 1u8.write(writer)?, } - self.monitor_pending_funding_locked.write(writer)?; + self.monitor_pending_channel_ready.write(writer)?; self.monitor_pending_revoke_and_ack.write(writer)?; self.monitor_pending_commitment_signed.write(writer)?; @@ -6082,7 +6138,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel _ => return Err(DecodeError::InvalidValue), }; - let monitor_pending_funding_locked = Readable::read(reader)?; + let monitor_pending_channel_ready = Readable::read(reader)?; let monitor_pending_revoke_and_ack = Readable::read(reader)?; let monitor_pending_commitment_signed = Readable::read(reader)?; @@ -6292,7 +6348,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel resend_order, - monitor_pending_funding_locked, + monitor_pending_channel_ready, monitor_pending_revoke_and_ack, monitor_pending_commitment_signed, monitor_pending_forwards, @@ -6383,7 +6439,7 @@ mod tests { use ln::channelmanager::{HTLCSource, PaymentId}; use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator}; use ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS}; - use ln::features::InitFeatures; + use ln::features::{InitFeatures, ChannelTypeFeatures}; use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate}; use ln::script::ShutdownScript; use ln::chan_utils; @@ -6667,7 +6723,7 @@ mod tests { }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap(); - let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap(); + let (funding_signed_msg, _, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap(); // Node B --> Node A: funding signed let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&logger); @@ -7698,4 +7754,29 @@ mod tests { assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret).unwrap(), SecretKey::from_slice(&hex::decode("d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110").unwrap()[..]).unwrap()); } + + #[test] + fn test_zero_conf_channel_type_support() { + let feeest = TestFeeEstimator{fee_est: 15000}; + let secp_ctx = Secp256k1::new(); + let seed = [42; 32]; + let network = Network::Testnet; + let keys_provider = test_utils::TestKeysInterface::new(&seed, network); + let logger = test_utils::TestLogger::new(); + + let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let config = UserConfig::default(); + let node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, + node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap(); + + let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key(); + channel_type_features.set_zero_conf_required(); + + let mut open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); + open_channel_msg.channel_type = Some(channel_type_features); + let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let res = Channel::::new_from_req(&&feeest, &&keys_provider, + node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42); + assert!(res.is_ok()); + } }