Skip to content

Commit 4c01c4b

Browse files
committed
Clone for ChannelContext
1 parent 85d1e5f commit 4c01c4b

File tree

2 files changed

+172
-6
lines changed

2 files changed

+172
-6
lines changed

lightning/src/ln/channel.rs

+171-5
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ enum FeeUpdateState {
112112
Outbound,
113113
}
114114

115+
#[derive(Clone)]
115116
enum InboundHTLCRemovalReason {
116117
FailRelay(msgs::OnionErrorPacket),
117118
FailMalformed(([u8; 32], u16)),
@@ -146,6 +147,7 @@ impl_writeable_tlv_based_enum!(InboundHTLCResolution,
146147
},
147148
);
148149

150+
#[derive(Clone)]
149151
enum InboundHTLCState {
150152
/// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an
151153
/// update_add_htlc message for this HTLC.
@@ -220,6 +222,7 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
220222
}
221223
}
222224

225+
#[derive(Clone)]
223226
struct InboundHTLCOutput {
224227
htlc_id: u64,
225228
amount_msat: u64,
@@ -228,7 +231,8 @@ struct InboundHTLCOutput {
228231
state: InboundHTLCState,
229232
}
230233

231-
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
234+
#[derive(Clone)]
235+
#[cfg_attr(test, derive(Debug, PartialEq))]
232236
enum OutboundHTLCState {
233237
/// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
234238
/// 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 {
310314
}
311315
}
312316

313-
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
317+
#[derive(Clone)]
318+
#[cfg_attr(test, derive(Debug, PartialEq))]
314319
struct OutboundHTLCOutput {
315320
htlc_id: u64,
316321
amount_msat: u64,
@@ -323,7 +328,8 @@ struct OutboundHTLCOutput {
323328
}
324329

325330
/// See AwaitingRemoteRevoke ChannelState for more info
326-
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
331+
#[derive(Clone)]
332+
#[cfg_attr(test, derive(Debug, PartialEq))]
327333
enum HTLCUpdateAwaitingACK {
328334
AddHTLC { // TODO: Time out if we're getting close to cltv_expiry
329335
// always outbound
@@ -798,7 +804,7 @@ pub(super) enum ChannelUpdateStatus {
798804
}
799805

800806
/// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here.
801-
#[derive(PartialEq)]
807+
#[derive(Clone, PartialEq)]
802808
pub enum AnnouncementSigsState {
803809
/// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since
804810
/// we sent the last `AnnouncementSignatures`.
@@ -1113,6 +1119,7 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
11131119
/// Number of blocks needed for an output from a coinbase transaction to be spendable.
11141120
pub(crate) const COINBASE_MATURITY: u32 = 100;
11151121

1122+
#[derive(Clone)]
11161123
struct PendingChannelMonitorUpdate {
11171124
update: ChannelMonitorUpdate,
11181125
}
@@ -4097,6 +4104,113 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
40974104
self.channel_transaction_parameters = channel_transaction_parameters;
40984105
self.get_initial_counterparty_commitment_signature(logger)
40994106
}
4107+
4108+
/// Clone, each field, with a few exceptions, notably the channel signer, and
4109+
/// a few non-cloneable fields (such as Secp256k1 context)
4110+
#[allow(unused)]
4111+
fn clone(&self, holder_signer: <SP::Target as SignerProvider>::EcdsaSigner) -> Self {
4112+
Self {
4113+
config: self.config,
4114+
prev_config: self.prev_config,
4115+
inbound_handshake_limits_override: self.inbound_handshake_limits_override,
4116+
user_id: self.user_id,
4117+
channel_id: self.channel_id,
4118+
temporary_channel_id: self.temporary_channel_id,
4119+
channel_state: self.channel_state,
4120+
announcement_sigs_state: self.announcement_sigs_state.clone(),
4121+
// Create new Secp256k context
4122+
secp_ctx: Secp256k1::new(),
4123+
channel_value_satoshis: self.channel_value_satoshis,
4124+
latest_monitor_update_id: self.latest_monitor_update_id,
4125+
// Use provided channel signer
4126+
holder_signer: ChannelSignerType::Ecdsa(holder_signer),
4127+
shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(),
4128+
destination_script: self.destination_script.clone(),
4129+
cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number,
4130+
value_to_self_msat: self.value_to_self_msat,
4131+
pending_inbound_htlcs: self.pending_inbound_htlcs.clone(),
4132+
pending_outbound_htlcs: self.pending_outbound_htlcs.clone(),
4133+
holding_cell_htlc_updates: self.holding_cell_htlc_updates.clone(),
4134+
resend_order: self.resend_order.clone(),
4135+
monitor_pending_channel_ready: self.monitor_pending_channel_ready,
4136+
monitor_pending_revoke_and_ack: self.monitor_pending_revoke_and_ack,
4137+
monitor_pending_commitment_signed: self.monitor_pending_commitment_signed,
4138+
monitor_pending_forwards: self.monitor_pending_forwards.clone(),
4139+
monitor_pending_failures: self.monitor_pending_failures.clone(),
4140+
monitor_pending_finalized_fulfills: self.monitor_pending_finalized_fulfills.clone(),
4141+
monitor_pending_update_adds: self.monitor_pending_update_adds.clone(),
4142+
monitor_pending_tx_signatures: self.monitor_pending_tx_signatures.clone(),
4143+
signer_pending_revoke_and_ack: self.signer_pending_revoke_and_ack,
4144+
signer_pending_commitment_update: self.signer_pending_commitment_update,
4145+
signer_pending_funding: self.signer_pending_funding,
4146+
signer_pending_closing: self.signer_pending_closing,
4147+
signer_pending_channel_ready: self.signer_pending_channel_ready,
4148+
pending_update_fee: self.pending_update_fee,
4149+
holding_cell_update_fee: self.holding_cell_update_fee,
4150+
next_holder_htlc_id: self.next_holder_htlc_id,
4151+
next_counterparty_htlc_id: self.next_counterparty_htlc_id,
4152+
feerate_per_kw: self.feerate_per_kw,
4153+
update_time_counter: self.update_time_counter,
4154+
// Create new mutex with copied values
4155+
#[cfg(debug_assertions)]
4156+
holder_max_commitment_tx_output: Mutex::new(*self.holder_max_commitment_tx_output.lock().unwrap()),
4157+
#[cfg(debug_assertions)]
4158+
counterparty_max_commitment_tx_output: Mutex::new(*self.counterparty_max_commitment_tx_output.lock().unwrap()),
4159+
last_sent_closing_fee: self.last_sent_closing_fee.clone(),
4160+
last_received_closing_sig: self.last_received_closing_sig,
4161+
target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw,
4162+
pending_counterparty_closing_signed: self.pending_counterparty_closing_signed.clone(),
4163+
closing_fee_limits: self.closing_fee_limits,
4164+
expecting_peer_commitment_signed: self.expecting_peer_commitment_signed,
4165+
funding_tx_confirmed_in: self.funding_tx_confirmed_in,
4166+
funding_tx_confirmation_height: self.funding_tx_confirmation_height,
4167+
short_channel_id: self.short_channel_id,
4168+
channel_creation_height: self.channel_creation_height,
4169+
counterparty_dust_limit_satoshis: self.counterparty_dust_limit_satoshis,
4170+
holder_dust_limit_satoshis: self.holder_dust_limit_satoshis,
4171+
counterparty_max_htlc_value_in_flight_msat: self.counterparty_max_htlc_value_in_flight_msat,
4172+
holder_max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
4173+
counterparty_selected_channel_reserve_satoshis: self.counterparty_selected_channel_reserve_satoshis,
4174+
holder_selected_channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
4175+
counterparty_htlc_minimum_msat: self.counterparty_htlc_minimum_msat,
4176+
holder_htlc_minimum_msat: self.holder_htlc_minimum_msat,
4177+
counterparty_max_accepted_htlcs: self.counterparty_max_accepted_htlcs,
4178+
holder_max_accepted_htlcs: self.holder_max_accepted_htlcs,
4179+
minimum_depth: self.minimum_depth,
4180+
counterparty_forwarding_info: self.counterparty_forwarding_info.clone(),
4181+
channel_transaction_parameters: self.channel_transaction_parameters.clone(),
4182+
funding_transaction: self.funding_transaction.clone(),
4183+
is_manual_broadcast: self.is_manual_broadcast,
4184+
is_batch_funding: self.is_batch_funding,
4185+
counterparty_cur_commitment_point: self.counterparty_cur_commitment_point,
4186+
counterparty_prev_commitment_point: self.counterparty_prev_commitment_point,
4187+
counterparty_node_id: self.counterparty_node_id,
4188+
counterparty_shutdown_scriptpubkey: self.counterparty_shutdown_scriptpubkey.clone(),
4189+
commitment_secrets: self.commitment_secrets.clone(),
4190+
channel_update_status: self.channel_update_status,
4191+
closing_signed_in_flight: self.closing_signed_in_flight,
4192+
announcement_sigs: self.announcement_sigs,
4193+
// Create new mutex with copied values
4194+
#[cfg(any(test, fuzzing))]
4195+
next_local_commitment_tx_fee_info_cached: Mutex::new(self.next_local_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4196+
#[cfg(any(test, fuzzing))]
4197+
next_remote_commitment_tx_fee_info_cached: Mutex::new(self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4198+
workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(),
4199+
sent_message_awaiting_response: self.sent_message_awaiting_response,
4200+
#[cfg(any(test, fuzzing))]
4201+
historical_inbound_htlc_fulfills: self.historical_inbound_htlc_fulfills.clone(),
4202+
channel_type: self.channel_type.clone(),
4203+
latest_inbound_scid_alias: self.latest_inbound_scid_alias,
4204+
outbound_scid_alias: self.outbound_scid_alias,
4205+
channel_pending_event_emitted: self.channel_pending_event_emitted,
4206+
funding_tx_broadcast_safe_event_emitted: self.funding_tx_broadcast_safe_event_emitted,
4207+
channel_ready_event_emitted: self.channel_ready_event_emitted,
4208+
local_initiated_shutdown: self.local_initiated_shutdown.clone(),
4209+
channel_keys_id: self.channel_keys_id,
4210+
blocked_monitor_updates: self.blocked_monitor_updates.clone(),
4211+
next_funding_txid: self.next_funding_txid.clone(),
4212+
}
4213+
}
41004214
}
41014215

41024216
// Internal utility functions for channels
@@ -4224,6 +4338,7 @@ pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
42244338
}
42254339

42264340
#[cfg(any(test, fuzzing))]
4341+
#[derive(Clone)]
42274342
struct CommitmentTxInfoCached {
42284343
fee: u64,
42294344
total_pending_htlcs: usize,
@@ -10268,7 +10383,7 @@ mod tests {
1026810383
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1026910384
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
1027010385
use crate::ln::channel::InitFeatures;
10271-
use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
10386+
use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelContext, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
1027210387
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
1027310388
use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
1027410389
use crate::ln::msgs;
@@ -12032,4 +12147,55 @@ mod tests {
1203212147
assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
1203312148
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1203412149
}
12150+
12151+
#[test]
12152+
fn channel_context_clone() {
12153+
let fee_estimator = TestFeeEstimator {fee_est: 253 };
12154+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
12155+
let seed = [42; 32];
12156+
let network = Network::Testnet;
12157+
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
12158+
let secp_ctx = Secp256k1::new();
12159+
let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
12160+
let config = UserConfig::default();
12161+
12162+
let signer_provider: &TestKeysInterface = &&keys_provider;
12163+
let channel_value_satoshis = 10000000;
12164+
let user_id = 42;
12165+
let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
12166+
let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12167+
let logger = test_utils::TestLogger::new();
12168+
let pubkeys = holder_signer.pubkeys().clone();
12169+
12170+
// Create a context
12171+
let context = ChannelContext::<&TestKeysInterface>::new_for_outbound_channel(
12172+
&bounded_fee_estimator,
12173+
&&keys_provider,
12174+
&signer_provider,
12175+
node_a_node_id,
12176+
&channelmanager::provided_init_features(&config),
12177+
channel_value_satoshis,
12178+
100000,
12179+
user_id,
12180+
&config,
12181+
0,
12182+
42,
12183+
None,
12184+
100000,
12185+
[42; 32],
12186+
holder_signer,
12187+
pubkeys,
12188+
&logger,
12189+
).unwrap();
12190+
12191+
// Clone it
12192+
let holder_signer2 = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12193+
let context_cloned = context.clone(holder_signer2);
12194+
12195+
// Compare some fields
12196+
assert_eq!(context_cloned.channel_value_satoshis, context.channel_value_satoshis);
12197+
assert_eq!(context_cloned.channel_id, context.channel_id);
12198+
assert_eq!(context_cloned.funding_tx_broadcast_safe_event_emitted, context.funding_tx_broadcast_safe_event_emitted);
12199+
assert_eq!(context_cloned.channel_keys_id, context.channel_keys_id);
12200+
}
1203512201
}

lightning/src/ln/channelmanager.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use crate::ln::inbound_payment;
4949
use crate::ln::types::ChannelId;
5050
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
5151
use crate::ln::channel::{self, Channel, ChannelPhase, ChannelError, ChannelUpdateStatus, ShutdownResult, UpdateFulfillCommitFetch, OutboundV1Channel, InboundV1Channel, WithChannelContext, InteractivelyFunded as _};
52-
#[cfg(any(dual_funding, splicing))]
52+
#[cfg(dual_funding)]
5353
use crate::ln::channel::InboundV2Channel;
5454
use crate::ln::channel_state::ChannelDetails;
5555
use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};

0 commit comments

Comments
 (0)