@@ -104,6 +104,7 @@ enum FeeUpdateState {
104
104
Outbound,
105
105
}
106
106
107
+ #[derive(Clone)]
107
108
enum InboundHTLCRemovalReason {
108
109
FailRelay(msgs::OnionErrorPacket),
109
110
FailMalformed(([u8; 32], u16)),
@@ -138,6 +139,7 @@ impl_writeable_tlv_based_enum!(InboundHTLCResolution,
138
139
},
139
140
);
140
141
142
+ #[derive(Clone)]
141
143
enum InboundHTLCState {
142
144
/// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an
143
145
/// update_add_htlc message for this HTLC.
@@ -212,6 +214,7 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
212
214
}
213
215
}
214
216
217
+ #[derive(Clone)]
215
218
struct InboundHTLCOutput {
216
219
htlc_id: u64,
217
220
amount_msat: u64,
@@ -220,7 +223,8 @@ struct InboundHTLCOutput {
220
223
state: InboundHTLCState,
221
224
}
222
225
223
- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
226
+ #[derive(Clone)]
227
+ #[cfg_attr(test, derive(Debug, PartialEq))]
224
228
enum OutboundHTLCState {
225
229
/// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
226
230
/// created it we would have put it in the holding cell instead). When they next revoke_and_ack
@@ -302,7 +306,8 @@ impl<'a> Into<Option<&'a HTLCFailReason>> for &'a OutboundHTLCOutcome {
302
306
}
303
307
}
304
308
305
- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
309
+ #[derive(Clone)]
310
+ #[cfg_attr(test, derive(Debug, PartialEq))]
306
311
struct OutboundHTLCOutput {
307
312
htlc_id: u64,
308
313
amount_msat: u64,
@@ -315,7 +320,8 @@ struct OutboundHTLCOutput {
315
320
}
316
321
317
322
/// See AwaitingRemoteRevoke ChannelState for more info
318
- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
323
+ #[derive(Clone)]
324
+ #[cfg_attr(test, derive(Debug, PartialEq))]
319
325
enum HTLCUpdateAwaitingACK {
320
326
AddHTLC { // TODO: Time out if we're getting close to cltv_expiry
321
327
// always outbound
@@ -790,7 +796,7 @@ pub(super) enum ChannelUpdateStatus {
790
796
}
791
797
792
798
/// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here.
793
- #[derive(PartialEq)]
799
+ #[derive(Clone, PartialEq)]
794
800
pub enum AnnouncementSigsState {
795
801
/// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since
796
802
/// we sent the last `AnnouncementSignatures`.
@@ -1106,6 +1112,7 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
1106
1112
/// Number of blocks needed for an output from a coinbase transaction to be spendable.
1107
1113
pub(crate) const COINBASE_MATURITY: u32 = 100;
1108
1114
1115
+ #[derive(Clone)]
1109
1116
struct PendingChannelMonitorUpdate {
1110
1117
update: ChannelMonitorUpdate,
1111
1118
}
@@ -3621,6 +3628,111 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3621
3628
self.channel_transaction_parameters.channel_type_features = self.channel_type.clone();
3622
3629
Ok(())
3623
3630
}
3631
+
3632
+ /// Clone, each field, with a few exceptions, notably the channel signer, and
3633
+ /// a few non-cloneable fields (such as Secp256k1 context)
3634
+ #[allow(unused)]
3635
+ fn clone(&self, holder_signer: <SP::Target as SignerProvider>::EcdsaSigner) -> Self {
3636
+ Self {
3637
+ config: self.config,
3638
+ prev_config: self.prev_config,
3639
+ inbound_handshake_limits_override: self.inbound_handshake_limits_override,
3640
+ user_id: self.user_id,
3641
+ channel_id: self.channel_id,
3642
+ temporary_channel_id: self.temporary_channel_id,
3643
+ channel_state: self.channel_state,
3644
+ announcement_sigs_state: self.announcement_sigs_state.clone(),
3645
+ // Create new Secp256k context
3646
+ secp_ctx: Secp256k1::new(),
3647
+ channel_value_satoshis: self.channel_value_satoshis,
3648
+ latest_monitor_update_id: self.latest_monitor_update_id,
3649
+ // Use provided channel signer
3650
+ holder_signer: ChannelSignerType::Ecdsa(holder_signer),
3651
+ shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(),
3652
+ destination_script: self.destination_script.clone(),
3653
+ holder_commitment_point: self.holder_commitment_point,
3654
+ cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number,
3655
+ value_to_self_msat: self.value_to_self_msat,
3656
+ pending_inbound_htlcs: self.pending_inbound_htlcs.clone(),
3657
+ pending_outbound_htlcs: self.pending_outbound_htlcs.clone(),
3658
+ holding_cell_htlc_updates: self.holding_cell_htlc_updates.clone(),
3659
+ resend_order: self.resend_order.clone(),
3660
+ monitor_pending_channel_ready: self.monitor_pending_channel_ready,
3661
+ monitor_pending_revoke_and_ack: self.monitor_pending_revoke_and_ack,
3662
+ monitor_pending_commitment_signed: self.monitor_pending_commitment_signed,
3663
+ monitor_pending_forwards: self.monitor_pending_forwards.clone(),
3664
+ monitor_pending_failures: self.monitor_pending_failures.clone(),
3665
+ monitor_pending_finalized_fulfills: self.monitor_pending_finalized_fulfills.clone(),
3666
+ monitor_pending_update_adds: self.monitor_pending_update_adds.clone(),
3667
+ signer_pending_revoke_and_ack: self.signer_pending_revoke_and_ack,
3668
+ signer_pending_commitment_update: self.signer_pending_commitment_update,
3669
+ signer_pending_funding: self.signer_pending_funding,
3670
+ signer_pending_closing: self.signer_pending_closing,
3671
+ pending_update_fee: self.pending_update_fee,
3672
+ holding_cell_update_fee: self.holding_cell_update_fee,
3673
+ next_holder_htlc_id: self.next_holder_htlc_id,
3674
+ next_counterparty_htlc_id: self.next_counterparty_htlc_id,
3675
+ feerate_per_kw: self.feerate_per_kw,
3676
+ update_time_counter: self.update_time_counter,
3677
+ // Create new mutex with copied values
3678
+ #[cfg(debug_assertions)]
3679
+ holder_max_commitment_tx_output: Mutex::new(*self.holder_max_commitment_tx_output.lock().unwrap()),
3680
+ #[cfg(debug_assertions)]
3681
+ counterparty_max_commitment_tx_output: Mutex::new(*self.counterparty_max_commitment_tx_output.lock().unwrap()),
3682
+ last_sent_closing_fee: self.last_sent_closing_fee.clone(),
3683
+ last_received_closing_sig: self.last_received_closing_sig,
3684
+ target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw,
3685
+ pending_counterparty_closing_signed: self.pending_counterparty_closing_signed.clone(),
3686
+ closing_fee_limits: self.closing_fee_limits,
3687
+ expecting_peer_commitment_signed: self.expecting_peer_commitment_signed,
3688
+ funding_tx_confirmed_in: self.funding_tx_confirmed_in,
3689
+ funding_tx_confirmation_height: self.funding_tx_confirmation_height,
3690
+ short_channel_id: self.short_channel_id,
3691
+ channel_creation_height: self.channel_creation_height,
3692
+ counterparty_dust_limit_satoshis: self.counterparty_dust_limit_satoshis,
3693
+ holder_dust_limit_satoshis: self.holder_dust_limit_satoshis,
3694
+ counterparty_max_htlc_value_in_flight_msat: self.counterparty_max_htlc_value_in_flight_msat,
3695
+ holder_max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
3696
+ counterparty_selected_channel_reserve_satoshis: self.counterparty_selected_channel_reserve_satoshis,
3697
+ holder_selected_channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
3698
+ counterparty_htlc_minimum_msat: self.counterparty_htlc_minimum_msat,
3699
+ holder_htlc_minimum_msat: self.holder_htlc_minimum_msat,
3700
+ counterparty_max_accepted_htlcs: self.counterparty_max_accepted_htlcs,
3701
+ holder_max_accepted_htlcs: self.holder_max_accepted_htlcs,
3702
+ minimum_depth: self.minimum_depth,
3703
+ counterparty_forwarding_info: self.counterparty_forwarding_info.clone(),
3704
+ channel_transaction_parameters: self.channel_transaction_parameters.clone(),
3705
+ funding_transaction: self.funding_transaction.clone(),
3706
+ is_manual_broadcast: self.is_manual_broadcast,
3707
+ is_batch_funding: self.is_batch_funding,
3708
+ counterparty_cur_commitment_point: self.counterparty_cur_commitment_point,
3709
+ counterparty_prev_commitment_point: self.counterparty_prev_commitment_point,
3710
+ counterparty_node_id: self.counterparty_node_id,
3711
+ counterparty_shutdown_scriptpubkey: self.counterparty_shutdown_scriptpubkey.clone(),
3712
+ commitment_secrets: self.commitment_secrets.clone(),
3713
+ channel_update_status: self.channel_update_status,
3714
+ closing_signed_in_flight: self.closing_signed_in_flight,
3715
+ announcement_sigs: self.announcement_sigs,
3716
+ // Create new mutex with copied values
3717
+ #[cfg(any(test, fuzzing))]
3718
+ next_local_commitment_tx_fee_info_cached: Mutex::new(self.next_local_commitment_tx_fee_info_cached.lock().unwrap().clone()),
3719
+ #[cfg(any(test, fuzzing))]
3720
+ next_remote_commitment_tx_fee_info_cached: Mutex::new(self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().clone()),
3721
+ workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(),
3722
+ sent_message_awaiting_response: self.sent_message_awaiting_response,
3723
+ #[cfg(any(test, fuzzing))]
3724
+ historical_inbound_htlc_fulfills: self.historical_inbound_htlc_fulfills.clone(),
3725
+ channel_type: self.channel_type.clone(),
3726
+ latest_inbound_scid_alias: self.latest_inbound_scid_alias,
3727
+ outbound_scid_alias: self.outbound_scid_alias,
3728
+ channel_pending_event_emitted: self.channel_pending_event_emitted,
3729
+ funding_tx_broadcast_safe_event_emitted: self.funding_tx_broadcast_safe_event_emitted,
3730
+ channel_ready_event_emitted: self.channel_ready_event_emitted,
3731
+ local_initiated_shutdown: self.local_initiated_shutdown.clone(),
3732
+ channel_keys_id: self.channel_keys_id,
3733
+ blocked_monitor_updates: self.blocked_monitor_updates.clone(),
3734
+ }
3735
+ }
3624
3736
}
3625
3737
3626
3738
// Internal utility functions for channels
@@ -3702,6 +3814,7 @@ pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
3702
3814
}
3703
3815
3704
3816
#[cfg(any(test, fuzzing))]
3817
+ #[derive(Clone)]
3705
3818
struct CommitmentTxInfoCached {
3706
3819
fee: u64,
3707
3820
total_pending_htlcs: usize,
@@ -9604,7 +9717,7 @@ mod tests {
9604
9717
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
9605
9718
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
9606
9719
use crate::ln::channel::InitFeatures;
9607
- use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
9720
+ use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelContext, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
9608
9721
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
9609
9722
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
9610
9723
use crate::ln::msgs;
@@ -11368,4 +11481,55 @@ mod tests {
11368
11481
assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
11369
11482
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
11370
11483
}
11484
+
11485
+ #[test]
11486
+ fn channel_context_clone() {
11487
+ let fee_estimator = TestFeeEstimator {fee_est: 253 };
11488
+ let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
11489
+ let seed = [42; 32];
11490
+ let network = Network::Testnet;
11491
+ let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
11492
+ let secp_ctx = Secp256k1::new();
11493
+ let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
11494
+ let config = UserConfig::default();
11495
+
11496
+ let signer_provider: &TestKeysInterface = &&keys_provider;
11497
+ let channel_value_satoshis = 10000000;
11498
+ let user_id = 42;
11499
+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
11500
+ let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
11501
+ let logger = test_utils::TestLogger::new();
11502
+ let pubkeys = holder_signer.pubkeys().clone();
11503
+
11504
+ // Create a context
11505
+ let context = ChannelContext::<&TestKeysInterface>::new_for_outbound_channel(
11506
+ &bounded_fee_estimator,
11507
+ &&keys_provider,
11508
+ &signer_provider,
11509
+ node_a_node_id,
11510
+ &channelmanager::provided_init_features(&config),
11511
+ channel_value_satoshis,
11512
+ 100000,
11513
+ user_id,
11514
+ &config,
11515
+ 0,
11516
+ 42,
11517
+ None,
11518
+ 100000,
11519
+ [42; 32],
11520
+ holder_signer,
11521
+ pubkeys,
11522
+ &logger,
11523
+ ).unwrap();
11524
+
11525
+ // Clone it
11526
+ let holder_signer2 = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
11527
+ let context_cloned = context.clone(holder_signer2);
11528
+
11529
+ // Compare some fields
11530
+ assert_eq!(context_cloned.channel_value_satoshis, context.channel_value_satoshis);
11531
+ assert_eq!(context_cloned.channel_id, context.channel_id);
11532
+ assert_eq!(context_cloned.funding_tx_broadcast_safe_event_emitted, context.funding_tx_broadcast_safe_event_emitted);
11533
+ assert_eq!(context_cloned.channel_keys_id, context.channel_keys_id);
11534
+ }
11371
11535
}
0 commit comments