X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=0792164e20d588a043de6700e0c23ca3956eff9d;hb=952cee4a168d266d7bdd43d21ac71a3e3de46a53;hp=65f1be00008994242bf518e85bfc7527d21bf033;hpb=84fa127661ff09de94ac6129dd0790d6de79f8b7;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 65f1be00..0792164e 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -810,6 +810,31 @@ impl Channel { 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 { + 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( fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures, @@ -967,10 +992,7 @@ impl Channel { #[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 Channel { 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 Channel { 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 Channel { // 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::::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 Channel { } 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 Channel { 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 Channel { 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 Channel { 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,