From 609340dc73531aeeecf29024eec953f05e23ff93 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:45:55 +0100 Subject: [PATCH 1/2] Clone for ChannelContext --- lightning/src/ln/channel.rs | 174 ++++++++++++++++++++++++++++- lightning/src/ln/channelmanager.rs | 1 + 2 files changed, 170 insertions(+), 5 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index e76cc0deb1d..c9c242b3df8 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -112,6 +112,7 @@ enum FeeUpdateState { Outbound, } +#[derive(Clone)] enum InboundHTLCRemovalReason { FailRelay(msgs::OnionErrorPacket), FailMalformed(([u8; 32], u16)), @@ -146,6 +147,7 @@ impl_writeable_tlv_based_enum!(InboundHTLCResolution, }, ); +#[derive(Clone)] enum InboundHTLCState { /// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an /// update_add_htlc message for this HTLC. @@ -220,6 +222,7 @@ impl From<&InboundHTLCState> for Option { } } +#[derive(Clone)] struct InboundHTLCOutput { htlc_id: u64, amount_msat: u64, @@ -228,7 +231,8 @@ struct InboundHTLCOutput { state: InboundHTLCState, } -#[cfg_attr(test, derive(Clone, Debug, PartialEq))] +#[derive(Clone)] +#[cfg_attr(test, derive(Debug, PartialEq))] enum OutboundHTLCState { /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we /// created it we would have put it in the holding cell instead). When they next revoke_and_ack @@ -310,7 +314,8 @@ impl<'a> Into> for &'a OutboundHTLCOutcome { } } -#[cfg_attr(test, derive(Clone, Debug, PartialEq))] +#[derive(Clone)] +#[cfg_attr(test, derive(Debug, PartialEq))] struct OutboundHTLCOutput { htlc_id: u64, amount_msat: u64, @@ -323,7 +328,8 @@ struct OutboundHTLCOutput { } /// See AwaitingRemoteRevoke ChannelState for more info -#[cfg_attr(test, derive(Clone, Debug, PartialEq))] +#[derive(Clone)] +#[cfg_attr(test, derive(Debug, PartialEq))] enum HTLCUpdateAwaitingACK { AddHTLC { // TODO: Time out if we're getting close to cltv_expiry // always outbound @@ -801,7 +807,7 @@ pub(super) enum ChannelUpdateStatus { } /// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here. -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub enum AnnouncementSigsState { /// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since /// we sent the last `AnnouncementSignatures`. @@ -1126,6 +1132,7 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60; /// Number of blocks needed for an output from a coinbase transaction to be spendable. pub(crate) const COINBASE_MATURITY: u32 = 100; +#[derive(Clone)] struct PendingChannelMonitorUpdate { update: ChannelMonitorUpdate, } @@ -4413,6 +4420,111 @@ impl ChannelContext where SP::Target: SignerProvider { self.channel_transaction_parameters = channel_transaction_parameters; self.get_initial_counterparty_commitment_signature(logger) } + + /// Clone, each field, with a few exceptions, notably the channel signer, and + /// a few non-cloneable fields (such as Secp256k1 context) + #[allow(unused)] + fn clone(&self, holder_signer: ::EcdsaSigner) -> Self { + Self { + config: self.config, + prev_config: self.prev_config, + inbound_handshake_limits_override: self.inbound_handshake_limits_override, + user_id: self.user_id, + channel_id: self.channel_id, + temporary_channel_id: self.temporary_channel_id, + channel_state: self.channel_state, + announcement_sigs_state: self.announcement_sigs_state.clone(), + // Create new Secp256k context + secp_ctx: Secp256k1::new(), + channel_value_satoshis: self.channel_value_satoshis, + latest_monitor_update_id: self.latest_monitor_update_id, + // Use provided channel signer + holder_signer: ChannelSignerType::Ecdsa(holder_signer), + shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(), + destination_script: self.destination_script.clone(), + cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number, + value_to_self_msat: self.value_to_self_msat, + pending_inbound_htlcs: self.pending_inbound_htlcs.clone(), + pending_outbound_htlcs: self.pending_outbound_htlcs.clone(), + holding_cell_htlc_updates: self.holding_cell_htlc_updates.clone(), + resend_order: self.resend_order.clone(), + monitor_pending_channel_ready: self.monitor_pending_channel_ready, + monitor_pending_revoke_and_ack: self.monitor_pending_revoke_and_ack, + monitor_pending_commitment_signed: self.monitor_pending_commitment_signed, + monitor_pending_forwards: self.monitor_pending_forwards.clone(), + monitor_pending_failures: self.monitor_pending_failures.clone(), + monitor_pending_finalized_fulfills: self.monitor_pending_finalized_fulfills.clone(), + monitor_pending_update_adds: self.monitor_pending_update_adds.clone(), + monitor_pending_tx_signatures: self.monitor_pending_tx_signatures.clone(), + signer_pending_revoke_and_ack: self.signer_pending_revoke_and_ack, + signer_pending_commitment_update: self.signer_pending_commitment_update, + signer_pending_funding: self.signer_pending_funding, + signer_pending_closing: self.signer_pending_closing, + signer_pending_channel_ready: self.signer_pending_channel_ready, + pending_update_fee: self.pending_update_fee, + holding_cell_update_fee: self.holding_cell_update_fee, + next_holder_htlc_id: self.next_holder_htlc_id, + next_counterparty_htlc_id: self.next_counterparty_htlc_id, + feerate_per_kw: self.feerate_per_kw, + update_time_counter: self.update_time_counter, + // Create new mutex with copied values + #[cfg(debug_assertions)] + holder_max_commitment_tx_output: Mutex::new(*self.holder_max_commitment_tx_output.lock().unwrap()), + #[cfg(debug_assertions)] + counterparty_max_commitment_tx_output: Mutex::new(*self.counterparty_max_commitment_tx_output.lock().unwrap()), + last_sent_closing_fee: self.last_sent_closing_fee.clone(), + last_received_closing_sig: self.last_received_closing_sig, + target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw, + pending_counterparty_closing_signed: self.pending_counterparty_closing_signed.clone(), + closing_fee_limits: self.closing_fee_limits, + expecting_peer_commitment_signed: self.expecting_peer_commitment_signed, + funding_tx_confirmed_in: self.funding_tx_confirmed_in, + funding_tx_confirmation_height: self.funding_tx_confirmation_height, + short_channel_id: self.short_channel_id, + channel_creation_height: self.channel_creation_height, + counterparty_dust_limit_satoshis: self.counterparty_dust_limit_satoshis, + holder_dust_limit_satoshis: self.holder_dust_limit_satoshis, + counterparty_max_htlc_value_in_flight_msat: self.counterparty_max_htlc_value_in_flight_msat, + holder_max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat, + counterparty_selected_channel_reserve_satoshis: self.counterparty_selected_channel_reserve_satoshis, + holder_selected_channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis, + counterparty_htlc_minimum_msat: self.counterparty_htlc_minimum_msat, + holder_htlc_minimum_msat: self.holder_htlc_minimum_msat, + counterparty_max_accepted_htlcs: self.counterparty_max_accepted_htlcs, + holder_max_accepted_htlcs: self.holder_max_accepted_htlcs, + minimum_depth: self.minimum_depth, + counterparty_forwarding_info: self.counterparty_forwarding_info.clone(), + channel_transaction_parameters: self.channel_transaction_parameters.clone(), + funding_transaction: self.funding_transaction.clone(), + is_manual_broadcast: self.is_manual_broadcast, + is_batch_funding: self.is_batch_funding, + counterparty_cur_commitment_point: self.counterparty_cur_commitment_point, + counterparty_prev_commitment_point: self.counterparty_prev_commitment_point, + counterparty_node_id: self.counterparty_node_id, + counterparty_shutdown_scriptpubkey: self.counterparty_shutdown_scriptpubkey.clone(), + commitment_secrets: self.commitment_secrets.clone(), + channel_update_status: self.channel_update_status, + closing_signed_in_flight: self.closing_signed_in_flight, + announcement_sigs: self.announcement_sigs, + // Create new mutex with copied values + #[cfg(any(test, fuzzing))] + next_local_commitment_tx_fee_info_cached: Mutex::new(self.next_local_commitment_tx_fee_info_cached.lock().unwrap().clone()), + #[cfg(any(test, fuzzing))] + next_remote_commitment_tx_fee_info_cached: Mutex::new(self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().clone()), + workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(), + sent_message_awaiting_response: self.sent_message_awaiting_response, + channel_type: self.channel_type.clone(), + latest_inbound_scid_alias: self.latest_inbound_scid_alias, + outbound_scid_alias: self.outbound_scid_alias, + channel_pending_event_emitted: self.channel_pending_event_emitted, + funding_tx_broadcast_safe_event_emitted: self.funding_tx_broadcast_safe_event_emitted, + channel_ready_event_emitted: self.channel_ready_event_emitted, + local_initiated_shutdown: self.local_initiated_shutdown.clone(), + channel_keys_id: self.channel_keys_id, + blocked_monitor_updates: self.blocked_monitor_updates.clone(), + next_funding_txid: self.next_funding_txid.clone(), + } + } } // Internal utility functions for channels @@ -4540,6 +4652,7 @@ pub(super) struct FundedChannel where SP::Target: SignerProvider { } #[cfg(any(test, fuzzing))] +#[derive(Clone)] struct CommitmentTxInfoCached { fee: u64, total_pending_htlcs: usize, @@ -10474,7 +10587,7 @@ mod tests { use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint}; use crate::ln::channelmanager::{self, HTLCSource, PaymentId}; use crate::ln::channel::InitFeatures; - use crate::ln::channel::{AwaitingChannelReadyFlags, ChannelState, FundedChannel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat}; + use crate::ln::channel::{AwaitingChannelReadyFlags, ChannelContext, ChannelState, FundedChannel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat}; use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS}; use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; use crate::ln::msgs; @@ -12238,4 +12351,55 @@ mod tests { assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY)); assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some()); } + + #[test] + fn channel_context_clone() { + let fee_estimator = TestFeeEstimator {fee_est: 253 }; + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator); + let seed = [42; 32]; + let network = Network::Testnet; + let keys_provider = test_utils::TestKeysInterface::new(&seed, network); + let secp_ctx = Secp256k1::new(); + let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let config = UserConfig::default(); + + let signer_provider: &TestKeysInterface = &&keys_provider; + let channel_value_satoshis = 10000000; + let user_id = 42; + let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id); + let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); + let logger = test_utils::TestLogger::new(); + let pubkeys = holder_signer.pubkeys().clone(); + + // Create a context + let context = ChannelContext::<&TestKeysInterface>::new_for_outbound_channel( + &bounded_fee_estimator, + &&keys_provider, + &signer_provider, + node_a_node_id, + &channelmanager::provided_init_features(&config), + channel_value_satoshis, + 100000, + user_id, + &config, + 0, + 42, + None, + 100000, + [42; 32], + holder_signer, + pubkeys, + &logger, + ).unwrap(); + + // Clone it + let holder_signer2 = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); + let context_cloned = context.clone(holder_signer2); + + // Compare some fields + assert_eq!(context_cloned.channel_value_satoshis, context.channel_value_satoshis); + assert_eq!(context_cloned.channel_id, context.channel_id); + assert_eq!(context_cloned.funding_tx_broadcast_safe_event_emitted, context.funding_tx_broadcast_safe_event_emitted); + assert_eq!(context_cloned.channel_keys_id, context.channel_keys_id); + } } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index eb5bd89575a..d2031078537 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -49,6 +49,7 @@ use crate::ln::inbound_payment; use crate::ln::types::ChannelId; use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::ln::channel::{self, Channel, ChannelError, ChannelUpdateStatus, FundedChannel, ShutdownResult, UpdateFulfillCommitFetch, OutboundV1Channel, ReconnectionMsg, InboundV1Channel, WithChannelContext}; +#[cfg(dual_funding)] #[cfg(any(dual_funding, splicing))] use crate::ln::channel::PendingV2Channel; use crate::ln::channel_state::ChannelDetails; From 7636b2b176b97d0065efa6e19120f4ec56e220c9 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:46:46 +0100 Subject: [PATCH 2/2] Add Arc to Mutex fields to make them cloneable --- lightning/src/ln/channel.rs | 53 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index c9c242b3df8..77131c09dab 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -69,7 +69,7 @@ use crate::prelude::*; use core::{cmp,mem,fmt}; use core::ops::Deref; #[cfg(any(test, fuzzing, debug_assertions))] -use crate::sync::Mutex; +use crate::sync::{Arc, Mutex}; use crate::sign::type_resolver::ChannelSignerType; use super::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint}; @@ -1673,10 +1673,10 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { #[cfg(debug_assertions)] /// Max to_local and to_remote outputs in a locally-generated commitment transaction - holder_max_commitment_tx_output: Mutex<(u64, u64)>, + holder_max_commitment_tx_output: Arc>, #[cfg(debug_assertions)] /// Max to_local and to_remote outputs in a remote-generated commitment transaction - counterparty_max_commitment_tx_output: Mutex<(u64, u64)>, + counterparty_max_commitment_tx_output: Arc>, // (fee_sats, skip_remote_output, fee_range, holder_sig) last_sent_closing_fee: Option<(u64, bool, ClosingSignedFeeRange, Option)>, @@ -1788,9 +1788,9 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { // be, by comparing the cached values to the fee of the tranaction generated by // `build_commitment_transaction`. #[cfg(any(test, fuzzing))] - next_local_commitment_tx_fee_info_cached: Mutex>, + next_local_commitment_tx_fee_info_cached: Arc>>, #[cfg(any(test, fuzzing))] - next_remote_commitment_tx_fee_info_cached: Mutex>, + next_remote_commitment_tx_fee_info_cached: Arc>>, /// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed /// they will not send a channel_reestablish until the channel locks in. Then, they will send a @@ -2461,9 +2461,9 @@ impl ChannelContext where SP::Target: SignerProvider { #[cfg(debug_assertions)] - holder_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))), + holder_max_commitment_tx_output: Arc::new(Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat)))), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))), + counterparty_max_commitment_tx_output: Arc::new(Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat)))), last_sent_closing_fee: None, last_received_closing_sig: None, @@ -2521,9 +2521,9 @@ impl ChannelContext where SP::Target: SignerProvider { announcement_sigs: None, #[cfg(any(test, fuzzing))] - next_local_commitment_tx_fee_info_cached: Mutex::new(None), + next_local_commitment_tx_fee_info_cached: Arc::new(Mutex::new(None)), #[cfg(any(test, fuzzing))] - next_remote_commitment_tx_fee_info_cached: Mutex::new(None), + next_remote_commitment_tx_fee_info_cached: Arc::new(Mutex::new(None)), workaround_lnd_bug_4006: None, sent_message_awaiting_response: None, @@ -2693,9 +2693,9 @@ impl ChannelContext where SP::Target: SignerProvider { // We'll add our counterparty's `funding_satoshis` to these max commitment output assertions // when we receive `accept_channel2`. #[cfg(debug_assertions)] - holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + holder_max_commitment_tx_output: Arc::new(Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat))), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + counterparty_max_commitment_tx_output: Arc::new(Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat))), last_sent_closing_fee: None, last_received_closing_sig: None, @@ -2751,9 +2751,9 @@ impl ChannelContext where SP::Target: SignerProvider { announcement_sigs: None, #[cfg(any(test, fuzzing))] - next_local_commitment_tx_fee_info_cached: Mutex::new(None), + next_local_commitment_tx_fee_info_cached: Arc::new(Mutex::new(None)), #[cfg(any(test, fuzzing))] - next_remote_commitment_tx_fee_info_cached: Mutex::new(None), + next_remote_commitment_tx_fee_info_cached: Arc::new(Mutex::new(None)), workaround_lnd_bug_4006: None, sent_message_awaiting_response: None, @@ -4421,11 +4421,13 @@ impl ChannelContext where SP::Target: SignerProvider { self.get_initial_counterparty_commitment_signature(logger) } - /// Clone, each field, with a few exceptions, notably the channel signer, and - /// a few non-cloneable fields (such as Secp256k1 context) + /// Clone, each field, with the exception of the channel signer. #[allow(unused)] fn clone(&self, holder_signer: ::EcdsaSigner) -> Self { Self { + // Use provided channel signer + holder_signer: ChannelSignerType::Ecdsa(holder_signer), + config: self.config, prev_config: self.prev_config, inbound_handshake_limits_override: self.inbound_handshake_limits_override, @@ -4434,12 +4436,9 @@ impl ChannelContext where SP::Target: SignerProvider { temporary_channel_id: self.temporary_channel_id, channel_state: self.channel_state, announcement_sigs_state: self.announcement_sigs_state.clone(), - // Create new Secp256k context - secp_ctx: Secp256k1::new(), + secp_ctx: self.secp_ctx.clone(), channel_value_satoshis: self.channel_value_satoshis, latest_monitor_update_id: self.latest_monitor_update_id, - // Use provided channel signer - holder_signer: ChannelSignerType::Ecdsa(holder_signer), shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(), destination_script: self.destination_script.clone(), cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number, @@ -4469,9 +4468,9 @@ impl ChannelContext where SP::Target: SignerProvider { update_time_counter: self.update_time_counter, // Create new mutex with copied values #[cfg(debug_assertions)] - holder_max_commitment_tx_output: Mutex::new(*self.holder_max_commitment_tx_output.lock().unwrap()), + holder_max_commitment_tx_output: self.holder_max_commitment_tx_output.clone(), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: Mutex::new(*self.counterparty_max_commitment_tx_output.lock().unwrap()), + counterparty_max_commitment_tx_output: self.counterparty_max_commitment_tx_output.clone(), last_sent_closing_fee: self.last_sent_closing_fee.clone(), last_received_closing_sig: self.last_received_closing_sig, target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw, @@ -4508,9 +4507,9 @@ impl ChannelContext where SP::Target: SignerProvider { announcement_sigs: self.announcement_sigs, // Create new mutex with copied values #[cfg(any(test, fuzzing))] - next_local_commitment_tx_fee_info_cached: Mutex::new(self.next_local_commitment_tx_fee_info_cached.lock().unwrap().clone()), + next_local_commitment_tx_fee_info_cached: self.next_local_commitment_tx_fee_info_cached.clone(), #[cfg(any(test, fuzzing))] - next_remote_commitment_tx_fee_info_cached: Mutex::new(self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().clone()), + next_remote_commitment_tx_fee_info_cached: self.next_remote_commitment_tx_fee_info_cached.clone(), workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(), sent_message_awaiting_response: self.sent_message_awaiting_response, channel_type: self.channel_type.clone(), @@ -10490,9 +10489,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch feerate_per_kw, #[cfg(debug_assertions)] - holder_max_commitment_tx_output: Mutex::new((0, 0)), + holder_max_commitment_tx_output: Arc::new(Mutex::new((0, 0))), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: Mutex::new((0, 0)), + counterparty_max_commitment_tx_output: Arc::new(Mutex::new((0, 0))), last_sent_closing_fee: None, last_received_closing_sig: None, @@ -10537,9 +10536,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch announcement_sigs, #[cfg(any(test, fuzzing))] - next_local_commitment_tx_fee_info_cached: Mutex::new(None), + next_local_commitment_tx_fee_info_cached: Arc::new(Mutex::new(None)), #[cfg(any(test, fuzzing))] - next_remote_commitment_tx_fee_info_cached: Mutex::new(None), + next_remote_commitment_tx_fee_info_cached: Arc::new(Mutex::new(None)), workaround_lnd_bug_4006: None, sent_message_awaiting_response: None,