@@ -115,6 +115,7 @@ enum FeeUpdateState {
115115 Outbound,
116116}
117117
118+ #[derive(Clone)]
118119enum InboundHTLCRemovalReason {
119120 FailRelay(msgs::OnionErrorPacket),
120121 FailMalformed(([u8; 32], u16)),
@@ -149,6 +150,7 @@ impl_writeable_tlv_based_enum!(InboundHTLCResolution,
149150 },
150151);
151152
153+ #[derive(Clone)]
152154enum InboundHTLCState {
153155 /// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an
154156 /// update_add_htlc message for this HTLC.
@@ -223,6 +225,7 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
223225 }
224226}
225227
228+ #[derive(Clone)]
226229struct InboundHTLCOutput {
227230 htlc_id: u64,
228231 amount_msat: u64,
@@ -231,7 +234,8 @@ struct InboundHTLCOutput {
231234 state: InboundHTLCState,
232235}
233236
234- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
237+ #[derive(Clone)]
238+ #[cfg_attr(test, derive(Debug, PartialEq))]
235239enum OutboundHTLCState {
236240 /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
237241 /// created it we would have put it in the holding cell instead). When they next revoke_and_ack
@@ -313,7 +317,8 @@ impl<'a> Into<Option<&'a HTLCFailReason>> for &'a OutboundHTLCOutcome {
313317 }
314318}
315319
316- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
320+ #[derive(Clone)]
321+ #[cfg_attr(test, derive(Debug, PartialEq))]
317322struct OutboundHTLCOutput {
318323 htlc_id: u64,
319324 amount_msat: u64,
@@ -326,7 +331,8 @@ struct OutboundHTLCOutput {
326331}
327332
328333/// See AwaitingRemoteRevoke ChannelState for more info
329- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
334+ #[derive(Clone)]
335+ #[cfg_attr(test, derive(Debug, PartialEq))]
330336enum HTLCUpdateAwaitingACK {
331337 AddHTLC { // TODO: Time out if we're getting close to cltv_expiry
332338 // always outbound
@@ -836,7 +842,7 @@ pub(super) enum ChannelUpdateStatus {
836842}
837843
838844/// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here.
839- #[derive(PartialEq)]
845+ #[derive(Clone, PartialEq)]
840846pub enum AnnouncementSigsState {
841847 /// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since
842848 /// we sent the last `AnnouncementSignatures`.
@@ -1164,6 +1170,7 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
11641170/// Number of blocks needed for an output from a coinbase transaction to be spendable.
11651171pub(crate) const COINBASE_MATURITY: u32 = 100;
11661172
1173+ #[derive(Clone)]
11671174struct PendingChannelMonitorUpdate {
11681175 update: ChannelMonitorUpdate,
11691176}
@@ -4877,6 +4884,112 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
48774884 self.counterparty_cur_commitment_point = Some(counterparty_cur_commitment_point_override);
48784885 self.get_initial_counterparty_commitment_signature(funding, logger)
48794886 }
4887+
4888+ /// Clone, each field, with the exception of the channel signer.
4889+ #[allow(unused)]
4890+ fn clone(&self, holder_signer: <SP::Target as SignerProvider>::EcdsaSigner) -> Self {
4891+ Self {
4892+ // Use provided channel signer
4893+ holder_signer: ChannelSignerType::Ecdsa(holder_signer),
4894+
4895+ config: self.config,
4896+ prev_config: self.prev_config,
4897+ inbound_handshake_limits_override: self.inbound_handshake_limits_override,
4898+ user_id: self.user_id,
4899+ channel_id: self.channel_id,
4900+ temporary_channel_id: self.temporary_channel_id,
4901+ channel_state: self.channel_state,
4902+ announcement_sigs_state: self.announcement_sigs_state.clone(),
4903+ secp_ctx: self.secp_ctx.clone(),
4904+ // channel_value_satoshis: self.channel_value_satoshis,
4905+ latest_monitor_update_id: self.latest_monitor_update_id,
4906+ shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(),
4907+ destination_script: self.destination_script.clone(),
4908+ // holder_commitment_point: self.holder_commitment_point,
4909+ cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number,
4910+ // value_to_self_msat: self.value_to_self_msat,
4911+ pending_inbound_htlcs: self.pending_inbound_htlcs.clone(),
4912+ pending_outbound_htlcs: self.pending_outbound_htlcs.clone(),
4913+ holding_cell_htlc_updates: self.holding_cell_htlc_updates.clone(),
4914+ resend_order: self.resend_order.clone(),
4915+ monitor_pending_channel_ready: self.monitor_pending_channel_ready,
4916+ monitor_pending_revoke_and_ack: self.monitor_pending_revoke_and_ack,
4917+ monitor_pending_commitment_signed: self.monitor_pending_commitment_signed,
4918+ monitor_pending_forwards: self.monitor_pending_forwards.clone(),
4919+ monitor_pending_failures: self.monitor_pending_failures.clone(),
4920+ monitor_pending_finalized_fulfills: self.monitor_pending_finalized_fulfills.clone(),
4921+ monitor_pending_update_adds: self.monitor_pending_update_adds.clone(),
4922+ monitor_pending_tx_signatures: self.monitor_pending_tx_signatures.clone(),
4923+ signer_pending_revoke_and_ack: self.signer_pending_revoke_and_ack,
4924+ signer_pending_commitment_update: self.signer_pending_commitment_update,
4925+ signer_pending_funding: self.signer_pending_funding,
4926+ signer_pending_closing: self.signer_pending_closing,
4927+ signer_pending_channel_ready: self.signer_pending_channel_ready,
4928+ pending_update_fee: self.pending_update_fee,
4929+ holding_cell_update_fee: self.holding_cell_update_fee,
4930+ next_holder_htlc_id: self.next_holder_htlc_id,
4931+ next_counterparty_htlc_id: self.next_counterparty_htlc_id,
4932+ feerate_per_kw: self.feerate_per_kw,
4933+ update_time_counter: self.update_time_counter,
4934+ // Create new mutex with copied values
4935+ // #[cfg(debug_assertions)]
4936+ // holder_max_commitment_tx_output: self.holder_max_commitment_tx_output.clone(),
4937+ // #[cfg(debug_assertions)]
4938+ // counterparty_max_commitment_tx_output: self.counterparty_max_commitment_tx_output.clone(),
4939+ last_sent_closing_fee: self.last_sent_closing_fee.clone(),
4940+ last_received_closing_sig: self.last_received_closing_sig,
4941+ target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw,
4942+ pending_counterparty_closing_signed: self.pending_counterparty_closing_signed.clone(),
4943+ closing_fee_limits: self.closing_fee_limits,
4944+ expecting_peer_commitment_signed: self.expecting_peer_commitment_signed,
4945+ funding_tx_confirmed_in: self.funding_tx_confirmed_in,
4946+ funding_tx_confirmation_height: self.funding_tx_confirmation_height,
4947+ short_channel_id: self.short_channel_id,
4948+ channel_creation_height: self.channel_creation_height,
4949+ counterparty_dust_limit_satoshis: self.counterparty_dust_limit_satoshis,
4950+ holder_dust_limit_satoshis: self.holder_dust_limit_satoshis,
4951+ counterparty_max_htlc_value_in_flight_msat: self.counterparty_max_htlc_value_in_flight_msat,
4952+ holder_max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
4953+ // counterparty_selected_channel_reserve_satoshis: self.counterparty_selected_channel_reserve_satoshis,
4954+ // holder_selected_channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
4955+ counterparty_htlc_minimum_msat: self.counterparty_htlc_minimum_msat,
4956+ holder_htlc_minimum_msat: self.holder_htlc_minimum_msat,
4957+ counterparty_max_accepted_htlcs: self.counterparty_max_accepted_htlcs,
4958+ holder_max_accepted_htlcs: self.holder_max_accepted_htlcs,
4959+ minimum_depth: self.minimum_depth,
4960+ counterparty_forwarding_info: self.counterparty_forwarding_info.clone(),
4961+ // channel_transaction_parameters: self.channel_transaction_parameters.clone(),
4962+ // funding_transaction: self.funding_transaction.clone(),
4963+ is_manual_broadcast: self.is_manual_broadcast,
4964+ is_batch_funding: self.is_batch_funding,
4965+ counterparty_cur_commitment_point: self.counterparty_cur_commitment_point,
4966+ counterparty_prev_commitment_point: self.counterparty_prev_commitment_point,
4967+ counterparty_node_id: self.counterparty_node_id,
4968+ counterparty_shutdown_scriptpubkey: self.counterparty_shutdown_scriptpubkey.clone(),
4969+ commitment_secrets: self.commitment_secrets.clone(),
4970+ channel_update_status: self.channel_update_status,
4971+ closing_signed_in_flight: self.closing_signed_in_flight,
4972+ announcement_sigs: self.announcement_sigs,
4973+ // Create new mutex with copied values
4974+ // #[cfg(any(test, fuzzing))]
4975+ // next_local_commitment_tx_fee_info_cached: self.next_local_commitment_tx_fee_info_cached.clone(),
4976+ // #[cfg(any(test, fuzzing))]
4977+ // next_remote_commitment_tx_fee_info_cached: self.next_remote_commitment_tx_fee_info_cached.clone(),
4978+ workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(),
4979+ sent_message_awaiting_response: self.sent_message_awaiting_response,
4980+ channel_type: self.channel_type.clone(),
4981+ latest_inbound_scid_alias: self.latest_inbound_scid_alias,
4982+ outbound_scid_alias: self.outbound_scid_alias,
4983+ channel_pending_event_emitted: self.channel_pending_event_emitted,
4984+ funding_tx_broadcast_safe_event_emitted: self.funding_tx_broadcast_safe_event_emitted,
4985+ channel_ready_event_emitted: self.channel_ready_event_emitted,
4986+ local_initiated_shutdown: self.local_initiated_shutdown.clone(),
4987+ channel_keys_id: self.channel_keys_id,
4988+ blocked_monitor_updates: self.blocked_monitor_updates.clone(),
4989+ next_funding_txid: self.next_funding_txid.clone(),
4990+ is_holder_quiescence_initiator: self.is_holder_quiescence_initiator,
4991+ }
4992+ }
48804993}
48814994
48824995// Internal utility functions for channels
@@ -5056,6 +5169,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
50565169}
50575170
50585171#[cfg(any(test, fuzzing))]
5172+ #[derive(Clone)]
50595173struct CommitmentTxInfoCached {
50605174 fee: u64,
50615175 total_pending_htlcs: usize,
@@ -11341,7 +11455,7 @@ mod tests {
1134111455 use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1134211456 use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
1134311457 use crate::ln::channel::InitFeatures;
11344- use crate::ln::channel::{AwaitingChannelReadyFlags, ChannelState, FundedChannel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
11458+ use crate::ln::channel::{AwaitingChannelReadyFlags, ChannelContext, ChannelId, ChannelPublicKeys, ChannelState, FundedChannel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
1134511459 use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
1134611460 use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
1134711461 use crate::ln::msgs;
@@ -13249,6 +13363,59 @@ mod tests {
1324913363 }
1325013364 }
1325113365
13366+ #[test]
13367+ fn channel_context_clone() {
13368+ let fee_estimator = TestFeeEstimator {fee_est: 253 };
13369+ let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
13370+ let seed = [42; 32];
13371+ let network = Network::Testnet;
13372+ let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
13373+ let secp_ctx = Secp256k1::new();
13374+ let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
13375+ let config = UserConfig::default();
13376+
13377+ let signer_provider: &TestKeysInterface = &&keys_provider;
13378+ let channel_value_satoshis = 10000000;
13379+ let user_id = 42;
13380+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, user_id);
13381+ let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
13382+ let logger = test_utils::TestLogger::new();
13383+
13384+ let temporary_channel_id_fn = Some(|pubkeys: &ChannelPublicKeys| {
13385+ ChannelId::temporary_v2_from_revocation_basepoint(&pubkeys.revocation_basepoint)
13386+ });
13387+
13388+ // Create a context
13389+ let context = ChannelContext::<&TestKeysInterface>::new_for_outbound_channel(
13390+ &bounded_fee_estimator,
13391+ &&keys_provider,
13392+ &signer_provider,
13393+ node_a_node_id,
13394+ &channelmanager::provided_init_features(&config),
13395+ channel_value_satoshis,
13396+ 100000,
13397+ user_id,
13398+ &config,
13399+ 0,
13400+ 42,
13401+ temporary_channel_id_fn,
13402+ 100000,
13403+ [42; 32],
13404+ holder_signer,
13405+ &logger,
13406+ ).unwrap().1;
13407+
13408+ // Clone it
13409+ let holder_signer2 = signer_provider.derive_channel_signer(channel_keys_id);
13410+ let context_cloned = context.clone(holder_signer2);
13411+
13412+ // Compare some fields
13413+ // assert_eq!(context_cloned.channel_value_satoshis, context.channel_value_satoshis);
13414+ assert_eq!(context_cloned.channel_id, context.channel_id);
13415+ assert_eq!(context_cloned.funding_tx_broadcast_safe_event_emitted, context.funding_tx_broadcast_safe_event_emitted);
13416+ assert_eq!(context_cloned.channel_keys_id, context.channel_keys_id);
13417+ }
13418+
1325213419 #[cfg(all(test, splicing))]
1325313420 fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
1325413421 use crate::ln::channel::PendingSplice;
0 commit comments