@@ -111,6 +111,7 @@ enum FeeUpdateState {
111111 Outbound,
112112}
113113
114+ #[derive(Clone)]
114115enum InboundHTLCRemovalReason {
115116 FailRelay(msgs::OnionErrorPacket),
116117 FailMalformed(([u8; 32], u16)),
@@ -145,6 +146,7 @@ impl_writeable_tlv_based_enum!(InboundHTLCResolution,
145146 },
146147);
147148
149+ #[derive(Clone)]
148150enum InboundHTLCState {
149151 /// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an
150152 /// update_add_htlc message for this HTLC.
@@ -219,6 +221,7 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
219221 }
220222}
221223
224+ #[derive(Clone)]
222225struct InboundHTLCOutput {
223226 htlc_id: u64,
224227 amount_msat: u64,
@@ -227,7 +230,8 @@ struct InboundHTLCOutput {
227230 state: InboundHTLCState,
228231}
229232
230- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
233+ #[derive(Clone)]
234+ #[cfg_attr(test, derive(Debug, PartialEq))]
231235enum OutboundHTLCState {
232236 /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
233237 /// created it we would have put it in the holding cell instead). When they next revoke_and_ack
@@ -309,7 +313,8 @@ impl<'a> Into<Option<&'a HTLCFailReason>> for &'a OutboundHTLCOutcome {
309313 }
310314}
311315
312- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
316+ #[derive(Clone)]
317+ #[cfg_attr(test, derive(Debug, PartialEq))]
313318struct OutboundHTLCOutput {
314319 htlc_id: u64,
315320 amount_msat: u64,
@@ -322,7 +327,8 @@ struct OutboundHTLCOutput {
322327}
323328
324329/// See AwaitingRemoteRevoke ChannelState for more info
325- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
330+ #[derive(Clone)]
331+ #[cfg_attr(test, derive(Debug, PartialEq))]
326332enum HTLCUpdateAwaitingACK {
327333 AddHTLC { // TODO: Time out if we're getting close to cltv_expiry
328334 // always outbound
@@ -797,7 +803,7 @@ pub(super) enum ChannelUpdateStatus {
797803}
798804
799805/// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here.
800- #[derive(PartialEq)]
806+ #[derive(Clone, PartialEq)]
801807pub enum AnnouncementSigsState {
802808 /// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since
803809 /// we sent the last `AnnouncementSignatures`.
@@ -1115,6 +1121,7 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
11151121/// Number of blocks needed for an output from a coinbase transaction to be spendable.
11161122pub(crate) const COINBASE_MATURITY: u32 = 100;
11171123
1124+ #[derive(Clone)]
11181125struct PendingChannelMonitorUpdate {
11191126 update: ChannelMonitorUpdate,
11201127}
@@ -4237,6 +4244,113 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
42374244 self.get_initial_counterparty_commitment_signature(logger)
42384245 }
42394246
4247+ /// Clone, each field, with a few exceptions, notably the channel signer, and
4248+ /// a few non-cloneable fields (such as Secp256k1 context)
4249+ #[allow(unused)]
4250+ fn clone(&self, holder_signer: <SP::Target as SignerProvider>::EcdsaSigner) -> Self {
4251+ Self {
4252+ config: self.config,
4253+ prev_config: self.prev_config,
4254+ inbound_handshake_limits_override: self.inbound_handshake_limits_override,
4255+ user_id: self.user_id,
4256+ channel_id: self.channel_id,
4257+ temporary_channel_id: self.temporary_channel_id,
4258+ channel_state: self.channel_state,
4259+ announcement_sigs_state: self.announcement_sigs_state.clone(),
4260+ // Create new Secp256k context
4261+ secp_ctx: Secp256k1::new(),
4262+ channel_value_satoshis: self.channel_value_satoshis,
4263+ latest_monitor_update_id: self.latest_monitor_update_id,
4264+ // Use provided channel signer
4265+ holder_signer: ChannelSignerType::Ecdsa(holder_signer),
4266+ shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(),
4267+ destination_script: self.destination_script.clone(),
4268+ holder_commitment_point: self.holder_commitment_point,
4269+ cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number,
4270+ value_to_self_msat: self.value_to_self_msat,
4271+ pending_inbound_htlcs: self.pending_inbound_htlcs.clone(),
4272+ pending_outbound_htlcs: self.pending_outbound_htlcs.clone(),
4273+ holding_cell_htlc_updates: self.holding_cell_htlc_updates.clone(),
4274+ resend_order: self.resend_order.clone(),
4275+ monitor_pending_channel_ready: self.monitor_pending_channel_ready,
4276+ monitor_pending_revoke_and_ack: self.monitor_pending_revoke_and_ack,
4277+ monitor_pending_commitment_signed: self.monitor_pending_commitment_signed,
4278+ monitor_pending_forwards: self.monitor_pending_forwards.clone(),
4279+ monitor_pending_failures: self.monitor_pending_failures.clone(),
4280+ monitor_pending_finalized_fulfills: self.monitor_pending_finalized_fulfills.clone(),
4281+ monitor_pending_update_adds: self.monitor_pending_update_adds.clone(),
4282+ monitor_pending_tx_signatures: self.monitor_pending_tx_signatures.clone(),
4283+ signer_pending_revoke_and_ack: self.signer_pending_revoke_and_ack,
4284+ signer_pending_commitment_update: self.signer_pending_commitment_update,
4285+ signer_pending_funding: self.signer_pending_funding,
4286+ signer_pending_closing: self.signer_pending_closing,
4287+ pending_update_fee: self.pending_update_fee,
4288+ holding_cell_update_fee: self.holding_cell_update_fee,
4289+ next_holder_htlc_id: self.next_holder_htlc_id,
4290+ next_counterparty_htlc_id: self.next_counterparty_htlc_id,
4291+ feerate_per_kw: self.feerate_per_kw,
4292+ update_time_counter: self.update_time_counter,
4293+ // Create new mutex with copied values
4294+ #[cfg(debug_assertions)]
4295+ holder_max_commitment_tx_output: Mutex::new(*self.holder_max_commitment_tx_output.lock().unwrap()),
4296+ #[cfg(debug_assertions)]
4297+ counterparty_max_commitment_tx_output: Mutex::new(*self.counterparty_max_commitment_tx_output.lock().unwrap()),
4298+ last_sent_closing_fee: self.last_sent_closing_fee.clone(),
4299+ last_received_closing_sig: self.last_received_closing_sig,
4300+ target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw,
4301+ pending_counterparty_closing_signed: self.pending_counterparty_closing_signed.clone(),
4302+ closing_fee_limits: self.closing_fee_limits,
4303+ expecting_peer_commitment_signed: self.expecting_peer_commitment_signed,
4304+ funding_tx_confirmed_in: self.funding_tx_confirmed_in,
4305+ funding_tx_confirmation_height: self.funding_tx_confirmation_height,
4306+ short_channel_id: self.short_channel_id,
4307+ channel_creation_height: self.channel_creation_height,
4308+ counterparty_dust_limit_satoshis: self.counterparty_dust_limit_satoshis,
4309+ holder_dust_limit_satoshis: self.holder_dust_limit_satoshis,
4310+ counterparty_max_htlc_value_in_flight_msat: self.counterparty_max_htlc_value_in_flight_msat,
4311+ holder_max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
4312+ counterparty_selected_channel_reserve_satoshis: self.counterparty_selected_channel_reserve_satoshis,
4313+ holder_selected_channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
4314+ counterparty_htlc_minimum_msat: self.counterparty_htlc_minimum_msat,
4315+ holder_htlc_minimum_msat: self.holder_htlc_minimum_msat,
4316+ counterparty_max_accepted_htlcs: self.counterparty_max_accepted_htlcs,
4317+ holder_max_accepted_htlcs: self.holder_max_accepted_htlcs,
4318+ minimum_depth: self.minimum_depth,
4319+ counterparty_forwarding_info: self.counterparty_forwarding_info.clone(),
4320+ channel_transaction_parameters: self.channel_transaction_parameters.clone(),
4321+ funding_transaction: self.funding_transaction.clone(),
4322+ is_manual_broadcast: self.is_manual_broadcast,
4323+ is_batch_funding: self.is_batch_funding,
4324+ counterparty_cur_commitment_point: self.counterparty_cur_commitment_point,
4325+ counterparty_prev_commitment_point: self.counterparty_prev_commitment_point,
4326+ counterparty_node_id: self.counterparty_node_id,
4327+ counterparty_shutdown_scriptpubkey: self.counterparty_shutdown_scriptpubkey.clone(),
4328+ commitment_secrets: self.commitment_secrets.clone(),
4329+ channel_update_status: self.channel_update_status,
4330+ closing_signed_in_flight: self.closing_signed_in_flight,
4331+ announcement_sigs: self.announcement_sigs,
4332+ // Create new mutex with copied values
4333+ #[cfg(any(test, fuzzing))]
4334+ next_local_commitment_tx_fee_info_cached: Mutex::new(self.next_local_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4335+ #[cfg(any(test, fuzzing))]
4336+ next_remote_commitment_tx_fee_info_cached: Mutex::new(self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4337+ workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(),
4338+ sent_message_awaiting_response: self.sent_message_awaiting_response,
4339+ #[cfg(any(test, fuzzing))]
4340+ historical_inbound_htlc_fulfills: self.historical_inbound_htlc_fulfills.clone(),
4341+ channel_type: self.channel_type.clone(),
4342+ latest_inbound_scid_alias: self.latest_inbound_scid_alias,
4343+ outbound_scid_alias: self.outbound_scid_alias,
4344+ channel_pending_event_emitted: self.channel_pending_event_emitted,
4345+ funding_tx_broadcast_safe_event_emitted: self.funding_tx_broadcast_safe_event_emitted,
4346+ channel_ready_event_emitted: self.channel_ready_event_emitted,
4347+ local_initiated_shutdown: self.local_initiated_shutdown.clone(),
4348+ channel_keys_id: self.channel_keys_id,
4349+ blocked_monitor_updates: self.blocked_monitor_updates.clone(),
4350+ next_funding_txid: self.next_funding_txid.clone(),
4351+ }
4352+ }
4353+
42404354 /// Splice process starting; update state, log, etc.
42414355 #[cfg(splicing)]
42424356 pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
@@ -4409,6 +4523,7 @@ pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
44094523}
44104524
44114525#[cfg(any(test, fuzzing))]
4526+ #[derive(Clone)]
44124527struct CommitmentTxInfoCached {
44134528 fee: u64,
44144529 total_pending_htlcs: usize,
@@ -10510,7 +10625,7 @@ mod tests {
1051010625 use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1051110626 use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
1051210627 use crate::ln::channel::InitFeatures;
10513- use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
10628+ use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelContext, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
1051410629 use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
1051510630 use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
1051610631 use crate::ln::msgs;
@@ -12275,6 +12390,57 @@ mod tests {
1227512390 assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1227612391 }
1227712392
12393+ #[test]
12394+ fn channel_context_clone() {
12395+ let fee_estimator = TestFeeEstimator {fee_est: 253 };
12396+ let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
12397+ let seed = [42; 32];
12398+ let network = Network::Testnet;
12399+ let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
12400+ let secp_ctx = Secp256k1::new();
12401+ let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
12402+ let config = UserConfig::default();
12403+
12404+ let signer_provider: &TestKeysInterface = &&keys_provider;
12405+ let channel_value_satoshis = 10000000;
12406+ let user_id = 42;
12407+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
12408+ let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12409+ let logger = test_utils::TestLogger::new();
12410+ let pubkeys = holder_signer.pubkeys().clone();
12411+
12412+ // Create a context
12413+ let context = ChannelContext::<&TestKeysInterface>::new_for_outbound_channel(
12414+ &bounded_fee_estimator,
12415+ &&keys_provider,
12416+ &signer_provider,
12417+ node_a_node_id,
12418+ &channelmanager::provided_init_features(&config),
12419+ channel_value_satoshis,
12420+ 100000,
12421+ user_id,
12422+ &config,
12423+ 0,
12424+ 42,
12425+ None,
12426+ 100000,
12427+ [42; 32],
12428+ holder_signer,
12429+ pubkeys,
12430+ &logger,
12431+ ).unwrap();
12432+
12433+ // Clone it
12434+ let holder_signer2 = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12435+ let context_cloned = context.clone(holder_signer2);
12436+
12437+ // Compare some fields
12438+ assert_eq!(context_cloned.channel_value_satoshis, context.channel_value_satoshis);
12439+ assert_eq!(context_cloned.channel_id, context.channel_id);
12440+ assert_eq!(context_cloned.funding_tx_broadcast_safe_event_emitted, context.funding_tx_broadcast_safe_event_emitted);
12441+ assert_eq!(context_cloned.channel_keys_id, context.channel_keys_id);
12442+ }
12443+
1227812444 #[cfg(all(test, splicing))]
1227912445 fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
1228012446 use crate::ln::channel::PendingSplice;
0 commit comments