Add notes about SCID alias rotation to `ChannelDetails` docs
[rust-lightning] / lightning / src / ln / channel.rs
index 65f1be00008994242bf518e85bfc7527d21bf033..0792164e20d588a043de6700e0c23ca3956eff9d 100644 (file)
@@ -810,6 +810,31 @@ impl<Signer: Sign> Channel<Signer> {
                self.channel_transaction_parameters.opt_anchors.is_some()
        }
 
+       fn get_initial_channel_type(config: &UserConfig) -> ChannelTypeFeatures {
+               // The default channel type (ie the first one we try) depends on whether the channel is
+               // public - if it is, we just go with `only_static_remotekey` as it's the only option
+               // available. If it's private, we first try `scid_privacy` as it provides better privacy
+               // with no other changes, and fall back to `only_static_remotekey`
+               let mut ret = ChannelTypeFeatures::only_static_remote_key();
+               if !config.channel_options.announced_channel && config.own_channel_config.negotiate_scid_privacy {
+                       ret.set_scid_privacy_required();
+               }
+               ret
+       }
+
+       /// If we receive an error message, it may only be a rejection of the channel type we tried,
+       /// not of our ability to open any channel at all. Thus, on error, we should first call this
+       /// and see if we get a new `OpenChannel` message, otherwise the channel is failed.
+       pub(crate) fn maybe_handle_error_without_close(&mut self, chain_hash: BlockHash) -> Result<msgs::OpenChannel, ()> {
+               if !self.is_outbound() || self.channel_state != ChannelState::OurInitSent as u32 { return Err(()); }
+               if self.channel_type == ChannelTypeFeatures::only_static_remote_key() {
+                       // We've exhausted our options
+                       return Err(());
+               }
+               self.channel_type = ChannelTypeFeatures::only_static_remote_key(); // We only currently support two types
+               Ok(self.get_open_channel(chain_hash))
+       }
+
        // Constructors:
        pub fn new_outbound<K: Deref, F: Deref>(
                fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
@@ -967,10 +992,7 @@ impl<Signer: Sign> Channel<Signer> {
                        #[cfg(any(test, fuzzing))]
                        historical_inbound_htlc_fulfills: HashSet::new(),
 
-                       // We currently only actually support one channel type, so don't retry with new types
-                       // on error messages. When we support more we'll need fallback support (assuming we
-                       // want to support old types).
-                       channel_type: ChannelTypeFeatures::only_static_remote_key(),
+                       channel_type: Self::get_initial_channel_type(&config),
                })
        }
 
@@ -1009,6 +1031,7 @@ impl<Signer: Sign> Channel<Signer> {
                      L::Target: Logger,
        {
                let opt_anchors = false; // TODO - should be based on features
+               let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false };
 
                // First check the channel type is known, failing before we do anything else if we don't
                // support this channel type.
@@ -1016,8 +1039,18 @@ impl<Signer: Sign> Channel<Signer> {
                        if channel_type.supports_any_optional_bits() {
                                return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
                        }
-                       if *channel_type != ChannelTypeFeatures::only_static_remote_key() {
-                               return Err(ChannelError::Close("Channel Type was not understood".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 {
+                                       return Err(ChannelError::Close("Channel Type was not understood".to_owned()));
+                               }
+                               if announced_channel {
+                                       return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
+                               }
                        }
                        channel_type.clone()
                } else {
@@ -1098,14 +1131,13 @@ impl<Signer: Sign> Channel<Signer> {
 
                // Convert things into internal flags and prep our state:
 
-               let announce = if (msg.channel_flags & 1) == 1 { true } else { false };
                if config.peer_channel_config_limits.force_announced_channel_preference {
-                       if local_config.announced_channel != announce {
+                       if local_config.announced_channel != announced_channel {
                                return Err(ChannelError::Close("Peer tried to open channel but their announcement preference is different from ours".to_owned()));
                        }
                }
                // we either accept their preference or the preferences match
-               local_config.announced_channel = announce;
+               local_config.announced_channel = announced_channel;
 
                let holder_selected_channel_reserve_satoshis = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis);
                if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
@@ -2188,17 +2220,28 @@ impl<Signer: Sign> Channel<Signer> {
                } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked 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 &&
-                                // Note that funding_signed/funding_created will have decremented both by 1!
-                                self.cur_holder_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 &&
-                                self.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1) ||
-                               // 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 self.counterparty_cur_commitment_point != Some(msg.next_per_commitment_point) {
+               } 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))
+               {
+                       // They probably disconnected/reconnected and re-sent the funding_locked, 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 {
+                                       // If they haven't ever sent an updated point, the point they send should match
+                                       // the current one.
+                                       self.counterparty_cur_commitment_point
+                               } else {
+                                       // If they have sent updated points, funding_locked 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()));
                        }
-                       // They probably disconnected/reconnected and re-sent the funding_locked, which is required
                        return Ok(None);
                } else {
                        return Err(ChannelError::Close("Peer sent a funding_locked at a strange time".to_owned()));
@@ -4221,6 +4264,11 @@ impl<Signer: Sign> Channel<Signer> {
                self.user_id
        }
 
+       /// Gets the channel's type
+       pub fn get_channel_type(&self) -> &ChannelTypeFeatures {
+               &self.channel_type
+       }
+
        /// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
        /// is_usable() returns true).
        /// Allowed in any state (including after shutdown)
@@ -4238,7 +4286,7 @@ impl<Signer: Sign> Channel<Signer> {
                self.outbound_scid_alias
        }
        /// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0,
-       /// indicating we were written by an old LDK which did not set outbound SCID aliases.
+       /// indicating we were written by LDK prior to 0.0.106 which did not set outbound SCID aliases.
        pub fn set_outbound_scid_alias(&mut self, outbound_scid_alias: u64) {
                assert_eq!(self.outbound_scid_alias, 0);
                self.outbound_scid_alias = outbound_scid_alias;
@@ -4492,7 +4540,8 @@ impl<Signer: Sign> Channel<Signer> {
                if need_commitment_update {
                        if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 {
                                if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
-                                       let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
+                                       let next_per_commitment_point =
+                                               self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.secp_ctx);
                                        return Some(msgs::FundingLocked {
                                                channel_id: self.channel_id,
                                                next_per_commitment_point,