X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=b1cd603f021d61564af75f2aa8216452973feb0a;hb=1ee0a66d21cfd3696ed93938ba08281a0c342741;hp=195e261fe6f785568f0013ebc16d10460e51c4bf;hpb=883afb38d47cb5d8d8721a356302b1e41b7c476c;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 195e261f..b1cd603f 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -784,6 +784,96 @@ pub(super) struct ChannelContext { pending_monitor_updates: Vec, } +impl ChannelContext { + pub(crate) fn opt_anchors(&self) -> bool { + self.channel_transaction_parameters.opt_anchors.is_some() + } + + /// Allowed in any state (including after shutdown) + pub fn get_update_time_counter(&self) -> u32 { + self.update_time_counter + } + + pub fn get_latest_monitor_update_id(&self) -> u64 { + self.latest_monitor_update_id + } + + pub fn should_announce(&self) -> bool { + self.config.announced_channel + } + + pub fn is_outbound(&self) -> bool { + self.channel_transaction_parameters.is_outbound_from_holder + } + + /// 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.options.forwarding_fee_base_msat + } + + /// Returns true if we've ever received a message from the remote end for this Channel + pub fn have_received_message(&self) -> bool { + self.channel_state > (ChannelState::OurInitSent as u32) + } + + /// Returns true if this channel is fully established and not known to be closing. + /// Allowed in any state (including after shutdown) + pub fn is_usable(&self) -> bool { + let mask = ChannelState::ChannelReady as u32 | BOTH_SIDES_SHUTDOWN_MASK; + (self.channel_state & mask) == (ChannelState::ChannelReady as u32) && !self.monitor_pending_channel_ready + } + + /// Returns true if this channel is currently available for use. This is a superset of + /// is_usable() and considers things like the channel being temporarily disabled. + /// Allowed in any state (including after shutdown) + pub fn is_live(&self) -> bool { + self.is_usable() && (self.channel_state & (ChannelState::PeerDisconnected as u32) == 0) + } +} + +// Internal utility functions for channels + +/// Returns the value to use for `holder_max_htlc_value_in_flight_msat` as a percentage of the +/// `channel_value_satoshis` in msat, set through +/// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`] +/// +/// The effective percentage is lower bounded by 1% and upper bounded by 100%. +/// +/// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`]: crate::util::config::ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel +fn get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis: u64, config: &ChannelHandshakeConfig) -> u64 { + let configured_percent = if config.max_inbound_htlc_value_in_flight_percent_of_channel < 1 { + 1 + } else if config.max_inbound_htlc_value_in_flight_percent_of_channel > 100 { + 100 + } else { + config.max_inbound_htlc_value_in_flight_percent_of_channel as u64 + }; + channel_value_satoshis * 10 * configured_percent +} + +/// Returns a minimum channel reserve value the remote needs to maintain, +/// required by us according to the configured or default +/// [`ChannelHandshakeConfig::their_channel_reserve_proportional_millionths`] +/// +/// Guaranteed to return a value no larger than channel_value_satoshis +/// +/// This is used both for outbound and inbound channels and has lower bound +/// of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`. +pub(crate) fn get_holder_selected_channel_reserve_satoshis(channel_value_satoshis: u64, config: &UserConfig) -> u64 { + let calculated_reserve = channel_value_satoshis.saturating_mul(config.channel_handshake_config.their_channel_reserve_proportional_millionths as u64) / 1_000_000; + cmp::min(channel_value_satoshis, cmp::max(calculated_reserve, MIN_THEIR_CHAN_RESERVE_SATOSHIS)) +} + +/// This is for legacy reasons, present for forward-compatibility. +/// LDK versions older than 0.0.104 don't know how read/handle values other than default +/// from storage. Hence, we use this function to not persist default values of +/// `holder_selected_channel_reserve_satoshis` for channels into storage. +pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 { + let (q, _) = channel_value_satoshis.overflowing_div(100); + cmp::min(channel_value_satoshis, cmp::max(q, 1000)) +} + // 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 @@ -884,50 +974,6 @@ macro_rules! secp_check { } impl Channel { - /// Returns the value to use for `holder_max_htlc_value_in_flight_msat` as a percentage of the - /// `channel_value_satoshis` in msat, set through - /// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`] - /// - /// The effective percentage is lower bounded by 1% and upper bounded by 100%. - /// - /// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`]: crate::util::config::ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel - fn get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis: u64, config: &ChannelHandshakeConfig) -> u64 { - let configured_percent = if config.max_inbound_htlc_value_in_flight_percent_of_channel < 1 { - 1 - } else if config.max_inbound_htlc_value_in_flight_percent_of_channel > 100 { - 100 - } else { - config.max_inbound_htlc_value_in_flight_percent_of_channel as u64 - }; - channel_value_satoshis * 10 * configured_percent - } - - /// Returns a minimum channel reserve value the remote needs to maintain, - /// required by us according to the configured or default - /// [`ChannelHandshakeConfig::their_channel_reserve_proportional_millionths`] - /// - /// Guaranteed to return a value no larger than channel_value_satoshis - /// - /// This is used both for outbound and inbound channels and has lower bound - /// of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`. - pub(crate) fn get_holder_selected_channel_reserve_satoshis(channel_value_satoshis: u64, config: &UserConfig) -> u64 { - let calculated_reserve = channel_value_satoshis.saturating_mul(config.channel_handshake_config.their_channel_reserve_proportional_millionths as u64) / 1_000_000; - cmp::min(channel_value_satoshis, cmp::max(calculated_reserve, MIN_THEIR_CHAN_RESERVE_SATOSHIS)) - } - - /// This is for legacy reasons, present for forward-compatibility. - /// LDK versions older than 0.0.104 don't know how read/handle values other than default - /// from storage. Hence, we use this function to not persist default values of - /// `holder_selected_channel_reserve_satoshis` for channels into storage. - pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 { - let (q, _) = channel_value_satoshis.overflowing_div(100); - cmp::min(channel_value_satoshis, cmp::max(q, 1000)) - } - - pub(crate) fn opt_anchors(&self) -> bool { - self.context.channel_transaction_parameters.opt_anchors.is_some() - } - fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> 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 @@ -958,7 +1004,7 @@ impl Channel { /// 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.context.channel_state != ChannelState::OurInitSent as u32 { return Err(()); } + if !self.context.is_outbound() || self.context.channel_state != ChannelState::OurInitSent as u32 { return Err(()); } if self.context.channel_type == ChannelTypeFeatures::only_static_remote_key() { // We've exhausted our options return Err(()); @@ -1012,7 +1058,7 @@ impl Channel { if holder_selected_contest_delay < BREAKDOWN_TIMEOUT { return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)}); } - let holder_selected_channel_reserve_satoshis = Channel::::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config); + let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config); if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { // Protocol level safety check in place, although it should never happen because // of `MIN_THEIR_CHAN_RESERVE_SATOSHIS` @@ -1123,7 +1169,7 @@ impl Channel { 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.channel_handshake_config), + holder_max_htlc_value_in_flight_msat: 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, @@ -1339,7 +1385,7 @@ impl Channel { } } - let holder_selected_channel_reserve_satoshis = Channel::::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis, config); + let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis, config); if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { // Protocol level safety check in place, although it should never happen because // of `MIN_THEIR_CHAN_RESERVE_SATOSHIS` @@ -1482,7 +1528,7 @@ impl Channel { 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.channel_handshake_config), + holder_max_htlc_value_in_flight_msat: 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, @@ -1578,9 +1624,9 @@ impl Channel { if match update_state { // Note that these match the inclusion criteria when scanning // pending_inbound_htlcs below. - FeeUpdateState::RemoteAnnounced => { debug_assert!(!self.is_outbound()); !generated_by_local }, - FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { debug_assert!(!self.is_outbound()); !generated_by_local }, - FeeUpdateState::Outbound => { assert!(self.is_outbound()); generated_by_local }, + FeeUpdateState::RemoteAnnounced => { debug_assert!(!self.context.is_outbound()); !generated_by_local }, + FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { debug_assert!(!self.context.is_outbound()); !generated_by_local }, + FeeUpdateState::Outbound => { assert!(self.context.is_outbound()); generated_by_local }, } { feerate_per_kw = feerate; } @@ -1588,7 +1634,7 @@ impl Channel { log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for channel {} for {}, generated by {} with fee {}...", commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number), - get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()), + get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.context.is_outbound()), log_bytes!(self.context.channel_id), if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw); macro_rules! get_htlc_in_commitment { @@ -1607,7 +1653,7 @@ impl Channel { ($htlc: expr, $outbound: expr, $source: expr, $state_name: expr) => { if $outbound == local { // "offered HTLC output" let htlc_in_tx = get_htlc_in_commitment!($htlc, true); - let htlc_tx_fee = if self.opt_anchors() { + let htlc_tx_fee = if self.context.opt_anchors() { 0 } else { feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000 @@ -1621,7 +1667,7 @@ impl Channel { } } else { let htlc_in_tx = get_htlc_in_commitment!($htlc, false); - let htlc_tx_fee = if self.opt_anchors() { + let htlc_tx_fee = if self.context.opt_anchors() { 0 } else { feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000 @@ -1731,7 +1777,7 @@ impl Channel { let total_fee_sat = Channel::::commit_tx_fee_sat(feerate_per_kw, included_non_dust_htlcs.len(), self.context.channel_transaction_parameters.opt_anchors.is_some()); let anchors_val = if self.context.channel_transaction_parameters.opt_anchors.is_some() { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 } as i64; - let (value_to_self, value_to_remote) = if self.is_outbound() { + let (value_to_self, value_to_remote) = if self.context.is_outbound() { (value_to_self_msat / 1000 - anchors_val - total_fee_sat as i64, value_to_remote_msat / 1000) } else { (value_to_self_msat / 1000, value_to_remote_msat / 1000 - anchors_val - total_fee_sat as i64) @@ -1836,14 +1882,14 @@ impl Channel { assert!(self.context.pending_update_fee.is_none()); let mut total_fee_satoshis = proposed_total_fee_satoshis; - let mut value_to_holder: i64 = (self.context.value_to_self_msat as i64) / 1000 - if self.is_outbound() { total_fee_satoshis as i64 } else { 0 }; - let mut value_to_counterparty: i64 = ((self.context.channel_value_satoshis * 1000 - self.context.value_to_self_msat) as i64 / 1000) - if self.is_outbound() { 0 } else { total_fee_satoshis as i64 }; + let mut value_to_holder: i64 = (self.context.value_to_self_msat as i64) / 1000 - if self.context.is_outbound() { total_fee_satoshis as i64 } else { 0 }; + let mut value_to_counterparty: i64 = ((self.context.channel_value_satoshis * 1000 - self.context.value_to_self_msat) as i64 / 1000) - if self.context.is_outbound() { 0 } else { total_fee_satoshis as i64 }; if value_to_holder < 0 { - assert!(self.is_outbound()); + assert!(self.context.is_outbound()); total_fee_satoshis += (-value_to_holder) as u64; } else if value_to_counterparty < 0 { - assert!(!self.is_outbound()); + assert!(!self.context.is_outbound()); total_fee_satoshis += (-value_to_counterparty) as u64; } @@ -2212,7 +2258,7 @@ impl Channel { let peer_limits = if let Some(ref limits) = self.context.inbound_handshake_limits_override { limits } else { default_limits }; // Check sanity of message fields: - if !self.is_outbound() { + if !self.context.is_outbound() { return Err(ChannelError::Close("Got an accept_channel message from an inbound peer".to_owned())); } if self.context.channel_state != ChannelState::OurInitSent as u32 { @@ -2380,7 +2426,7 @@ impl Channel { SP::Target: SignerProvider, L::Target: Logger { - if self.is_outbound() { + if self.context.is_outbound() { return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned())); } if self.context.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) { @@ -2432,7 +2478,7 @@ impl Channel { let funding_redeemscript = self.get_funding_redeemscript(); let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); - let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()); + let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.context.is_outbound()); let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id); monitor_signer.provide_channel_parameters(&self.context.channel_transaction_parameters); @@ -2473,7 +2519,7 @@ impl Channel { SP::Target: SignerProvider, L::Target: Logger { - if !self.is_outbound() { + if !self.context.is_outbound() { return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned())); } if self.context.channel_state & !(ChannelState::MonitorUpdateInProgress as u32) != ChannelState::FundingCreated as u32 { @@ -2522,7 +2568,7 @@ impl Channel { let funding_redeemscript = self.get_funding_redeemscript(); let funding_txo = self.get_funding_txo().unwrap(); let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); - let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()); + let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.context.is_outbound()); let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id); monitor_signer.provide_channel_parameters(&self.context.channel_transaction_parameters); @@ -2640,7 +2686,7 @@ impl Channel { on_holder_tx_holding_cell_htlcs_count: 0, }; - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() { + let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.opt_anchors() { (0, 0) } else { let dust_buffer_feerate = self.get_dust_buffer_feerate(outbound_feerate_update) as u64; @@ -2672,7 +2718,7 @@ impl Channel { on_holder_tx_holding_cell_htlcs_count: 0, }; - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() { + let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.opt_anchors() { (0, 0) } else { let dust_buffer_feerate = self.get_dust_buffer_feerate(outbound_feerate_update) as u64; @@ -2733,7 +2779,7 @@ impl Channel { let mut available_capacity_msat = outbound_capacity_msat; - if self.is_outbound() { + if self.context.is_outbound() { // We should mind channel commit tx fee when computing how much of the available capacity // can be used in the next htlc. Mirrors the logic in send_htlc. // @@ -2742,7 +2788,7 @@ impl Channel { // dependency. // This complicates the computation around dust-values, up to the one-htlc-value. let mut real_dust_limit_timeout_sat = self.context.holder_dust_limit_satoshis; - if !self.opt_anchors() { + if !self.context.opt_anchors() { real_dust_limit_timeout_sat += self.context.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000; } @@ -2768,7 +2814,7 @@ impl Channel { // If the channel is inbound (i.e. counterparty pays the fee), we need to make sure // sending a new HTLC won't reduce their balance below our reserve threshold. let mut real_dust_limit_success_sat = self.context.counterparty_dust_limit_satoshis; - if !self.opt_anchors() { + if !self.context.opt_anchors() { real_dust_limit_success_sat += self.context.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000; } @@ -2795,7 +2841,7 @@ impl Channel { let mut remaining_msat_below_dust_exposure_limit = None; let mut dust_exposure_dust_limit_msat = 0; - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.context.opt_anchors() { (self.context.counterparty_dust_limit_satoshis, self.context.holder_dust_limit_satoshis) } else { let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64; @@ -2875,9 +2921,9 @@ impl Channel { /// /// Dust HTLCs are excluded. fn next_local_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 { - assert!(self.is_outbound()); + assert!(self.context.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.context.opt_anchors() { (0, 0) } else { (self.context.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000, @@ -2940,12 +2986,12 @@ impl Channel { } let num_htlcs = included_htlcs + addl_htlcs; - let res = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs, self.opt_anchors()); + let res = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs, self.context.opt_anchors()); #[cfg(any(test, fuzzing))] { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs - 1, self.opt_anchors()); + fee = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs - 1, self.context.opt_anchors()); } let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len() + self.context.holding_cell_htlc_updates.len(); @@ -2978,9 +3024,9 @@ impl Channel { /// /// Dust HTLCs are excluded. fn next_remote_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 { - assert!(!self.is_outbound()); + assert!(!self.context.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.context.opt_anchors() { (0, 0) } else { (self.context.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000, @@ -3030,12 +3076,12 @@ impl Channel { } let num_htlcs = included_htlcs + addl_htlcs; - let res = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs, self.opt_anchors()); + let res = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs, self.context.opt_anchors()); #[cfg(any(test, fuzzing))] { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs - 1, self.opt_anchors()); + fee = Self::commit_tx_fee_msat(self.context.feerate_per_kw, num_htlcs - 1, self.context.opt_anchors()); } let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len(); let commitment_tx_info = CommitmentTxInfoCached { @@ -3110,7 +3156,7 @@ impl Channel { } } - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() { + let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.opt_anchors() { (0, 0) } else { let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64; @@ -3147,7 +3193,7 @@ impl Channel { // Check that the remote can afford to pay for this HTLC on-chain at the current // feerate_per_kw, while maintaining their channel reserve (as required by the spec). - let remote_commit_tx_fee_msat = if self.is_outbound() { 0 } else { + let remote_commit_tx_fee_msat = if self.context.is_outbound() { 0 } else { let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); self.next_remote_commit_tx_fee_msat(htlc_candidate, None) // Don't include the extra fee spike buffer HTLC in calculations }; @@ -3159,7 +3205,7 @@ impl Channel { return Err(ChannelError::Close("Remote HTLC add would put them under remote reserve value".to_owned())); } - if !self.is_outbound() { + if !self.context.is_outbound() { // `2 *` and `Some(())` is for the fee spike buffer we keep for the remote. This deviates from // the spec because in the spec, the fee spike buffer requirement doesn't exist on the // receiver's side, only on the sender's. @@ -3315,7 +3361,7 @@ impl Channel { update_state == FeeUpdateState::RemoteAnnounced } else { false }; if update_fee { - debug_assert!(!self.is_outbound()); + debug_assert!(!self.context.is_outbound()); let counterparty_reserve_we_require_msat = self.context.holder_selected_channel_reserve_satoshis * 1000; if commitment_stats.remote_balance_msat < commitment_stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat { return Err(ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned())); @@ -3323,7 +3369,7 @@ impl Channel { } #[cfg(any(test, fuzzing))] { - if self.is_outbound() { + if self.context.is_outbound() { let projected_commit_tx_info = self.context.next_local_commitment_tx_fee_info_cached.lock().unwrap().take(); *self.context.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None; if let Some(info) = projected_commit_tx_info { @@ -3363,11 +3409,11 @@ impl Channel { for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() { if let Some(_) = htlc.transaction_output_index { let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw, - self.get_counterparty_selected_contest_delay().unwrap(), &htlc, self.opt_anchors(), + self.get_counterparty_selected_contest_delay().unwrap(), &htlc, self.context.opt_anchors(), false, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); - let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, self.opt_anchors(), &keys); - let htlc_sighashtype = if self.opt_anchors() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; + let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, self.context.opt_anchors(), &keys); + let htlc_sighashtype = if self.context.opt_anchors() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]); log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.serialize()), @@ -3783,14 +3829,14 @@ impl Channel { if let Some((feerate, update_state)) = self.context.pending_update_fee { match update_state { FeeUpdateState::Outbound => { - debug_assert!(self.is_outbound()); + debug_assert!(self.context.is_outbound()); log_trace!(logger, " ...promoting outbound fee update {} to Committed", feerate); self.context.feerate_per_kw = feerate; self.context.pending_update_fee = None; }, - FeeUpdateState::RemoteAnnounced => { debug_assert!(!self.is_outbound()); }, + FeeUpdateState::RemoteAnnounced => { debug_assert!(!self.context.is_outbound()); }, FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { - debug_assert!(!self.is_outbound()); + debug_assert!(!self.context.is_outbound()); log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce fee update {} to Committed", feerate); require_commitment = true; self.context.feerate_per_kw = feerate; @@ -3869,13 +3915,13 @@ impl Channel { /// You MUST call [`Self::send_commitment_no_state_update`] prior to any other calls on this /// [`Channel`] if `force_holding_cell` is false. fn send_update_fee(&mut self, feerate_per_kw: u32, mut force_holding_cell: bool, logger: &L) -> Option where L::Target: Logger { - if !self.is_outbound() { + if !self.context.is_outbound() { panic!("Cannot send fee from inbound channel"); } - if !self.is_usable() { + if !self.context.is_usable() { panic!("Cannot update fee until channel is fully established and we haven't started shutting down"); } - if !self.is_live() { + if !self.context.is_live() { panic!("Cannot update fee while peer is disconnected/we're awaiting a monitor update (ChannelManager should have caught this)"); } @@ -3884,7 +3930,7 @@ impl Channel { let outbound_stats = self.get_outbound_pending_htlc_stats(Some(feerate_per_kw)); let keys = self.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); let commitment_stats = self.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger); - let buffer_fee_msat = Channel::::commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + outbound_stats.on_holder_tx_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.opt_anchors()) * 1000; + let buffer_fee_msat = Channel::::commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + outbound_stats.on_holder_tx_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.opt_anchors()) * 1000; let holder_balance_msat = commitment_stats.local_balance_msat - outbound_stats.holding_cell_msat; if holder_balance_msat < buffer_fee_msat + self.context.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 { //TODO: auto-close after a number of failures? @@ -3980,7 +4026,7 @@ impl Channel { if let Some((_, update_state)) = self.context.pending_update_fee { if update_state == FeeUpdateState::RemoteAnnounced { - debug_assert!(!self.is_outbound()); + debug_assert!(!self.context.is_outbound()); self.context.pending_update_fee = None; } } @@ -4049,7 +4095,7 @@ impl Channel { // (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.context.channel_state & !MULTI_STATE_FLAGS >= ChannelState::FundingSent as u32 { + if self.context.is_outbound() && self.context.channel_state & !MULTI_STATE_FLAGS >= ChannelState::FundingSent as u32 { self.context.funding_transaction.take() } else { None }; // That said, if the funding transaction is already confirmed (ie we're active with a @@ -4065,7 +4111,7 @@ impl Channel { // 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.context.monitor_pending_channel_ready { - assert!(!self.is_outbound() || self.context.minimum_depth == Some(0), + assert!(!self.context.is_outbound() || self.context.minimum_depth == Some(0), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); self.context.monitor_pending_channel_ready = false; let next_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); @@ -4117,7 +4163,7 @@ impl Channel { pub fn update_fee(&mut self, fee_estimator: &LowerBoundedFeeEstimator, msg: &msgs::UpdateFee, logger: &L) -> Result<(), ChannelError> where F::Target: FeeEstimator, L::Target: Logger { - if self.is_outbound() { + if self.context.is_outbound() { return Err(ChannelError::Close("Non-funding remote tried to update channel fee".to_owned())); } if self.context.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { @@ -4208,7 +4254,7 @@ impl Channel { } } - let update_fee = if self.is_outbound() && self.context.pending_update_fee.is_some() { + let update_fee = if self.context.is_outbound() && self.context.pending_update_fee.is_some() { Some(msgs::UpdateFee { channel_id: self.channel_id(), feerate_per_kw: self.context.pending_update_fee.unwrap().0, @@ -4419,7 +4465,7 @@ impl Channel { // If we fail to come to consensus, we'll have to force-close. let mut proposed_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background); let normal_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal); - let mut proposed_max_feerate = if self.is_outbound() { normal_feerate } else { u32::max_value() }; + let mut proposed_max_feerate = if self.context.is_outbound() { normal_feerate } else { u32::max_value() }; // The spec requires that (when the channel does not have anchors) we only send absolute // channel fees no greater than the absolute channel fee on the current commitment @@ -4428,7 +4474,7 @@ impl Channel { // some force-closure by old nodes, but we wanted to close the channel anyway. if let Some(target_feerate) = self.context.target_closing_feerate_sats_per_kw { - let min_feerate = if self.is_outbound() { target_feerate } else { cmp::min(self.context.feerate_per_kw, target_feerate) }; + let min_feerate = if self.context.is_outbound() { target_feerate } else { cmp::min(self.context.feerate_per_kw, target_feerate) }; proposed_feerate = cmp::max(proposed_feerate, min_feerate); proposed_max_feerate = cmp::max(proposed_max_feerate, min_feerate); } @@ -4442,7 +4488,7 @@ impl Channel { // if the funders' output is dust we have to know the absolute fee we're going to use. let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.context.counterparty_shutdown_scriptpubkey.as_ref().unwrap())); let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000; - let proposed_max_total_fee_satoshis = if self.is_outbound() { + let proposed_max_total_fee_satoshis = if self.context.is_outbound() { // 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. @@ -4492,7 +4538,7 @@ impl Channel { return Ok((None, None)); } - if !self.is_outbound() { + if !self.context.is_outbound() { if let Some(msg) = &self.context.pending_counterparty_closing_signed.take() { return self.closing_signed(fee_estimator, &msg); } @@ -4685,7 +4731,7 @@ impl Channel { return Err(ChannelError::Close("Remote tried to send us a closing tx with > 21 million BTC fee".to_owned())); } - if self.is_outbound() && self.context.last_sent_closing_fee.is_none() { + if self.context.is_outbound() && self.context.last_sent_closing_fee.is_none() { return Err(ChannelError::Close("Remote tried to send a closing_signed when we were supposed to propose the first one".to_owned())); } @@ -4773,7 +4819,7 @@ impl Channel { return Err(ChannelError::Warn(format!("Unable to come to consensus about closing feerate, remote's min fee ({} sat) was greater than our max fee ({} sat)", min_fee_satoshis, our_max_fee))); } - if !self.is_outbound() { + if !self.context.is_outbound() { // They have to pay, so pick the highest fee in the overlapping range. // We should never set an upper bound aside from their full balance debug_assert_eq!(our_max_fee, self.context.channel_value_satoshis - (self.context.value_to_self_msat + 999) / 1000); @@ -4993,7 +5039,7 @@ impl Channel { // Checks whether we should emit a `ChannelReady` event. pub(crate) fn should_emit_channel_ready_event(&mut self) -> bool { - self.is_usable() && !self.context.channel_ready_event_emitted + self.context.is_usable() && !self.context.channel_ready_event_emitted } // Remembers that we already emitted a `ChannelReady` event. @@ -5138,48 +5184,6 @@ impl Channel { } } - /// Allowed in any state (including after shutdown) - pub fn get_update_time_counter(&self) -> u32 { - self.context.update_time_counter - } - - pub fn get_latest_monitor_update_id(&self) -> u64 { - self.context.latest_monitor_update_id - } - - pub fn should_announce(&self) -> bool { - self.context.config.announced_channel - } - - pub fn is_outbound(&self) -> bool { - self.context.channel_transaction_parameters.is_outbound_from_holder - } - - /// 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.context.config.options.forwarding_fee_base_msat - } - - /// Returns true if we've ever received a message from the remote end for this Channel - pub fn have_received_message(&self) -> bool { - self.context.channel_state > (ChannelState::OurInitSent as u32) - } - - /// Returns true if this channel is fully established and not known to be closing. - /// Allowed in any state (including after shutdown) - pub fn is_usable(&self) -> bool { - let mask = ChannelState::ChannelReady as u32 | BOTH_SIDES_SHUTDOWN_MASK; - (self.context.channel_state & mask) == (ChannelState::ChannelReady as u32) && !self.context.monitor_pending_channel_ready - } - - /// Returns true if this channel is currently available for use. This is a superset of - /// is_usable() and considers things like the channel being temporarily disabled. - /// Allowed in any state (including after shutdown) - pub fn is_live(&self) -> bool { - self.is_usable() && (self.context.channel_state & (ChannelState::PeerDisconnected as u32) == 0) - } - /// Returns true if this channel has been marked as awaiting a monitor update to move forward. /// Allowed in any state (including after shutdown) pub fn is_awaiting_monitor_update(&self) -> bool { @@ -5187,7 +5191,7 @@ impl Channel { } pub fn get_latest_complete_monitor_update_id(&self) -> u64 { - if self.context.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); } + if self.context.pending_monitor_updates.is_empty() { return self.context.get_latest_monitor_update_id(); } self.context.pending_monitor_updates[0].update.update_id - 1 } @@ -5279,7 +5283,7 @@ impl Channel { // Because deciding we're awaiting initial broadcast spuriously could result in // funds-loss (as we don't have a monitor, but have the funding transaction confirmed), // we hard-assert here, even in production builds. - if self.is_outbound() { assert!(self.context.funding_transaction.is_some()); } + if self.context.is_outbound() { assert!(self.context.funding_transaction.is_some()); } assert!(self.context.monitor_pending_channel_ready); assert_eq!(self.context.latest_monitor_update_id, 0); return true; @@ -5402,7 +5406,7 @@ impl Channel { 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() || tx.output[txo_idx].value != self.context.channel_value_satoshis { - if self.is_outbound() { + if self.context.is_outbound() { // If we generated the funding transaction and it doesn't match what it // should, the client is really broken and we should just panic and // tell them off. That said, because hash collisions happen with high @@ -5415,7 +5419,7 @@ impl Channel { let err_reason = "funding tx had wrong script/value or output index"; return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() }); } else { - if self.is_outbound() { + if self.context.is_outbound() { for input in tx.input.iter() { if input.witness.is_empty() { // We generated a malleable funding transaction, implying we've @@ -5535,7 +5539,7 @@ impl Channel { self.context.minimum_depth.unwrap(), funding_tx_confirmations); return Err(ClosureReason::ProcessingError { err: err_reason }); } - } else if !self.is_outbound() && self.context.funding_tx_confirmed_in.is_none() && + } else if !self.context.is_outbound() && self.context.funding_tx_confirmed_in.is_none() && height >= self.context.channel_creation_height + FUNDING_CONF_DEADLINE_BLOCKS { log_info!(logger, "Closing channel {} due to funding timeout", log_bytes!(self.context.channel_id)); // If funding_tx_confirmed_in is unset, the channel must not be active @@ -5581,7 +5585,7 @@ impl Channel { // something in the handler for the message that prompted this message): pub fn get_open_channel(&self, chain_hash: BlockHash) -> msgs::OpenChannel { - if !self.is_outbound() { + if !self.context.is_outbound() { panic!("Tried to open a channel for an inbound channel?"); } if self.context.channel_state != ChannelState::OurInitSent as u32 { @@ -5637,7 +5641,7 @@ impl Channel { /// /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel pub fn accept_inbound_channel(&mut self, user_id: u128) -> msgs::AcceptChannel { - if self.is_outbound() { + if self.context.is_outbound() { panic!("Tried to send accept_channel for an outbound channel?"); } if self.context.channel_state != (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32) { @@ -5715,7 +5719,7 @@ impl Channel { /// Do NOT broadcast the funding transaction until after a successful funding_signed call! /// If an Err is returned, it is a ChannelError::Close. pub fn get_outbound_funding_created(&mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L) -> Result where L::Target: Logger { - if !self.is_outbound() { + if !self.context.is_outbound() { panic!("Tried to create outbound funding_created message on an inbound channel!"); } if self.context.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) { @@ -5774,7 +5778,7 @@ impl Channel { if !self.context.config.announced_channel { return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned())); } - if !self.is_usable() { + if !self.context.is_usable() { return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned())); } @@ -5809,7 +5813,7 @@ impl Channel { return None; } - if !self.is_usable() { + if !self.context.is_usable() { return None; } @@ -6122,7 +6126,7 @@ impl Channel { } if let Some((feerate, update_state)) = self.context.pending_update_fee { if update_state == FeeUpdateState::AwaitingRemoteRevokeToAnnounce { - debug_assert!(!self.is_outbound()); + debug_assert!(!self.context.is_outbound()); log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce fee update {} to Committed", feerate); self.context.feerate_per_kw = feerate; self.context.pending_update_fee = None; @@ -6159,7 +6163,7 @@ impl Channel { #[cfg(any(test, fuzzing))] { - if !self.is_outbound() { + if !self.context.is_outbound() { let projected_commit_tx_info = self.context.next_remote_commitment_tx_fee_info_cached.lock().unwrap().take(); *self.context.next_local_commitment_tx_fee_info_cached.lock().unwrap() = None; if let Some(info) = projected_commit_tx_info { @@ -6168,7 +6172,7 @@ impl Channel { && info.next_holder_htlc_id == self.context.next_holder_htlc_id && info.next_counterparty_htlc_id == self.context.next_counterparty_htlc_id && info.feerate == self.context.feerate_per_kw { - let actual_fee = Self::commit_tx_fee_msat(self.context.feerate_per_kw, commitment_stats.num_nondust_htlcs, self.opt_anchors()); + let actual_fee = Self::commit_tx_fee_msat(self.context.feerate_per_kw, commitment_stats.num_nondust_htlcs, self.context.opt_anchors()); assert_eq!(actual_fee, info.fee); } } @@ -6208,8 +6212,8 @@ impl Channel { for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) { log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}", - encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.get_holder_selected_contest_delay(), htlc, self.opt_anchors(), false, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)), - encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, self.opt_anchors(), &counterparty_keys)), + encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.get_holder_selected_contest_delay(), htlc, self.context.opt_anchors(), false, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)), + encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, self.context.opt_anchors(), &counterparty_keys)), log_bytes!(counterparty_keys.broadcaster_htlc_key.serialize()), log_bytes!(htlc_sig.serialize_compact()[..]), log_bytes!(self.channel_id())); } @@ -6648,7 +6652,7 @@ impl Writeable for Channel { fail_reason.write(writer)?; } - if self.is_outbound() { + if self.context.is_outbound() { self.context.pending_update_fee.map(|(a, _)| a).write(writer)?; } else if let Some((feerate, FeeUpdateState::AwaitingRemoteRevokeToAnnounce)) = self.context.pending_update_fee { Some(feerate).write(writer)?; @@ -6730,13 +6734,13 @@ impl Writeable for Channel { // a different percentage of the channel value then 10%, which older versions of LDK used // to set it to before the percentage was made configurable. let serialized_holder_selected_reserve = - if self.context.holder_selected_channel_reserve_satoshis != Self::get_legacy_default_holder_selected_channel_reserve_satoshis(self.context.channel_value_satoshis) + if self.context.holder_selected_channel_reserve_satoshis != get_legacy_default_holder_selected_channel_reserve_satoshis(self.context.channel_value_satoshis) { Some(self.context.holder_selected_channel_reserve_satoshis) } else { None }; 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.context.holder_max_htlc_value_in_flight_msat != Self::get_holder_max_htlc_value_in_flight_msat(self.context.channel_value_satoshis, &old_max_in_flight_percent_config) + if self.context.holder_max_htlc_value_in_flight_msat != get_holder_max_htlc_value_in_flight_msat(self.context.channel_value_satoshis, &old_max_in_flight_percent_config) { Some(self.context.holder_max_htlc_value_in_flight_msat) } else { None }; let channel_pending_event_emitted = Some(self.context.channel_pending_event_emitted); @@ -7033,8 +7037,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch let mut announcement_sigs = None; 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_legacy_default_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().channel_handshake_config)); + let mut holder_selected_channel_reserve_satoshis = Some(get_legacy_default_holder_selected_channel_reserve_satoshis(channel_value_satoshis)); + let mut holder_max_htlc_value_in_flight_msat = Some(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()); @@ -7469,13 +7473,13 @@ mod tests { // the dust limit check. let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered); let local_commit_tx_fee = node_a_chan.next_local_commit_tx_fee_msat(htlc_candidate, None); - let local_commit_fee_0_htlcs = Channel::::commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.opt_anchors()); + let local_commit_fee_0_htlcs = Channel::::commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.context.opt_anchors()); assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs); // Finally, make sure that when Node A calculates the remote's commitment transaction fees, all // of the HTLCs are seen to be above the dust limit. node_a_chan.context.channel_transaction_parameters.is_outbound_from_holder = false; - let remote_commit_fee_3_htlcs = Channel::::commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.opt_anchors()); + let remote_commit_fee_3_htlcs = Channel::::commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.context.opt_anchors()); let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered); let remote_commit_tx_fee = node_a_chan.next_remote_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs); @@ -7497,18 +7501,18 @@ mod tests { let config = UserConfig::default(); let mut chan = Channel::::new_outbound(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); - let commitment_tx_fee_0_htlcs = Channel::::commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.opt_anchors()); - let commitment_tx_fee_1_htlc = Channel::::commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.opt_anchors()); + let commitment_tx_fee_0_htlcs = Channel::::commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.context.opt_anchors()); + let commitment_tx_fee_1_htlc = Channel::::commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.context.opt_anchors()); // If HTLC_SUCCESS_TX_WEIGHT and HTLC_TIMEOUT_TX_WEIGHT were swapped: then this HTLC would be // counted as dust when it shouldn't be. - let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.opt_anchors()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000; + let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.opt_anchors()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000; let htlc_candidate = HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered); let commitment_tx_fee = chan.next_local_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc); // If swapped: this HTLC would be counted as non-dust when it shouldn't be. - let dust_htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.opt_anchors()) / 1000) + chan.context.holder_dust_limit_satoshis - 1) * 1000; + let dust_htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.opt_anchors()) / 1000) + chan.context.holder_dust_limit_satoshis - 1) * 1000; let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered); let commitment_tx_fee = chan.next_local_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs); @@ -7516,13 +7520,13 @@ mod tests { chan.context.channel_transaction_parameters.is_outbound_from_holder = false; // If swapped: this HTLC would be counted as non-dust when it shouldn't be. - let dust_htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.opt_anchors()) / 1000) + chan.context.counterparty_dust_limit_satoshis + 1) * 1000; + let dust_htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.opt_anchors()) / 1000) + chan.context.counterparty_dust_limit_satoshis + 1) * 1000; let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered); let commitment_tx_fee = chan.next_remote_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs); // If swapped: this HTLC would be counted as dust when it shouldn't be. - let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.opt_anchors()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000; + let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.opt_anchors()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000; let htlc_candidate = HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered); let commitment_tx_fee = chan.next_remote_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);