@@ -112,6 +112,7 @@ enum FeeUpdateState {
112
112
Outbound,
113
113
}
114
114
115
+ #[derive(Clone)]
115
116
enum InboundHTLCRemovalReason {
116
117
FailRelay(msgs::OnionErrorPacket),
117
118
FailMalformed(([u8; 32], u16)),
@@ -146,6 +147,7 @@ impl_writeable_tlv_based_enum!(InboundHTLCResolution,
146
147
},
147
148
);
148
149
150
+ #[derive(Clone)]
149
151
enum InboundHTLCState {
150
152
/// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an
151
153
/// update_add_htlc message for this HTLC.
@@ -220,6 +222,7 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
220
222
}
221
223
}
222
224
225
+ #[derive(Clone)]
223
226
struct InboundHTLCOutput {
224
227
htlc_id: u64,
225
228
amount_msat: u64,
@@ -228,7 +231,8 @@ struct InboundHTLCOutput {
228
231
state: InboundHTLCState,
229
232
}
230
233
231
- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
234
+ #[derive(Clone)]
235
+ #[cfg_attr(test, derive(Debug, PartialEq))]
232
236
enum OutboundHTLCState {
233
237
/// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
234
238
/// 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<Option<&'a HTLCFailReason>> for &'a OutboundHTLCOutcome {
310
314
}
311
315
}
312
316
313
- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
317
+ #[derive(Clone)]
318
+ #[cfg_attr(test, derive(Debug, PartialEq))]
314
319
struct OutboundHTLCOutput {
315
320
htlc_id: u64,
316
321
amount_msat: u64,
@@ -323,7 +328,8 @@ struct OutboundHTLCOutput {
323
328
}
324
329
325
330
/// See AwaitingRemoteRevoke ChannelState for more info
326
- #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
331
+ #[derive(Clone)]
332
+ #[cfg_attr(test, derive(Debug, PartialEq))]
327
333
enum HTLCUpdateAwaitingACK {
328
334
AddHTLC { // TODO: Time out if we're getting close to cltv_expiry
329
335
// always outbound
@@ -798,7 +804,7 @@ pub(super) enum ChannelUpdateStatus {
798
804
}
799
805
800
806
/// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here.
801
- #[derive(PartialEq)]
807
+ #[derive(Clone, PartialEq)]
802
808
pub enum AnnouncementSigsState {
803
809
/// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since
804
810
/// we sent the last `AnnouncementSignatures`.
@@ -1116,6 +1122,7 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
1116
1122
/// Number of blocks needed for an output from a coinbase transaction to be spendable.
1117
1123
pub(crate) const COINBASE_MATURITY: u32 = 100;
1118
1124
1125
+ #[derive(Clone)]
1119
1126
struct PendingChannelMonitorUpdate {
1120
1127
update: ChannelMonitorUpdate,
1121
1128
}
@@ -4085,6 +4092,113 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4085
4092
self.channel_transaction_parameters = channel_transaction_parameters;
4086
4093
self.get_initial_counterparty_commitment_signature(logger)
4087
4094
}
4095
+
4096
+ /// Clone, each field, with a few exceptions, notably the channel signer, and
4097
+ /// a few non-cloneable fields (such as Secp256k1 context)
4098
+ #[allow(unused)]
4099
+ fn clone(&self, holder_signer: <SP::Target as SignerProvider>::EcdsaSigner) -> Self {
4100
+ Self {
4101
+ config: self.config,
4102
+ prev_config: self.prev_config,
4103
+ inbound_handshake_limits_override: self.inbound_handshake_limits_override,
4104
+ user_id: self.user_id,
4105
+ channel_id: self.channel_id,
4106
+ temporary_channel_id: self.temporary_channel_id,
4107
+ channel_state: self.channel_state,
4108
+ announcement_sigs_state: self.announcement_sigs_state.clone(),
4109
+ // Create new Secp256k context
4110
+ secp_ctx: Secp256k1::new(),
4111
+ channel_value_satoshis: self.channel_value_satoshis,
4112
+ latest_monitor_update_id: self.latest_monitor_update_id,
4113
+ // Use provided channel signer
4114
+ holder_signer: ChannelSignerType::Ecdsa(holder_signer),
4115
+ shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(),
4116
+ destination_script: self.destination_script.clone(),
4117
+ holder_commitment_point: self.holder_commitment_point,
4118
+ cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number,
4119
+ value_to_self_msat: self.value_to_self_msat,
4120
+ pending_inbound_htlcs: self.pending_inbound_htlcs.clone(),
4121
+ pending_outbound_htlcs: self.pending_outbound_htlcs.clone(),
4122
+ holding_cell_htlc_updates: self.holding_cell_htlc_updates.clone(),
4123
+ resend_order: self.resend_order.clone(),
4124
+ monitor_pending_channel_ready: self.monitor_pending_channel_ready,
4125
+ monitor_pending_revoke_and_ack: self.monitor_pending_revoke_and_ack,
4126
+ monitor_pending_commitment_signed: self.monitor_pending_commitment_signed,
4127
+ monitor_pending_forwards: self.monitor_pending_forwards.clone(),
4128
+ monitor_pending_failures: self.monitor_pending_failures.clone(),
4129
+ monitor_pending_finalized_fulfills: self.monitor_pending_finalized_fulfills.clone(),
4130
+ monitor_pending_update_adds: self.monitor_pending_update_adds.clone(),
4131
+ monitor_pending_tx_signatures: self.monitor_pending_tx_signatures.clone(),
4132
+ signer_pending_revoke_and_ack: self.signer_pending_revoke_and_ack,
4133
+ signer_pending_commitment_update: self.signer_pending_commitment_update,
4134
+ signer_pending_funding: self.signer_pending_funding,
4135
+ signer_pending_closing: self.signer_pending_closing,
4136
+ pending_update_fee: self.pending_update_fee,
4137
+ holding_cell_update_fee: self.holding_cell_update_fee,
4138
+ next_holder_htlc_id: self.next_holder_htlc_id,
4139
+ next_counterparty_htlc_id: self.next_counterparty_htlc_id,
4140
+ feerate_per_kw: self.feerate_per_kw,
4141
+ update_time_counter: self.update_time_counter,
4142
+ // Create new mutex with copied values
4143
+ #[cfg(debug_assertions)]
4144
+ holder_max_commitment_tx_output: Mutex::new(*self.holder_max_commitment_tx_output.lock().unwrap()),
4145
+ #[cfg(debug_assertions)]
4146
+ counterparty_max_commitment_tx_output: Mutex::new(*self.counterparty_max_commitment_tx_output.lock().unwrap()),
4147
+ last_sent_closing_fee: self.last_sent_closing_fee.clone(),
4148
+ last_received_closing_sig: self.last_received_closing_sig,
4149
+ target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw,
4150
+ pending_counterparty_closing_signed: self.pending_counterparty_closing_signed.clone(),
4151
+ closing_fee_limits: self.closing_fee_limits,
4152
+ expecting_peer_commitment_signed: self.expecting_peer_commitment_signed,
4153
+ funding_tx_confirmed_in: self.funding_tx_confirmed_in,
4154
+ funding_tx_confirmation_height: self.funding_tx_confirmation_height,
4155
+ short_channel_id: self.short_channel_id,
4156
+ channel_creation_height: self.channel_creation_height,
4157
+ counterparty_dust_limit_satoshis: self.counterparty_dust_limit_satoshis,
4158
+ holder_dust_limit_satoshis: self.holder_dust_limit_satoshis,
4159
+ counterparty_max_htlc_value_in_flight_msat: self.counterparty_max_htlc_value_in_flight_msat,
4160
+ holder_max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
4161
+ counterparty_selected_channel_reserve_satoshis: self.counterparty_selected_channel_reserve_satoshis,
4162
+ holder_selected_channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
4163
+ counterparty_htlc_minimum_msat: self.counterparty_htlc_minimum_msat,
4164
+ holder_htlc_minimum_msat: self.holder_htlc_minimum_msat,
4165
+ counterparty_max_accepted_htlcs: self.counterparty_max_accepted_htlcs,
4166
+ holder_max_accepted_htlcs: self.holder_max_accepted_htlcs,
4167
+ minimum_depth: self.minimum_depth,
4168
+ counterparty_forwarding_info: self.counterparty_forwarding_info.clone(),
4169
+ channel_transaction_parameters: self.channel_transaction_parameters.clone(),
4170
+ funding_transaction: self.funding_transaction.clone(),
4171
+ is_manual_broadcast: self.is_manual_broadcast,
4172
+ is_batch_funding: self.is_batch_funding,
4173
+ counterparty_cur_commitment_point: self.counterparty_cur_commitment_point,
4174
+ counterparty_prev_commitment_point: self.counterparty_prev_commitment_point,
4175
+ counterparty_node_id: self.counterparty_node_id,
4176
+ counterparty_shutdown_scriptpubkey: self.counterparty_shutdown_scriptpubkey.clone(),
4177
+ commitment_secrets: self.commitment_secrets.clone(),
4178
+ channel_update_status: self.channel_update_status,
4179
+ closing_signed_in_flight: self.closing_signed_in_flight,
4180
+ announcement_sigs: self.announcement_sigs,
4181
+ // Create new mutex with copied values
4182
+ #[cfg(any(test, fuzzing))]
4183
+ next_local_commitment_tx_fee_info_cached: Mutex::new(self.next_local_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4184
+ #[cfg(any(test, fuzzing))]
4185
+ next_remote_commitment_tx_fee_info_cached: Mutex::new(self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4186
+ workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(),
4187
+ sent_message_awaiting_response: self.sent_message_awaiting_response,
4188
+ #[cfg(any(test, fuzzing))]
4189
+ historical_inbound_htlc_fulfills: self.historical_inbound_htlc_fulfills.clone(),
4190
+ channel_type: self.channel_type.clone(),
4191
+ latest_inbound_scid_alias: self.latest_inbound_scid_alias,
4192
+ outbound_scid_alias: self.outbound_scid_alias,
4193
+ channel_pending_event_emitted: self.channel_pending_event_emitted,
4194
+ funding_tx_broadcast_safe_event_emitted: self.funding_tx_broadcast_safe_event_emitted,
4195
+ channel_ready_event_emitted: self.channel_ready_event_emitted,
4196
+ local_initiated_shutdown: self.local_initiated_shutdown.clone(),
4197
+ channel_keys_id: self.channel_keys_id,
4198
+ blocked_monitor_updates: self.blocked_monitor_updates.clone(),
4199
+ next_funding_txid: self.next_funding_txid.clone(),
4200
+ }
4201
+ }
4088
4202
}
4089
4203
4090
4204
// Internal utility functions for channels
@@ -4209,6 +4323,7 @@ pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
4209
4323
}
4210
4324
4211
4325
#[cfg(any(test, fuzzing))]
4326
+ #[derive(Clone)]
4212
4327
struct CommitmentTxInfoCached {
4213
4328
fee: u64,
4214
4329
total_pending_htlcs: usize,
@@ -10143,7 +10258,7 @@ mod tests {
10143
10258
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
10144
10259
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
10145
10260
use crate::ln::channel::InitFeatures;
10146
- use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
10261
+ use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelContext, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
10147
10262
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
10148
10263
use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
10149
10264
use crate::ln::msgs;
@@ -11907,4 +12022,55 @@ mod tests {
11907
12022
assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
11908
12023
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
11909
12024
}
12025
+
12026
+ #[test]
12027
+ fn channel_context_clone() {
12028
+ let fee_estimator = TestFeeEstimator {fee_est: 253 };
12029
+ let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
12030
+ let seed = [42; 32];
12031
+ let network = Network::Testnet;
12032
+ let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
12033
+ let secp_ctx = Secp256k1::new();
12034
+ let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
12035
+ let config = UserConfig::default();
12036
+
12037
+ let signer_provider: &TestKeysInterface = &&keys_provider;
12038
+ let channel_value_satoshis = 10000000;
12039
+ let user_id = 42;
12040
+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
12041
+ let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12042
+ let logger = test_utils::TestLogger::new();
12043
+ let pubkeys = holder_signer.pubkeys().clone();
12044
+
12045
+ // Create a context
12046
+ let context = ChannelContext::<&TestKeysInterface>::new_for_outbound_channel(
12047
+ &bounded_fee_estimator,
12048
+ &&keys_provider,
12049
+ &signer_provider,
12050
+ node_a_node_id,
12051
+ &channelmanager::provided_init_features(&config),
12052
+ channel_value_satoshis,
12053
+ 100000,
12054
+ user_id,
12055
+ &config,
12056
+ 0,
12057
+ 42,
12058
+ None,
12059
+ 100000,
12060
+ [42; 32],
12061
+ holder_signer,
12062
+ pubkeys,
12063
+ &logger,
12064
+ ).unwrap();
12065
+
12066
+ // Clone it
12067
+ let holder_signer2 = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12068
+ let context_cloned = context.clone(holder_signer2);
12069
+
12070
+ // Compare some fields
12071
+ assert_eq!(context_cloned.channel_value_satoshis, context.channel_value_satoshis);
12072
+ assert_eq!(context_cloned.channel_id, context.channel_id);
12073
+ assert_eq!(context_cloned.funding_tx_broadcast_safe_event_emitted, context.funding_tx_broadcast_safe_event_emitted);
12074
+ assert_eq!(context_cloned.channel_keys_id, context.channel_keys_id);
12075
+ }
11910
12076
}
0 commit comments