Add baseline OnionMessenger and msgs::OnionMessage and its serialization
[rust-lightning] / lightning / src / ln / channel.rs
index ca02f0a9ac9e302ae10047025097ff24c1fcc7cd..2da743033d3596f5176b17ee6b864f8fa7416679 100644 (file)
@@ -39,7 +39,7 @@ use util::events::ClosureReason;
 use util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
 use util::logger::Logger;
 use util::errors::APIError;
-use util::config::{UserConfig, ChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits};
+use util::config::{UserConfig, ChannelConfig, LegacyChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits};
 use util::scid_utils::scid_from_parts;
 
 use io;
@@ -482,6 +482,16 @@ pub(crate) const CONCURRENT_INBOUND_HTLC_FEE_BUFFER: u32 = 2;
 /// transaction (not counting the value of the HTLCs themselves).
 pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
 
+/// When a [`Channel`] has its [`ChannelConfig`] updated, its existing one is stashed for up to this
+/// number of ticks to allow forwarding HTLCs by nodes that have yet to receive the new
+/// ChannelUpdate prompted by the config update. This value was determined as follows:
+///
+///   * The expected interval between ticks (1 minute).
+///   * The average convergence delay of updates across the network, i.e., ~300 seconds on average
+///      for a node to see an update as seen on `<https://arxiv.org/pdf/2205.12737.pdf>`.
+///   * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
+pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;
+
 // TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
 // has been completed, and then turn into a Channel to get compiler-time enforcement of things like
 // calling channel_id() before we're set up or things like get_outbound_funding_signed on an
@@ -490,10 +500,12 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
 // Holder designates channel data owned for the benefice of the user client.
 // Counterparty designates channel data owned by the another channel participant entity.
 pub(super) struct Channel<Signer: Sign> {
-       #[cfg(any(test, feature = "_test_utils"))]
-       pub(crate) config: ChannelConfig,
-       #[cfg(not(any(test, feature = "_test_utils")))]
-       config: ChannelConfig,
+       config: LegacyChannelConfig,
+
+       // Track the previous `ChannelConfig` so that we can continue forwarding HTLCs that were
+       // constructed using it. The second element in the tuple corresponds to the number of ticks that
+       // have elapsed since the update occurred.
+       prev_config: Option<(ChannelConfig, usize)>,
 
        inbound_handshake_limits_override: Option<ChannelHandshakeLimits>,
 
@@ -790,7 +802,6 @@ pub(super) enum ChannelError {
        Ignore(String),
        Warn(String),
        Close(String),
-       CloseDelayBroadcast(String),
 }
 
 impl fmt::Debug for ChannelError {
@@ -799,7 +810,6 @@ impl fmt::Debug for ChannelError {
                        &ChannelError::Ignore(ref e) => write!(f, "Ignore : {}", e),
                        &ChannelError::Warn(ref e) => write!(f, "Warn : {}", e),
                        &ChannelError::Close(ref e) => write!(f, "Close : {}", e),
-                       &ChannelError::CloseDelayBroadcast(ref e) => write!(f, "CloseDelayBroadcast : {}", e)
                }
        }
 }
@@ -855,7 +865,7 @@ impl<Signer: Sign> Channel<Signer> {
                // 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 {
+               if !config.channel_handshake_config.announced_channel && config.channel_handshake_config.negotiate_scid_privacy {
                        ret.set_scid_privacy_required();
                }
                ret
@@ -885,7 +895,7 @@ impl<Signer: Sign> Channel<Signer> {
        {
                let opt_anchors = false; // TODO - should be based on features
 
-               let holder_selected_contest_delay = config.own_channel_config.our_to_self_delay;
+               let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay;
                let holder_signer = keys_provider.get_channel_signer(false, channel_value_satoshis);
                let pubkeys = holder_signer.pubkeys().clone();
 
@@ -918,7 +928,7 @@ impl<Signer: Sign> Channel<Signer> {
                let mut secp_ctx = Secp256k1::new();
                secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
 
-               let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
+               let shutdown_scriptpubkey = if config.channel_handshake_config.commit_upfront_shutdown_pubkey {
                        Some(keys_provider.get_shutdown_scriptpubkey())
                } else { None };
 
@@ -930,8 +940,16 @@ impl<Signer: Sign> Channel<Signer> {
 
                Ok(Channel {
                        user_id,
-                       config: config.channel_options.clone(),
-                       inbound_handshake_limits_override: Some(config.peer_channel_config_limits.clone()),
+
+                       config: LegacyChannelConfig {
+                               options: config.channel_config.clone(),
+                               announced_channel: config.channel_handshake_config.announced_channel,
+                               commit_upfront_shutdown_pubkey: config.channel_handshake_config.commit_upfront_shutdown_pubkey,
+                       },
+
+                       prev_config: None,
+
+                       inbound_handshake_limits_override: Some(config.channel_handshake_limits.clone()),
 
                        channel_id: keys_provider.get_secure_random_bytes(),
                        channel_state: ChannelState::OurInitSent as u32,
@@ -988,11 +1006,11 @@ impl<Signer: Sign> Channel<Signer> {
                        counterparty_dust_limit_satoshis: 0,
                        holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
                        counterparty_max_htlc_value_in_flight_msat: 0,
-                       holder_max_htlc_value_in_flight_msat: Self::get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &config.own_channel_config),
+                       holder_max_htlc_value_in_flight_msat: Self::get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &config.channel_handshake_config),
                        counterparty_selected_channel_reserve_satoshis: None, // Filled in in accept_channel
                        holder_selected_channel_reserve_satoshis,
                        counterparty_htlc_minimum_msat: 0,
-                       holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
+                       holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 { 1 } else { config.channel_handshake_config.our_htlc_minimum_msat },
                        counterparty_max_accepted_htlcs: 0,
                        minimum_depth: None, // Filled in in accept_channel
 
@@ -1000,7 +1018,7 @@ impl<Signer: Sign> Channel<Signer> {
 
                        channel_transaction_parameters: ChannelTransactionParameters {
                                holder_pubkeys: pubkeys,
-                               holder_selected_contest_delay: config.own_channel_config.our_to_self_delay,
+                               holder_selected_contest_delay: config.channel_handshake_config.our_to_self_delay,
                                is_outbound_from_holder: true,
                                counterparty_parameters: None,
                                funding_outpoint: None,
@@ -1081,16 +1099,22 @@ 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()));
                        }
-                       // 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()));
                                }
                        }
@@ -1111,15 +1135,14 @@ impl<Signer: Sign> Channel<Signer> {
                        delayed_payment_basepoint: msg.delayed_payment_basepoint,
                        htlc_basepoint: msg.htlc_basepoint
                };
-               let mut local_config = (*config).channel_options.clone();
 
-               if config.own_channel_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
-                       return Err(ChannelError::Close(format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks. It must be greater than {}", config.own_channel_config.our_to_self_delay, BREAKDOWN_TIMEOUT)));
+               if config.channel_handshake_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
+                       return Err(ChannelError::Close(format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks. It must be greater than {}", config.channel_handshake_config.our_to_self_delay, BREAKDOWN_TIMEOUT)));
                }
 
                // Check sanity of message fields:
-               if msg.funding_satoshis > config.peer_channel_config_limits.max_funding_satoshis {
-                       return Err(ChannelError::Close(format!("Per our config, funding must be at most {}. It was {}", config.peer_channel_config_limits.max_funding_satoshis, msg.funding_satoshis)));
+               if msg.funding_satoshis > config.channel_handshake_limits.max_funding_satoshis {
+                       return Err(ChannelError::Close(format!("Per our config, funding must be at most {}. It was {}", config.channel_handshake_limits.max_funding_satoshis, msg.funding_satoshis)));
                }
                if msg.funding_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS {
                        return Err(ChannelError::Close(format!("Funding must be smaller than the total bitcoin supply. It was {}", msg.funding_satoshis)));
@@ -1139,7 +1162,7 @@ impl<Signer: Sign> Channel<Signer> {
                }
                Channel::<Signer>::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
 
-               let max_counterparty_selected_contest_delay = u16::min(config.peer_channel_config_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT);
+               let max_counterparty_selected_contest_delay = u16::min(config.channel_handshake_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT);
                if msg.to_self_delay > max_counterparty_selected_contest_delay {
                        return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_counterparty_selected_contest_delay, msg.to_self_delay)));
                }
@@ -1151,20 +1174,20 @@ impl<Signer: Sign> Channel<Signer> {
                }
 
                // Now check against optional parameters as set by config...
-               if msg.funding_satoshis < config.peer_channel_config_limits.min_funding_satoshis {
-                       return Err(ChannelError::Close(format!("Funding satoshis ({}) is less than the user specified limit ({})", msg.funding_satoshis, config.peer_channel_config_limits.min_funding_satoshis)));
+               if msg.funding_satoshis < config.channel_handshake_limits.min_funding_satoshis {
+                       return Err(ChannelError::Close(format!("Funding satoshis ({}) is less than the user specified limit ({})", msg.funding_satoshis, config.channel_handshake_limits.min_funding_satoshis)));
                }
-               if msg.htlc_minimum_msat > config.peer_channel_config_limits.max_htlc_minimum_msat {
-                       return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.htlc_minimum_msat,  config.peer_channel_config_limits.max_htlc_minimum_msat)));
+               if msg.htlc_minimum_msat > config.channel_handshake_limits.max_htlc_minimum_msat {
+                       return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.htlc_minimum_msat,  config.channel_handshake_limits.max_htlc_minimum_msat)));
                }
-               if msg.max_htlc_value_in_flight_msat < config.peer_channel_config_limits.min_max_htlc_value_in_flight_msat {
-                       return Err(ChannelError::Close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", msg.max_htlc_value_in_flight_msat, config.peer_channel_config_limits.min_max_htlc_value_in_flight_msat)));
+               if msg.max_htlc_value_in_flight_msat < config.channel_handshake_limits.min_max_htlc_value_in_flight_msat {
+                       return Err(ChannelError::Close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", msg.max_htlc_value_in_flight_msat, config.channel_handshake_limits.min_max_htlc_value_in_flight_msat)));
                }
-               if msg.channel_reserve_satoshis > config.peer_channel_config_limits.max_channel_reserve_satoshis {
-                       return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg.channel_reserve_satoshis, config.peer_channel_config_limits.max_channel_reserve_satoshis)));
+               if msg.channel_reserve_satoshis > config.channel_handshake_limits.max_channel_reserve_satoshis {
+                       return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg.channel_reserve_satoshis, config.channel_handshake_limits.max_channel_reserve_satoshis)));
                }
-               if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs {
-                       return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs)));
+               if msg.max_accepted_htlcs < config.channel_handshake_limits.min_max_accepted_htlcs {
+                       return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.channel_handshake_limits.min_max_accepted_htlcs)));
                }
                if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
                        return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
@@ -1175,13 +1198,11 @@ impl<Signer: Sign> Channel<Signer> {
 
                // Convert things into internal flags and prep our state:
 
-               if config.peer_channel_config_limits.force_announced_channel_preference {
-                       if local_config.announced_channel != announced_channel {
+               if config.channel_handshake_limits.force_announced_channel_preference {
+                       if config.channel_handshake_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 = 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 {
@@ -1233,7 +1254,7 @@ impl<Signer: Sign> Channel<Signer> {
                        }
                } else { None };
 
-               let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
+               let shutdown_scriptpubkey = if config.channel_handshake_config.commit_upfront_shutdown_pubkey {
                        Some(keys_provider.get_shutdown_scriptpubkey())
                } else { None };
 
@@ -1248,7 +1269,15 @@ impl<Signer: Sign> Channel<Signer> {
 
                let chan = Channel {
                        user_id,
-                       config: local_config,
+
+                       config: LegacyChannelConfig {
+                               options: config.channel_config.clone(),
+                               announced_channel,
+                               commit_upfront_shutdown_pubkey: config.channel_handshake_config.commit_upfront_shutdown_pubkey,
+                       },
+
+                       prev_config: None,
+
                        inbound_handshake_limits_override: None,
 
                        channel_id: msg.temporary_channel_id,
@@ -1306,19 +1335,19 @@ impl<Signer: Sign> Channel<Signer> {
                        counterparty_dust_limit_satoshis: msg.dust_limit_satoshis,
                        holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
                        counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000),
-                       holder_max_htlc_value_in_flight_msat: Self::get_holder_max_htlc_value_in_flight_msat(msg.funding_satoshis, &config.own_channel_config),
+                       holder_max_htlc_value_in_flight_msat: Self::get_holder_max_htlc_value_in_flight_msat(msg.funding_satoshis, &config.channel_handshake_config),
                        counterparty_selected_channel_reserve_satoshis: Some(msg.channel_reserve_satoshis),
                        holder_selected_channel_reserve_satoshis,
                        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 },
+                       holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 { 1 } else { config.channel_handshake_config.our_htlc_minimum_msat },
                        counterparty_max_accepted_htlcs: msg.max_accepted_htlcs,
-                       minimum_depth: Some(cmp::max(config.own_channel_config.minimum_depth, 1)),
+                       minimum_depth: Some(cmp::max(config.channel_handshake_config.minimum_depth, 1)),
 
                        counterparty_forwarding_info: None,
 
                        channel_transaction_parameters: ChannelTransactionParameters {
                                holder_pubkeys: pubkeys,
-                               holder_selected_contest_delay: config.own_channel_config.our_to_self_delay,
+                               holder_selected_contest_delay: config.channel_handshake_config.our_to_self_delay,
                                is_outbound_from_holder: false,
                                counterparty_parameters: Some(CounterpartyChannelTransactionParameters {
                                        selected_contest_delay: msg.to_self_delay,
@@ -3768,6 +3797,11 @@ impl<Signer: Sign> Channel<Signer> {
 
        /// 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.
+       ///
+       /// Some links printed in log lines are included here to check them during build (when run with
+       /// `cargo doc --document-private-items`):
+       /// [`super::channelmanager::ChannelManager::force_close_without_broadcasting_txn`] and
+       /// [`super::channelmanager::ChannelManager::force_close_all_channels_without_broadcasting_txn`].
        pub fn channel_reestablish<L: Deref>(&mut self, msg: &msgs::ChannelReestablish, logger: &L,
                node_pk: PublicKey, genesis_block_hash: BlockHash, best_block: &BestBlock)
        -> Result<ReestablishResponses, ChannelError> where L::Target: Logger {
@@ -3793,9 +3827,20 @@ impl<Signer: Sign> Channel<Signer> {
                                                return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided".to_owned()));
                                        }
                                        if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number {
-                                               return Err(ChannelError::CloseDelayBroadcast(
-                                                       "We have fallen behind - we have received proof that if we broadcast remote is going to claim our funds - we can't do any automated broadcasting".to_owned()
-                                               ));
+                                               macro_rules! log_and_panic {
+                                                       ($err_msg: expr) => {
+                                                               log_error!(logger, $err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
+                                                               panic!($err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
+                                                       }
+                                               }
+                                               log_and_panic!("We have fallen behind - we have received proof that if we broadcast our counterparty is going to claim all our funds.\n\
+                                                       This implies you have restarted with lost ChannelMonitor and ChannelManager state, the first of which is a violation of the LDK chain::Watch requirements.\n\
+                                                       More specifically, this means you have a bug in your implementation that can cause loss of funds, or you are running with an old backup, which is unsafe.\n\
+                                                       If you have restored from an old backup and wish to force-close channels and return to operation, you should start up, call\n\
+                                                       ChannelManager::force_close_without_broadcasting_txn on channel {} with counterparty {} or\n\
+                                                       ChannelManager::force_close_all_channels_without_broadcasting_txn, then reconnect to peer(s).\n\
+                                                       Note that due to a long-standing bug in lnd you may have to reach out to peers running lnd-based nodes to ask them to manually force-close channels\n\
+                                                       See https://github.com/lightningdevkit/rust-lightning/issues/1565 for more info.");
                                        }
                                },
                                OptionalField::Absent => {}
@@ -3902,7 +3947,7 @@ impl<Signer: Sign> Channel<Signer> {
                                // now!
                                match self.free_holding_cell_htlcs(logger) {
                                        Err(ChannelError::Close(msg)) => Err(ChannelError::Close(msg)),
-                                       Err(ChannelError::Warn(_)) | Err(ChannelError::Ignore(_)) | Err(ChannelError::CloseDelayBroadcast(_)) =>
+                                       Err(ChannelError::Warn(_)) | Err(ChannelError::Ignore(_)) =>
                                                panic!("Got non-channel-failing result from free_holding_cell_htlcs"),
                                        Ok((Some((commitment_update, monitor_update)), holding_cell_failed_htlcs)) => {
                                                Ok(ReestablishResponses {
@@ -4005,7 +4050,7 @@ impl<Signer: Sign> Channel<Signer> {
                                // We always add force_close_avoidance_max_fee_satoshis to our normal
                                // feerate-calculated fee, but allow the max to be overridden if we're using a
                                // target feerate-calculated fee.
-                               cmp::max(normal_feerate as u64 * tx_weight / 1000 + self.config.force_close_avoidance_max_fee_satoshis,
+                               cmp::max(normal_feerate as u64 * tx_weight / 1000 + self.config.options.force_close_avoidance_max_fee_satoshis,
                                        proposed_max_feerate as u64 * tx_weight / 1000)
                        } else {
                                self.channel_value_satoshis - (self.value_to_self_msat + 999) / 1000
@@ -4465,15 +4510,93 @@ impl<Signer: Sign> Channel<Signer> {
        }
 
        pub fn get_fee_proportional_millionths(&self) -> u32 {
-               self.config.forwarding_fee_proportional_millionths
+               self.config.options.forwarding_fee_proportional_millionths
        }
 
        pub fn get_cltv_expiry_delta(&self) -> u16 {
-               cmp::max(self.config.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA)
+               cmp::max(self.config.options.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA)
        }
 
        pub fn get_max_dust_htlc_exposure_msat(&self) -> u64 {
-               self.config.max_dust_htlc_exposure_msat
+               self.config.options.max_dust_htlc_exposure_msat
+       }
+
+       /// Returns the previous [`ChannelConfig`] applied to this channel, if any.
+       pub fn prev_config(&self) -> Option<ChannelConfig> {
+               self.prev_config.map(|prev_config| prev_config.0)
+       }
+
+       /// Tracks the number of ticks elapsed since the previous [`ChannelConfig`] was updated. Once
+       /// [`EXPIRE_PREV_CONFIG_TICKS`] is reached, the previous config is considered expired and will
+       /// no longer be considered when forwarding HTLCs.
+       pub fn maybe_expire_prev_config(&mut self) {
+               if self.prev_config.is_none() {
+                       return;
+               }
+               let prev_config = self.prev_config.as_mut().unwrap();
+               prev_config.1 += 1;
+               if prev_config.1 == EXPIRE_PREV_CONFIG_TICKS {
+                       self.prev_config = None;
+               }
+       }
+
+       /// Returns the current [`ChannelConfig`] applied to the channel.
+       pub fn config(&self) -> ChannelConfig {
+               self.config.options
+       }
+
+       /// Updates the channel's config. A bool is returned indicating whether the config update
+       /// applied resulted in a new ChannelUpdate message.
+       pub fn update_config(&mut self, config: &ChannelConfig) -> bool {
+               let did_channel_update =
+                       self.config.options.forwarding_fee_proportional_millionths != config.forwarding_fee_proportional_millionths ||
+                       self.config.options.forwarding_fee_base_msat != config.forwarding_fee_base_msat ||
+                       self.config.options.cltv_expiry_delta != config.cltv_expiry_delta;
+               if did_channel_update {
+                       self.prev_config = Some((self.config.options, 0));
+                       // Update the counter, which backs the ChannelUpdate timestamp, to allow the relay
+                       // policy change to propagate throughout the network.
+                       self.update_time_counter += 1;
+               }
+               self.config.options = *config;
+               did_channel_update
+       }
+
+       fn internal_htlc_satisfies_config(
+               &self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, config: &ChannelConfig,
+       ) -> Result<(), (&'static str, u16)> {
+               let fee = amt_to_forward.checked_mul(config.forwarding_fee_proportional_millionths as u64)
+                       .and_then(|prop_fee| (prop_fee / 1000000).checked_add(config.forwarding_fee_base_msat as u64));
+               if fee.is_none() || htlc.amount_msat < fee.unwrap() ||
+                       (htlc.amount_msat - fee.unwrap()) < amt_to_forward {
+                       return Err((
+                               "Prior hop has deviated from specified fees parameters or origin node has obsolete ones",
+                               0x1000 | 12, // fee_insufficient
+                       ));
+               }
+               if (htlc.cltv_expiry as u64) < outgoing_cltv_value as u64 + config.cltv_expiry_delta as u64 {
+                       return Err((
+                               "Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
+                               0x1000 | 13, // incorrect_cltv_expiry
+                       ));
+               }
+               Ok(())
+       }
+
+       /// Determines whether the parameters of an incoming HTLC to be forwarded satisfy the channel's
+       /// [`ChannelConfig`]. This first looks at the channel's current [`ChannelConfig`], and if
+       /// unsuccessful, falls back to the previous one if one exists.
+       pub fn htlc_satisfies_config(
+               &self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32,
+       ) -> Result<(), (&'static str, u16)> {
+               self.internal_htlc_satisfies_config(&htlc, amt_to_forward, outgoing_cltv_value, &self.config())
+                       .or_else(|err| {
+                               if let Some(prev_config) = self.prev_config() {
+                                       self.internal_htlc_satisfies_config(htlc, amt_to_forward, outgoing_cltv_value, &prev_config)
+                               } else {
+                                       Err(err)
+                               }
+                       })
        }
 
        pub fn get_feerate(&self) -> u32 {
@@ -4560,7 +4683,7 @@ impl<Signer: Sign> Channel<Signer> {
        /// Gets the fee we'd want to charge for adding an HTLC output to this Channel
        /// Allowed in any state (including after shutdown)
        pub fn get_outbound_forwarding_fee_base_msat(&self) -> u32 {
-               self.config.forwarding_fee_base_msat
+               self.config.options.forwarding_fee_base_msat
        }
 
        /// Returns true if we've ever received a message from the remote end for this Channel
@@ -4652,9 +4775,17 @@ impl<Signer: Sign> Channel<Signer> {
                } 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 {
-                       panic!("Started confirming a channel in a state pre-FundingSent?: {}", self.channel_state);
                } else {
+                       if self.channel_state < ChannelState::ChannelFunded 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.channel_state);
+                       }
                        // We got a reorg but not enough to trigger a force close, just ignore.
                        false
                };
@@ -5973,7 +6104,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
                        if self.holder_selected_channel_reserve_satoshis != Self::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis)
                        { Some(self.holder_selected_channel_reserve_satoshis) } else { None };
 
-               let mut old_max_in_flight_percent_config = UserConfig::default().own_channel_config;
+               let mut old_max_in_flight_percent_config = UserConfig::default().channel_handshake_config;
                old_max_in_flight_percent_config.max_inbound_htlc_value_in_flight_percent_of_channel = MAX_IN_FLIGHT_PERCENT_LEGACY;
                let serialized_holder_htlc_max_in_flight =
                        if self.holder_max_htlc_value_in_flight_msat != Self::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis, &old_max_in_flight_percent_config)
@@ -6016,11 +6147,11 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
 
                let user_id = Readable::read(reader)?;
 
-               let mut config = Some(ChannelConfig::default());
+               let mut config = Some(LegacyChannelConfig::default());
                if ver == 1 {
                        // Read the old serialization of the ChannelConfig from version 0.0.98.
-                       config.as_mut().unwrap().forwarding_fee_proportional_millionths = Readable::read(reader)?;
-                       config.as_mut().unwrap().cltv_expiry_delta = Readable::read(reader)?;
+                       config.as_mut().unwrap().options.forwarding_fee_proportional_millionths = Readable::read(reader)?;
+                       config.as_mut().unwrap().options.cltv_expiry_delta = Readable::read(reader)?;
                        config.as_mut().unwrap().announced_channel = Readable::read(reader)?;
                        config.as_mut().unwrap().commit_upfront_shutdown_pubkey = Readable::read(reader)?;
                } else {
@@ -6246,7 +6377,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
                let mut target_closing_feerate_sats_per_kw = None;
                let mut monitor_pending_finalized_fulfills = Some(Vec::new());
                let mut holder_selected_channel_reserve_satoshis = Some(Self::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis));
-               let mut holder_max_htlc_value_in_flight_msat = Some(Self::get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &UserConfig::default().own_channel_config));
+               let mut holder_max_htlc_value_in_flight_msat = Some(Self::get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &UserConfig::default().channel_handshake_config));
                // Prior to supporting channel type negotiation, all of our channels were static_remotekey
                // only, so we default to that if none was written.
                let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key());
@@ -6316,6 +6447,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
 
                        config: config.unwrap(),
 
+                       prev_config: None,
+
                        // Note that we don't care about serializing handshake limits as we only ever serialize
                        // channel data after the handshake has completed.
                        inbound_handshake_limits_override: None,
@@ -6433,7 +6566,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;
@@ -6450,6 +6583,7 @@ mod tests {
        use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
        use bitcoin::secp256k1::ffi::Signature as FFISignature;
        use bitcoin::secp256k1::{SecretKey,PublicKey};
+       use bitcoin::secp256k1::ecdh::SharedSecret;
        use bitcoin::secp256k1::ecdsa::RecoverableSignature;
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::hashes::Hash;
@@ -6488,6 +6622,7 @@ mod tests {
                type Signer = InMemorySigner;
 
                fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> { panic!(); }
+               fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&[u8; 32]>) -> Result<SharedSecret, ()> { panic!(); }
                fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); }
                fn get_destination_script(&self) -> Script {
                        let secp_ctx = Secp256k1::signing_only();
@@ -6591,7 +6726,7 @@ mod tests {
                // Node B --> Node A: accept channel, explicitly setting B's dust limit.
                let mut accept_channel_msg = node_b_chan.accept_inbound_channel(0);
                accept_channel_msg.dust_limit_satoshis = 546;
-               node_a_chan.accept_channel(&accept_channel_msg, &config.peer_channel_config_limits, &InitFeatures::known()).unwrap();
+               node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &InitFeatures::known()).unwrap();
                node_a_chan.holder_dust_limit_satoshis = 1560;
 
                // Put some inbound and outbound HTLCs in A's channel.
@@ -6708,7 +6843,7 @@ mod tests {
 
                // Node B --> Node A: accept channel
                let accept_channel_msg = node_b_chan.accept_inbound_channel(0);
-               node_a_chan.accept_channel(&accept_channel_msg, &config.peer_channel_config_limits, &InitFeatures::known()).unwrap();
+               node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &InitFeatures::known()).unwrap();
 
                // Node A --> Node B: funding created
                let output_script = node_a_chan.get_funding_redeemscript();
@@ -6761,13 +6896,13 @@ mod tests {
                let inbound_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
 
                let mut config_2_percent = UserConfig::default();
-               config_2_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 2;
+               config_2_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 2;
                let mut config_99_percent = UserConfig::default();
-               config_99_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 99;
+               config_99_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 99;
                let mut config_0_percent = UserConfig::default();
-               config_0_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 0;
+               config_0_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 0;
                let mut config_101_percent = UserConfig::default();
-               config_101_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 101;
+               config_101_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 101;
 
                // Test that `new_outbound` creates a channel with the correct value for
                // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
@@ -6912,7 +7047,7 @@ mod tests {
 
                let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let mut config = UserConfig::default();
-               config.channel_options.announced_channel = false;
+               config.channel_handshake_config.announced_channel = false;
                let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
                chan.holder_dust_limit_satoshis = 546;
                chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel
@@ -7748,4 +7883,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::<EnforcingSigner>::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::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider,
+                       node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42);
+               assert!(res.is_ok());
+       }
 }