X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=db38588230b77e153f967aba6781296fe459967d;hb=86fd9e7fbc549f1e556063301a22a5bb3bc1f333;hp=26b70f286257a447ca0487819833c710303370df;hpb=5e528ff6bb141ea1044114128406b6a6b194c4b1;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 26b70f28..db385882 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -309,10 +309,10 @@ pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; pub const DEFAULT_MAX_HTLCS: u16 = 50; -pub(crate) fn commitment_tx_base_weight(opt_anchors: bool) -> u64 { +pub(crate) fn commitment_tx_base_weight(channel_type_features: &ChannelTypeFeatures) -> u64 { const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; const COMMITMENT_TX_BASE_ANCHOR_WEIGHT: u64 = 1124; - if opt_anchors { COMMITMENT_TX_BASE_ANCHOR_WEIGHT } else { COMMITMENT_TX_BASE_WEIGHT } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { COMMITMENT_TX_BASE_ANCHOR_WEIGHT } else { COMMITMENT_TX_BASE_WEIGHT } } #[cfg(not(test))] @@ -588,17 +588,10 @@ pub(crate) const DISCONNECT_PEER_AWAITING_RESPONSE_TICKS: usize = 2; struct PendingChannelMonitorUpdate { update: ChannelMonitorUpdate, - /// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an - /// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is - /// blocked on some external event and the [`ChannelManager`] will update us when we're ready. - /// - /// [`ChannelManager`]: super::channelmanager::ChannelManager - blocked: bool, } impl_writeable_tlv_based!(PendingChannelMonitorUpdate, { (0, update, required), - (2, blocked, required), }); /// Contains everything about the channel including state, and various flags. @@ -869,18 +862,12 @@ pub(super) struct ChannelContext { /// [`SignerProvider::derive_channel_signer`]. channel_keys_id: [u8; 32], - /// When we generate [`ChannelMonitorUpdate`]s to persist, they may not be persisted immediately. - /// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence - /// completes we still need to be able to complete the persistence. Thus, we have to keep a - /// copy of the [`ChannelMonitorUpdate`] here until it is complete. - pending_monitor_updates: Vec, + /// If we can't release a [`ChannelMonitorUpdate`] until some external action completes, we + /// store it here and only release it to the `ChannelManager` once it asks for it. + blocked_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 @@ -1207,10 +1194,10 @@ impl ChannelContext { ($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.get_channel_type().supports_anchors_zero_fee_htlc_tx() { 0 } else { - feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000 + feerate_per_kw as u64 * htlc_timeout_tx_weight(self.get_channel_type()) / 1000 }; if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee { log_trace!(logger, " ...including {} {} HTLC {} (hash {}) with value {}", if $outbound { "outbound" } else { "inbound" }, $state_name, $htlc.htlc_id, log_bytes!($htlc.payment_hash.0), $htlc.amount_msat); @@ -1221,10 +1208,10 @@ impl ChannelContext { } } 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.get_channel_type().supports_anchors_zero_fee_htlc_tx() { 0 } else { - feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000 + feerate_per_kw as u64 * htlc_success_tx_weight(self.get_channel_type()) / 1000 }; if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee { log_trace!(logger, " ...including {} {} HTLC {} (hash {}) with value {}", if $outbound { "outbound" } else { "inbound" }, $state_name, $htlc.htlc_id, log_bytes!($htlc.payment_hash.0), $htlc.amount_msat); @@ -1329,8 +1316,8 @@ impl ChannelContext { broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat as u64); } - let total_fee_sat = commit_tx_fee_sat(feerate_per_kw, included_non_dust_htlcs.len(), self.channel_transaction_parameters.opt_anchors.is_some()); - let anchors_val = if self.channel_transaction_parameters.opt_anchors.is_some() { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 } as i64; + let total_fee_sat = commit_tx_fee_sat(feerate_per_kw, included_non_dust_htlcs.len(), &self.channel_transaction_parameters.channel_type_features); + let anchors_val = if self.channel_transaction_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx() { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 } as i64; let (value_to_self, value_to_remote) = if self.is_outbound() { (value_to_self_msat / 1000 - anchors_val - total_fee_sat as i64, value_to_remote_msat / 1000) } else { @@ -1365,7 +1352,6 @@ impl ChannelContext { let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, value_to_a as u64, value_to_b as u64, - self.channel_transaction_parameters.opt_anchors.is_some(), funding_pubkey_a, funding_pubkey_b, keys.clone(), @@ -1473,12 +1459,12 @@ impl ChannelContext { on_holder_tx_holding_cell_htlcs_count: 0, }; - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.opt_anchors() { + let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { (0, 0) } else { let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64; - (dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000, - dust_buffer_feerate * htlc_success_tx_weight(false) / 1000) + (dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000, + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000) }; let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis; let holder_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis; @@ -1506,12 +1492,12 @@ impl ChannelContext { on_holder_tx_holding_cell_htlcs_count: 0, }; - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.opt_anchors() { + let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { (0, 0) } else { let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64; - (dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000, - dust_buffer_feerate * htlc_success_tx_weight(false) / 1000) + (dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000, + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000) }; let counterparty_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis; let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis; @@ -1577,8 +1563,8 @@ impl ChannelContext { // dependency. // This complicates the computation around dust-values, up to the one-htlc-value. let mut real_dust_limit_timeout_sat = context.holder_dust_limit_satoshis; - if !context.opt_anchors() { - real_dust_limit_timeout_sat += context.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000; + if !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + real_dust_limit_timeout_sat += context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.get_channel_type()) / 1000; } let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered); @@ -1603,8 +1589,8 @@ impl ChannelContext { // 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 = context.counterparty_dust_limit_satoshis; - if !context.opt_anchors() { - real_dust_limit_success_sat += context.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000; + if !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + real_dust_limit_success_sat += context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) / 1000; } let htlc_above_dust = HTLCCandidate::new(real_dust_limit_success_sat * 1000, HTLCInitiator::LocalOffered); @@ -1630,12 +1616,12 @@ impl ChannelContext { 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 context.opt_anchors() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { (context.counterparty_dust_limit_satoshis, context.holder_dust_limit_satoshis) } else { let dust_buffer_feerate = context.get_dust_buffer_feerate(None) as u64; - (context.counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight(false) / 1000, - context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000) + (context.counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000, + context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000) }; let on_counterparty_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat; if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > context.get_max_dust_htlc_exposure_msat() as i64 { @@ -1699,11 +1685,11 @@ impl ChannelContext { let context = &self; assert!(context.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.opt_anchors() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { (0, 0) } else { - (context.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000, - context.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000) + (context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) / 1000, + context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.get_channel_type()) / 1000) }; let real_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis; let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis; @@ -1762,12 +1748,12 @@ impl ChannelContext { } let num_htlcs = included_htlcs + addl_htlcs; - let res = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs, context.opt_anchors()); + let res = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs, &context.channel_type); #[cfg(any(test, fuzzing))] { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, context.opt_anchors()); + fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type); } let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len() + context.holding_cell_htlc_updates.len(); @@ -1803,11 +1789,11 @@ impl ChannelContext { let context = &self; assert!(!context.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.opt_anchors() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { (0, 0) } else { - (context.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000, - context.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000) + (context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) / 1000, + context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.get_channel_type()) / 1000) }; let real_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis; let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis; @@ -1853,12 +1839,12 @@ impl ChannelContext { } let num_htlcs = included_htlcs + addl_htlcs; - let res = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs, context.opt_anchors()); + let res = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs, &context.channel_type); #[cfg(any(test, fuzzing))] { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, context.opt_anchors()); + fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type); } let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len(); let commitment_tx_info = CommitmentTxInfoCached { @@ -1980,16 +1966,16 @@ pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channe // Get the fee cost in SATS of a commitment tx with a given number of HTLC outputs. // Note that num_htlcs should not include dust HTLCs. #[inline] -fn commit_tx_fee_sat(feerate_per_kw: u32, num_htlcs: usize, opt_anchors: bool) -> u64 { - feerate_per_kw as u64 * (commitment_tx_base_weight(opt_anchors) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 +fn commit_tx_fee_sat(feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 { + feerate_per_kw as u64 * (commitment_tx_base_weight(channel_type_features) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 } // Get the fee cost in MSATS of a commitment tx with a given number of HTLC outputs. // Note that num_htlcs should not include dust HTLCs. -fn commit_tx_fee_msat(feerate_per_kw: u32, num_htlcs: usize, opt_anchors: bool) -> u64 { +fn commit_tx_fee_msat(feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 { // Note that we need to divide before multiplying to round properly, // since the lowest denomination of bitcoin on-chain is the satoshi. - (commitment_tx_base_weight(opt_anchors) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) * feerate_per_kw as u64 / 1000 * 1000 + (commitment_tx_base_weight(channel_type_features) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) * feerate_per_kw as u64 / 1000 * 1000 } // TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking @@ -2264,7 +2250,7 @@ impl Channel { } pub fn get_update_fulfill_htlc_and_commit(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger { - let release_cs_monitor = self.context.pending_monitor_updates.iter().all(|upd| !upd.blocked); + let release_cs_monitor = self.context.blocked_monitor_updates.is_empty(); match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) { UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => { // Even if we aren't supposed to let new monitor updates with commitment state @@ -2272,43 +2258,30 @@ impl Channel { // matter what. Sadly, to push a new monitor update which flies before others // already queued, we have to insert it into the pending queue and update the // update_ids of all the following monitors. - let unblocked_update_pos = if release_cs_monitor && msg.is_some() { + if release_cs_monitor && msg.is_some() { let mut additional_update = self.build_commitment_no_status_check(logger); // build_commitment_no_status_check may bump latest_monitor_id but we want them // to be strictly increasing by one, so decrement it here. self.context.latest_monitor_update_id = monitor_update.update_id; monitor_update.updates.append(&mut additional_update.updates); - self.context.pending_monitor_updates.push(PendingChannelMonitorUpdate { - update: monitor_update, blocked: false, - }); - self.context.pending_monitor_updates.len() - 1 } else { - let insert_pos = self.context.pending_monitor_updates.iter().position(|upd| upd.blocked) - .unwrap_or(self.context.pending_monitor_updates.len()); - let new_mon_id = self.context.pending_monitor_updates.get(insert_pos) + let new_mon_id = self.context.blocked_monitor_updates.get(0) .map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id); monitor_update.update_id = new_mon_id; - self.context.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate { - update: monitor_update, blocked: false, - }); - for held_update in self.context.pending_monitor_updates.iter_mut().skip(insert_pos + 1) { + for held_update in self.context.blocked_monitor_updates.iter_mut() { held_update.update.update_id += 1; } if msg.is_some() { debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set"); let update = self.build_commitment_no_status_check(logger); - self.context.pending_monitor_updates.push(PendingChannelMonitorUpdate { - update, blocked: true, + self.context.blocked_monitor_updates.push(PendingChannelMonitorUpdate { + update, }); } - insert_pos - }; - self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new()); - UpdateFulfillCommitFetch::NewClaim { - monitor_update: self.context.pending_monitor_updates.get(unblocked_update_pos) - .expect("We just pushed the monitor update").update.clone(), - htlc_value_msat, } + + self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new()); + UpdateFulfillCommitFetch::NewClaim { monitor_update, htlc_value_msat, } }, UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {}, } @@ -2633,12 +2606,12 @@ impl Channel { } } - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.opt_anchors() { + let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { (0, 0) } else { let dust_buffer_feerate = self.context.get_dust_buffer_feerate(None) as u64; - (dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000, - dust_buffer_feerate * htlc_success_tx_weight(false) / 1000) + (dust_buffer_feerate * htlc_timeout_tx_weight(self.context.get_channel_type()) / 1000, + dust_buffer_feerate * htlc_success_tx_weight(self.context.get_channel_type()) / 1000) }; let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis; if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats { @@ -2886,11 +2859,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.context.get_counterparty_selected_contest_delay().unwrap(), &htlc, self.context.opt_anchors(), - false, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + self.context.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.context.channel_type, + &keys.broadcaster_delayed_payment_key, &keys.revocation_key); - 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_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys); + let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { 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()), @@ -3349,8 +3322,7 @@ impl Channel { } match self.free_holding_cell_htlcs(logger) { - (Some(_), htlcs_to_fail) => { - let mut additional_update = self.context.pending_monitor_updates.pop().unwrap().update; + (Some(mut additional_update), htlcs_to_fail) => { // free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be // strictly increasing by one, so decrement it here. self.context.latest_monitor_update_id = monitor_update.update_id; @@ -3412,7 +3384,7 @@ impl Channel { let outbound_stats = self.context.get_outbound_pending_htlc_stats(Some(feerate_per_kw)); let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger); - let buffer_fee_msat = 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 buffer_fee_msat = 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.get_channel_type()) * 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? @@ -3566,12 +3538,6 @@ impl Channel { { assert_eq!(self.context.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32); self.context.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32); - let mut found_blocked = false; - self.context.pending_monitor_updates.retain(|upd| { - if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); } - if upd.blocked { found_blocked = true; } - upd.blocked - }); // If we're past (or at) the FundingSent stage on an outbound channel, try to // (re-)broadcast the funding transaction as we may have declined to broadcast it when we @@ -4431,56 +4397,37 @@ impl Channel { (self.context.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0 } - pub fn get_latest_complete_monitor_update_id(&self) -> u64 { - 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 + /// Gets the latest [`ChannelMonitorUpdate`] ID which has been released and is in-flight. + pub fn get_latest_unblocked_monitor_update_id(&self) -> u64 { + if self.context.blocked_monitor_updates.is_empty() { return self.context.get_latest_monitor_update_id(); } + self.context.blocked_monitor_updates[0].update.update_id - 1 } /// Returns the next blocked monitor update, if one exists, and a bool which indicates a /// further blocked monitor update exists after the next. pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(ChannelMonitorUpdate, bool)> { - for i in 0..self.context.pending_monitor_updates.len() { - if self.context.pending_monitor_updates[i].blocked { - self.context.pending_monitor_updates[i].blocked = false; - return Some((self.context.pending_monitor_updates[i].update.clone(), - self.context.pending_monitor_updates.len() > i + 1)); - } - } - None + if self.context.blocked_monitor_updates.is_empty() { return None; } + Some((self.context.blocked_monitor_updates.remove(0).update, + !self.context.blocked_monitor_updates.is_empty())) } /// Pushes a new monitor update into our monitor update queue, returning it if it should be /// immediately given to the user for persisting or `None` if it should be held as blocked. fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> Option { - let release_monitor = self.context.pending_monitor_updates.iter().all(|upd| !upd.blocked); - self.context.pending_monitor_updates.push(PendingChannelMonitorUpdate { - update, blocked: !release_monitor, - }); - if release_monitor { self.context.pending_monitor_updates.last().map(|upd| upd.update.clone()) } else { None } - } - - pub fn no_monitor_updates_pending(&self) -> bool { - self.context.pending_monitor_updates.is_empty() - } - - pub fn complete_all_mon_updates_through(&mut self, update_id: u64) { - self.context.pending_monitor_updates.retain(|upd| { - if upd.update.update_id <= update_id { - assert!(!upd.blocked, "Completed update must have flown"); - false - } else { true } - }); - } - - pub fn complete_one_mon_update(&mut self, update_id: u64) { - self.context.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id); + let release_monitor = self.context.blocked_monitor_updates.is_empty(); + if !release_monitor { + self.context.blocked_monitor_updates.push(PendingChannelMonitorUpdate { + update, + }); + None + } else { + Some(update) + } } - /// Returns an iterator over all unblocked monitor updates which have not yet completed. - pub fn uncompleted_unblocked_mon_updates(&self) -> impl Iterator { - self.context.pending_monitor_updates.iter() - .filter_map(|upd| if upd.blocked { None } else { Some(&upd.update) }) + pub fn blocked_monitor_updates_pending(&self) -> usize { + self.context.blocked_monitor_updates.len() } /// Returns true if the channel is awaiting the persistence of the initial ChannelMonitor. @@ -5228,7 +5175,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 = commit_tx_fee_msat(self.context.feerate_per_kw, commitment_stats.num_nondust_htlcs, self.context.opt_anchors()); + let actual_fee = commit_tx_fee_msat(self.context.feerate_per_kw, commitment_stats.num_nondust_htlcs, self.context.get_channel_type()); assert_eq!(actual_fee, info.fee); } } @@ -5268,8 +5215,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.context.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)), + encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.context.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)), + encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &counterparty_keys)), log_bytes!(counterparty_keys.broadcaster_htlc_key.serialize()), log_bytes!(htlc_sig.serialize_compact()[..]), log_bytes!(self.context.channel_id())); } @@ -5483,7 +5430,7 @@ impl OutboundV1Channel { let feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal); let value_to_self_msat = channel_value_satoshis * 1000 - push_msat; - let commitment_tx_fee = commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, channel_type.requires_anchors_zero_fee_htlc_tx()); + let commitment_tx_fee = commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type); if value_to_self_msat < commitment_tx_fee { return Err(APIError::APIMisuseError{ err: format!("Funding amount ({}) can't even pay fee for initial commitment transaction fee of {}.", value_to_self_msat / 1000, commitment_tx_fee / 1000) }); } @@ -5598,8 +5545,7 @@ impl OutboundV1Channel { is_outbound_from_holder: true, counterparty_parameters: None, funding_outpoint: None, - opt_anchors: if channel_type.requires_anchors_zero_fee_htlc_tx() { Some(()) } else { None }, - opt_non_zero_fee_anchors: None + channel_type_features: channel_type.clone() }, funding_transaction: None, @@ -5636,7 +5582,7 @@ impl OutboundV1Channel { channel_type, channel_keys_id, - pending_monitor_updates: Vec::new(), + blocked_monitor_updates: Vec::new(), } }) } @@ -5721,12 +5667,9 @@ impl OutboundV1Channel { // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we // set it now. If they don't understand it, we'll fall back to our default of // `only_static_remotekey`. - #[cfg(anchors)] - { // Attributes are not allowed on if expressions on our current MSRV of 1.41. - if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx && - their_features.supports_anchors_zero_fee_htlc_tx() { - ret.set_anchors_zero_fee_htlc_tx_required(); - } + if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx && + their_features.supports_anchors_zero_fee_htlc_tx() { + ret.set_anchors_zero_fee_htlc_tx_required(); } ret @@ -5752,13 +5695,13 @@ impl OutboundV1Channel { // whatever reason. if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { self.context.channel_type.clear_anchors_zero_fee_htlc_tx(); - assert!(self.context.channel_transaction_parameters.opt_non_zero_fee_anchors.is_none()); - self.context.channel_transaction_parameters.opt_anchors = None; + assert!(!self.context.channel_transaction_parameters.channel_type_features.supports_anchors_nonzero_fee_htlc_tx()); } else if self.context.channel_type.supports_scid_privacy() { self.context.channel_type.clear_scid_privacy(); } else { self.context.channel_type = ChannelTypeFeatures::only_static_remote_key(); } + self.context.channel_transaction_parameters.channel_type_features = self.context.channel_type.clone(); Ok(self.get_open_channel(chain_hash)) } @@ -5877,7 +5820,8 @@ impl OutboundV1Channel { if channel_type != ChannelTypeFeatures::only_static_remote_key() { return Err(ChannelError::Close("Only static_remote_key is supported for non-negotiated channel types".to_owned())); } - self.context.channel_type = channel_type; + self.context.channel_type = channel_type.clone(); + self.context.channel_transaction_parameters.channel_type_features = channel_type; } let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { @@ -5984,7 +5928,6 @@ impl InboundV1Channel { } channel_type }; - let opt_anchors = channel_type.supports_anchors_zero_fee_htlc_tx(); let channel_keys_id = signer_provider.generate_channel_keys_id(true, msg.funding_satoshis, user_id); let holder_signer = signer_provider.derive_channel_signer(msg.funding_satoshis, channel_keys_id); @@ -6085,7 +6028,7 @@ impl InboundV1Channel { // check if the funder's amount for the initial commitment tx is sufficient // for full fee payment plus a few HTLCs to ensure the channel will be useful. let funders_amount_msat = msg.funding_satoshis * 1000 - msg.push_msat; - let commitment_tx_fee = commit_tx_fee_msat(msg.feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT, opt_anchors) / 1000; + let commitment_tx_fee = commit_tx_fee_msat(msg.feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) / 1000; if funders_amount_msat / 1000 < commitment_tx_fee { return Err(ChannelError::Close(format!("Funding amount ({} sats) can't even pay fee for initial commitment transaction fee of {} sats.", funders_amount_msat / 1000, commitment_tx_fee))); } @@ -6228,8 +6171,7 @@ impl InboundV1Channel { pubkeys: counterparty_pubkeys, }), funding_outpoint: None, - opt_anchors: if opt_anchors { Some(()) } else { None }, - opt_non_zero_fee_anchors: None + channel_type_features: channel_type.clone() }, funding_transaction: None, @@ -6266,7 +6208,7 @@ impl InboundV1Channel { channel_type, channel_keys_id, - pending_monitor_updates: Vec::new(), + blocked_monitor_updates: Vec::new(), } }; @@ -6852,7 +6794,7 @@ impl Writeable for Channel { (28, holder_max_accepted_htlcs, option), (29, self.context.temporary_channel_id, option), (31, channel_pending_event_emitted, option), - (33, self.context.pending_monitor_updates, vec_type), + (33, self.context.blocked_monitor_updates, vec_type), (35, pending_outbound_skimmed_fees, optional_vec), (37, holding_cell_skimmed_fees, optional_vec), }); @@ -7076,7 +7018,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch _ => return Err(DecodeError::InvalidValue), }; - let channel_parameters: ChannelTransactionParameters = Readable::read(reader)?; + let mut channel_parameters: ChannelTransactionParameters = Readable::read(reader)?; let funding_transaction = Readable::read(reader)?; let counterparty_cur_commitment_point = Readable::read(reader)?; @@ -7133,7 +7075,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch let mut temporary_channel_id: Option<[u8; 32]> = None; let mut holder_max_accepted_htlcs: Option = None; - let mut pending_monitor_updates = Some(Vec::new()); + let mut blocked_monitor_updates = Some(Vec::new()); let mut pending_outbound_skimmed_fees_opt: Option>> = None; let mut holding_cell_skimmed_fees_opt: Option>> = None; @@ -7160,7 +7102,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch (28, holder_max_accepted_htlcs, option), (29, temporary_channel_id, option), (31, channel_pending_event_emitted, option), - (33, pending_monitor_updates, vec_type), + (33, blocked_monitor_updates, vec_type), (35, pending_outbound_skimmed_fees_opt, optional_vec), (37, holding_cell_skimmed_fees_opt, optional_vec), }); @@ -7207,6 +7149,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch return Err(DecodeError::UnknownRequiredFeature); } + // ChannelTransactionParameters may have had an empty features set upon deserialization. + // To account for that, we're proactively setting/overriding the field here. + channel_parameters.channel_type_features = chan_features.clone(); + let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes()); @@ -7353,7 +7299,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch channel_type: channel_type.unwrap(), channel_keys_id, - pending_monitor_updates: pending_monitor_updates.unwrap(), + blocked_monitor_updates: blocked_monitor_updates.unwrap(), } }) } @@ -7370,7 +7316,6 @@ mod tests { use hex; use crate::ln::PaymentHash; use crate::ln::channelmanager::{self, HTLCSource, PaymentId}; - #[cfg(anchors)] use crate::ln::channel::InitFeatures; use crate::ln::channel::{Channel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat}; use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS}; @@ -7460,7 +7405,7 @@ mod tests { } } - #[cfg(not(feature = "grind_signatures"))] + #[cfg(all(feature = "_test_vectors", not(feature = "grind_signatures")))] fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap()) } @@ -7586,13 +7531,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.context.next_local_commit_tx_fee_msat(htlc_candidate, None); - let local_commit_fee_0_htlcs = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.context.opt_anchors()); + let local_commit_fee_0_htlcs = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.context.get_channel_type()); 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 = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.context.opt_anchors()); + let remote_commit_fee_3_htlcs = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.context.get_channel_type()); let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered); let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs); @@ -7614,18 +7559,18 @@ mod tests { let config = UserConfig::default(); let mut chan = OutboundV1Channel::::new(&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 = commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.context.opt_anchors()); - let commitment_tx_fee_1_htlc = commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.context.opt_anchors()); + let commitment_tx_fee_0_htlcs = commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.context.get_channel_type()); + let commitment_tx_fee_1_htlc = commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.context.get_channel_type()); // 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.context.opt_anchors()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000; + let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.get_channel_type()) / 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.context.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.context.opt_anchors()) / 1000) + chan.context.holder_dust_limit_satoshis - 1) * 1000; + let dust_htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.get_channel_type()) / 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.context.next_local_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs); @@ -7633,13 +7578,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.context.opt_anchors()) / 1000) + chan.context.counterparty_dust_limit_satoshis + 1) * 1000; + let dust_htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.get_channel_type()) / 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.context.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.context.opt_anchors()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000; + let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.get_channel_type()) / 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.context.next_remote_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc); @@ -7987,15 +7932,15 @@ mod tests { macro_rules! test_commitment { ( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $($remain:tt)* ) => { - chan.context.channel_transaction_parameters.opt_anchors = None; - test_commitment_common!($counterparty_sig_hex, $sig_hex, $tx_hex, false, $($remain)*); + chan.context.channel_transaction_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key(); + test_commitment_common!($counterparty_sig_hex, $sig_hex, $tx_hex, &ChannelTypeFeatures::only_static_remote_key(), $($remain)*); }; } macro_rules! test_commitment_with_anchors { ( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $($remain:tt)* ) => { - chan.context.channel_transaction_parameters.opt_anchors = Some(()); - test_commitment_common!($counterparty_sig_hex, $sig_hex, $tx_hex, true, $($remain)*); + chan.context.channel_transaction_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + test_commitment_common!($counterparty_sig_hex, $sig_hex, $tx_hex, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), $($remain)*); }; } @@ -8054,9 +7999,9 @@ mod tests { let ref htlc = htlcs[$htlc_idx]; let htlc_tx = chan_utils::build_htlc_transaction(&unsigned_tx.txid, chan.context.feerate_per_kw, chan.context.get_counterparty_selected_contest_delay().unwrap(), - &htlc, $opt_anchors, false, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + &htlc, $opt_anchors, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, $opt_anchors, &keys); - let htlc_sighashtype = if $opt_anchors { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; + let htlc_sighashtype = if $opt_anchors.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; let htlc_sighash = Message::from_slice(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]).unwrap(); assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key).is_ok(), "verify counterparty htlc sig"); @@ -8073,7 +8018,7 @@ mod tests { } let htlc_sig = htlc_sig_iter.next().unwrap(); - let num_anchors = if $opt_anchors { 2 } else { 0 }; + let num_anchors = if $opt_anchors.supports_anchors_zero_fee_htlc_tx() { 2 } else { 0 }; assert_eq!((htlc_sig.0).0.transaction_output_index, Some($htlc_idx + num_anchors), "output index"); let signature = Signature::from_der(&hex::decode($htlc_sig_hex).unwrap()[..]).unwrap(); @@ -8394,6 +8339,8 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 2185; chan.context.holder_dust_limit_satoshis = 2001; + let cached_channel_type = chan.context.channel_type; + chan.context.channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3044022040f63a16148cf35c8d3d41827f5ae7f7c3746885bb64d4d1b895892a83812b3e02202fcf95c2bf02c466163b3fa3ced6a24926fbb4035095a96842ef516e86ba54c0", "3045022100cd8479cfe1edb1e5a1d487391e0451a469c7171e51e680183f19eb4321f20e9b02204eab7d5a6384b1b08e03baa6e4d9748dfd2b5ab2bae7e39604a0d0055bbffdd5", @@ -8414,6 +8361,7 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 3702; chan.context.holder_dust_limit_satoshis = 546; + chan.context.channel_type = cached_channel_type.clone(); test_commitment!("304502210092a587aeb777f869e7ff0d7898ea619ee26a3dacd1f3672b945eea600be431100220077ee9eae3528d15251f2a52b607b189820e57a6ccfac8d1af502b132ee40169", "3045022100e5efb73c32d32da2d79702299b6317de6fb24a60476e3855926d78484dd1b3c802203557cb66a42c944ef06e00bcc4da35a5bcb2f185aab0f8e403e519e1d66aaf75", @@ -8448,6 +8396,7 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 3687; chan.context.holder_dust_limit_satoshis = 3001; + chan.context.channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3045022100ad6c71569856b2d7ff42e838b4abe74a713426b37f22fa667a195a4c88908c6902202b37272b02a42dc6d9f4f82cab3eaf84ac882d9ed762859e1e75455c2c228377", "3045022100c970799bcb33f43179eb43b3378a0a61991cf2923f69b36ef12548c3df0e6d500220413dc27d2e39ee583093adfcb7799be680141738babb31cc7b0669a777a31f5d", @@ -8463,6 +8412,7 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 4914; chan.context.holder_dust_limit_satoshis = 546; + chan.context.channel_type = cached_channel_type.clone(); test_commitment!("3045022100b4b16d5f8cc9fc4c1aff48831e832a0d8990e133978a66e302c133550954a44d022073573ce127e2200d316f6b612803a5c0c97b8d20e1e44dbe2ac0dd2fb8c95244", "3045022100d72638bc6308b88bb6d45861aae83e5b9ff6e10986546e13bce769c70036e2620220320be7c6d66d22f30b9fcd52af66531505b1310ca3b848c19285b38d8a1a8c19", @@ -8487,6 +8437,7 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 4894; chan.context.holder_dust_limit_satoshis = 4001; + chan.context.channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3045022100e784a66b1588575801e237d35e510fd92a81ae3a4a2a1b90c031ad803d07b3f3022021bc5f16501f167607d63b681442da193eb0a76b4b7fd25c2ed4f8b28fd35b95", "30450221009f16ac85d232e4eddb3fcd750a68ebf0b58e3356eaada45d3513ede7e817bf4c02207c2b043b4e5f971261975406cb955219fa56bffe5d834a833694b5abc1ce4cfd", @@ -8496,6 +8447,7 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 9651180; chan.context.holder_dust_limit_satoshis = 546; + chan.context.channel_type = cached_channel_type.clone(); test_commitment!("304402200a8544eba1d216f5c5e530597665fa9bec56943c0f66d98fc3d028df52d84f7002201e45fa5c6bc3a506cc2553e7d1c0043a9811313fc39c954692c0d47cfce2bbd3", "3045022100e11b638c05c650c2f63a421d36ef8756c5ce82f2184278643520311cdf50aa200220259565fb9c8e4a87ccaf17f27a3b9ca4f20625754a0920d9c6c239d8156a11de", @@ -8513,6 +8465,7 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 6216010; chan.context.holder_dust_limit_satoshis = 4001; + chan.context.channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("30450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf", "30450221009ad80792e3038fe6968d12ff23e6888a565c3ddd065037f357445f01675d63f3022018384915e5f1f4ae157e15debf4f49b61c8d9d2b073c7d6f97c4a68caa3ed4c1", @@ -8522,6 +8475,7 @@ mod tests { chan.context.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 9651936; chan.context.holder_dust_limit_satoshis = 546; + chan.context.channel_type = cached_channel_type; test_commitment!("304402202ade0142008309eb376736575ad58d03e5b115499709c6db0b46e36ff394b492022037b63d78d66404d6504d4c4ac13be346f3d1802928a6d3ad95a6a944227161a2", "304402207e8d51e0c570a5868a78414f4e0cbfaed1106b171b9581542c30718ee4eb95ba02203af84194c97adf98898c9afe2f2ed4a7f8dba05a2dfab28ac9d9c604aa49a379", @@ -8588,6 +8542,7 @@ mod tests { "020000000001014bdccf28653066a2c554cafeffdfe1e678e64a69b056684deb0c4fba909423ec02000000000000000001e1120000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220471c9f3ad92e49b13b7b8059f43ecf8f7887b0dccbb9fdb54bfe23d62a8ae332022024bd22fae0740e86a44228c35330da9526fd7306dffb2b9dc362d5e78abef7cc0147304402207157f452f2506d73c315192311893800cfb3cc235cc1185b1cfcc136b55230db022014be242dbc6c5da141fec4034e7f387f74d6ff1899453d72ba957467540e1ecb01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6868fa010000" } } ); + chan.context.channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3044022027b38dfb654c34032ffb70bb43022981652fce923cbbe3cbe7394e2ade8b34230220584195b78da6e25c2e8da6b4308d9db25b65b64975db9266163ef592abb7c725", "3045022100b4014970d9d7962853f3f85196144671d7d5d87426250f0a5fdaf9a55292e92502205360910c9abb397467e19dbd63d081deb4a3240903114c98cec0a23591b79b76", "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5e881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994aad9c6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100b4014970d9d7962853f3f85196144671d7d5d87426250f0a5fdaf9a55292e92502205360910c9abb397467e19dbd63d081deb4a3240903114c98cec0a23591b79b7601473044022027b38dfb654c34032ffb70bb43022981652fce923cbbe3cbe7394e2ade8b34230220584195b78da6e25c2e8da6b4308d9db25b65b64975db9266163ef592abb7c72501475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", { @@ -8684,7 +8639,6 @@ mod tests { assert!(res.is_ok()); } - #[cfg(anchors)] #[test] fn test_supports_anchors_zero_htlc_tx_fee() { // Tests that if both sides support and negotiate `anchors_zero_fee_htlc_tx`, it is the @@ -8730,7 +8684,6 @@ mod tests { assert_eq!(channel_b.context.channel_type, expected_channel_type); } - #[cfg(anchors)] #[test] fn test_rejects_implicit_simple_anchors() { // Tests that if `option_anchors` is being negotiated implicitly through the intersection of @@ -8771,7 +8724,6 @@ mod tests { assert!(channel_b.is_err()); } - #[cfg(anchors)] #[test] fn test_rejects_simple_anchors_channel_type() { // Tests that if `option_anchors` is being negotiated through the `channel_type` feature, @@ -8793,8 +8745,8 @@ mod tests { let simple_anchors_raw_features = static_remote_key_required | simple_anchors_required; let simple_anchors_init = InitFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec()); let simple_anchors_channel_type = ChannelTypeFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec()); - assert!(simple_anchors_init.requires_unknown_bits()); - assert!(simple_anchors_channel_type.requires_unknown_bits()); + assert!(!simple_anchors_init.requires_unknown_bits()); + assert!(!simple_anchors_channel_type.requires_unknown_bits()); // First, we'll try to open a channel between A and B where A requests a channel type for // the original `option_anchors` feature (non zero fee htlc tx). This should be rejected by