Skip to content

Commit e01356d

Browse files
committed
Clone for ChannelContext
1 parent 2010c72 commit e01356d

File tree

1 file changed

+172
-5
lines changed

1 file changed

+172
-5
lines changed

lightning/src/ln/channel.rs

Lines changed: 172 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ enum FeeUpdateState {
111111
Outbound,
112112
}
113113

114+
#[derive(Clone)]
114115
enum 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)]
148150
enum 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)]
222225
struct 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))]
231235
enum 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))]
313318
struct 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))]
326332
enum HTLCUpdateAwaitingACK {
327333
AddHTLC { // TODO: Time out if we're getting close to cltv_expiry
328334
// always outbound
@@ -800,7 +806,7 @@ pub(super) enum ChannelUpdateStatus {
800806
}
801807

802808
/// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here.
803-
#[derive(PartialEq)]
809+
#[derive(Clone, PartialEq)]
804810
pub enum AnnouncementSigsState {
805811
/// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since
806812
/// we sent the last `AnnouncementSignatures`.
@@ -1125,6 +1131,7 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
11251131
/// Number of blocks needed for an output from a coinbase transaction to be spendable.
11261132
pub(crate) const COINBASE_MATURITY: u32 = 100;
11271133

1134+
#[derive(Clone)]
11281135
struct PendingChannelMonitorUpdate {
11291136
update: ChannelMonitorUpdate,
11301137
}
@@ -4638,6 +4645,114 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
46384645
self.get_initial_counterparty_commitment_signature(logger)
46394646
}
46404647

4648+
/// Clone, each field, with a few exceptions, notably the channel signer, and
4649+
/// a few non-cloneable fields (such as Secp256k1 context)
4650+
#[allow(unused)]
4651+
fn clone(&self, holder_signer: <SP::Target as SignerProvider>::EcdsaSigner) -> Self {
4652+
Self {
4653+
config: self.config,
4654+
prev_config: self.prev_config,
4655+
inbound_handshake_limits_override: self.inbound_handshake_limits_override,
4656+
user_id: self.user_id,
4657+
channel_id: self.channel_id,
4658+
temporary_channel_id: self.temporary_channel_id,
4659+
channel_state: self.channel_state,
4660+
announcement_sigs_state: self.announcement_sigs_state.clone(),
4661+
// Create new Secp256k context
4662+
secp_ctx: Secp256k1::new(),
4663+
channel_value_satoshis: self.channel_value_satoshis,
4664+
latest_monitor_update_id: self.latest_monitor_update_id,
4665+
// Use provided channel signer
4666+
holder_signer: ChannelSignerType::Ecdsa(holder_signer),
4667+
shutdown_scriptpubkey: self.shutdown_scriptpubkey.clone(),
4668+
destination_script: self.destination_script.clone(),
4669+
// holder_commitment_point: self.holder_commitment_point,
4670+
cur_counterparty_commitment_transaction_number: self.cur_counterparty_commitment_transaction_number,
4671+
value_to_self_msat: self.value_to_self_msat,
4672+
pending_inbound_htlcs: self.pending_inbound_htlcs.clone(),
4673+
pending_outbound_htlcs: self.pending_outbound_htlcs.clone(),
4674+
holding_cell_htlc_updates: self.holding_cell_htlc_updates.clone(),
4675+
resend_order: self.resend_order.clone(),
4676+
monitor_pending_channel_ready: self.monitor_pending_channel_ready,
4677+
monitor_pending_revoke_and_ack: self.monitor_pending_revoke_and_ack,
4678+
monitor_pending_commitment_signed: self.monitor_pending_commitment_signed,
4679+
monitor_pending_forwards: self.monitor_pending_forwards.clone(),
4680+
monitor_pending_failures: self.monitor_pending_failures.clone(),
4681+
monitor_pending_finalized_fulfills: self.monitor_pending_finalized_fulfills.clone(),
4682+
monitor_pending_update_adds: self.monitor_pending_update_adds.clone(),
4683+
monitor_pending_tx_signatures: self.monitor_pending_tx_signatures.clone(),
4684+
signer_pending_revoke_and_ack: self.signer_pending_revoke_and_ack,
4685+
signer_pending_commitment_update: self.signer_pending_commitment_update,
4686+
signer_pending_funding: self.signer_pending_funding,
4687+
signer_pending_closing: self.signer_pending_closing,
4688+
signer_pending_channel_ready: self.signer_pending_channel_ready,
4689+
pending_update_fee: self.pending_update_fee,
4690+
holding_cell_update_fee: self.holding_cell_update_fee,
4691+
next_holder_htlc_id: self.next_holder_htlc_id,
4692+
next_counterparty_htlc_id: self.next_counterparty_htlc_id,
4693+
feerate_per_kw: self.feerate_per_kw,
4694+
update_time_counter: self.update_time_counter,
4695+
// Create new mutex with copied values
4696+
#[cfg(debug_assertions)]
4697+
holder_max_commitment_tx_output: Mutex::new(*self.holder_max_commitment_tx_output.lock().unwrap()),
4698+
#[cfg(debug_assertions)]
4699+
counterparty_max_commitment_tx_output: Mutex::new(*self.counterparty_max_commitment_tx_output.lock().unwrap()),
4700+
last_sent_closing_fee: self.last_sent_closing_fee.clone(),
4701+
last_received_closing_sig: self.last_received_closing_sig,
4702+
target_closing_feerate_sats_per_kw: self.target_closing_feerate_sats_per_kw,
4703+
pending_counterparty_closing_signed: self.pending_counterparty_closing_signed.clone(),
4704+
closing_fee_limits: self.closing_fee_limits,
4705+
expecting_peer_commitment_signed: self.expecting_peer_commitment_signed,
4706+
funding_tx_confirmed_in: self.funding_tx_confirmed_in,
4707+
funding_tx_confirmation_height: self.funding_tx_confirmation_height,
4708+
short_channel_id: self.short_channel_id,
4709+
channel_creation_height: self.channel_creation_height,
4710+
counterparty_dust_limit_satoshis: self.counterparty_dust_limit_satoshis,
4711+
holder_dust_limit_satoshis: self.holder_dust_limit_satoshis,
4712+
counterparty_max_htlc_value_in_flight_msat: self.counterparty_max_htlc_value_in_flight_msat,
4713+
holder_max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
4714+
counterparty_selected_channel_reserve_satoshis: self.counterparty_selected_channel_reserve_satoshis,
4715+
holder_selected_channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
4716+
counterparty_htlc_minimum_msat: self.counterparty_htlc_minimum_msat,
4717+
holder_htlc_minimum_msat: self.holder_htlc_minimum_msat,
4718+
counterparty_max_accepted_htlcs: self.counterparty_max_accepted_htlcs,
4719+
holder_max_accepted_htlcs: self.holder_max_accepted_htlcs,
4720+
minimum_depth: self.minimum_depth,
4721+
counterparty_forwarding_info: self.counterparty_forwarding_info.clone(),
4722+
channel_transaction_parameters: self.channel_transaction_parameters.clone(),
4723+
funding_transaction: self.funding_transaction.clone(),
4724+
is_manual_broadcast: self.is_manual_broadcast,
4725+
is_batch_funding: self.is_batch_funding,
4726+
counterparty_cur_commitment_point: self.counterparty_cur_commitment_point,
4727+
counterparty_prev_commitment_point: self.counterparty_prev_commitment_point,
4728+
counterparty_node_id: self.counterparty_node_id,
4729+
counterparty_shutdown_scriptpubkey: self.counterparty_shutdown_scriptpubkey.clone(),
4730+
commitment_secrets: self.commitment_secrets.clone(),
4731+
channel_update_status: self.channel_update_status,
4732+
closing_signed_in_flight: self.closing_signed_in_flight,
4733+
announcement_sigs: self.announcement_sigs,
4734+
// Create new mutex with copied values
4735+
#[cfg(any(test, fuzzing))]
4736+
next_local_commitment_tx_fee_info_cached: Mutex::new(self.next_local_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4737+
#[cfg(any(test, fuzzing))]
4738+
next_remote_commitment_tx_fee_info_cached: Mutex::new(self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().clone()),
4739+
workaround_lnd_bug_4006: self.workaround_lnd_bug_4006.clone(),
4740+
sent_message_awaiting_response: self.sent_message_awaiting_response,
4741+
#[cfg(any(test, fuzzing))]
4742+
historical_inbound_htlc_fulfills: self.historical_inbound_htlc_fulfills.clone(),
4743+
channel_type: self.channel_type.clone(),
4744+
latest_inbound_scid_alias: self.latest_inbound_scid_alias,
4745+
outbound_scid_alias: self.outbound_scid_alias,
4746+
channel_pending_event_emitted: self.channel_pending_event_emitted,
4747+
funding_tx_broadcast_safe_event_emitted: self.funding_tx_broadcast_safe_event_emitted,
4748+
channel_ready_event_emitted: self.channel_ready_event_emitted,
4749+
local_initiated_shutdown: self.local_initiated_shutdown.clone(),
4750+
channel_keys_id: self.channel_keys_id,
4751+
blocked_monitor_updates: self.blocked_monitor_updates.clone(),
4752+
next_funding_txid: self.next_funding_txid.clone(),
4753+
}
4754+
}
4755+
46414756
/// Splice process starting; update state, log, etc.
46424757
#[cfg(splicing)]
46434758
pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
@@ -4814,6 +4929,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
48144929
}
48154930

48164931
#[cfg(any(test, fuzzing))]
4932+
#[derive(Clone)]
48174933
struct CommitmentTxInfoCached {
48184934
fee: u64,
48194935
total_pending_htlcs: usize,
@@ -10911,7 +11027,7 @@ mod tests {
1091111027
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1091211028
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
1091311029
use crate::ln::channel::InitFeatures;
10914-
use crate::ln::channel::{AwaitingChannelReadyFlags, ChannelState, FundedChannel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
11030+
use crate::ln::channel::{AwaitingChannelReadyFlags, ChannelContext, ChannelState, FundedChannel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
1091511031
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
1091611032
use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
1091711033
use crate::ln::msgs;
@@ -12676,6 +12792,57 @@ mod tests {
1267612792
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1267712793
}
1267812794

12795+
#[test]
12796+
fn channel_context_clone() {
12797+
let fee_estimator = TestFeeEstimator {fee_est: 253 };
12798+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
12799+
let seed = [42; 32];
12800+
let network = Network::Testnet;
12801+
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
12802+
let secp_ctx = Secp256k1::new();
12803+
let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
12804+
let config = UserConfig::default();
12805+
12806+
let signer_provider: &TestKeysInterface = &&keys_provider;
12807+
let channel_value_satoshis = 10000000;
12808+
let user_id = 42;
12809+
let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
12810+
let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12811+
let logger = test_utils::TestLogger::new();
12812+
let pubkeys = holder_signer.pubkeys().clone();
12813+
12814+
// Create a context
12815+
let context = ChannelContext::<&TestKeysInterface>::new_for_outbound_channel(
12816+
&bounded_fee_estimator,
12817+
&&keys_provider,
12818+
&signer_provider,
12819+
node_a_node_id,
12820+
&channelmanager::provided_init_features(&config),
12821+
channel_value_satoshis,
12822+
100000,
12823+
user_id,
12824+
&config,
12825+
0,
12826+
42,
12827+
None,
12828+
100000,
12829+
[42; 32],
12830+
holder_signer,
12831+
pubkeys,
12832+
&logger,
12833+
).unwrap();
12834+
12835+
// Clone it
12836+
let holder_signer2 = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
12837+
let context_cloned = context.clone(holder_signer2);
12838+
12839+
// Compare some fields
12840+
assert_eq!(context_cloned.channel_value_satoshis, context.channel_value_satoshis);
12841+
assert_eq!(context_cloned.channel_id, context.channel_id);
12842+
assert_eq!(context_cloned.funding_tx_broadcast_safe_event_emitted, context.funding_tx_broadcast_safe_event_emitted);
12843+
assert_eq!(context_cloned.channel_keys_id, context.channel_keys_id);
12844+
}
12845+
1267912846
#[cfg(all(test, splicing))]
1268012847
fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
1268112848
use crate::ln::channel::PendingSplice;

0 commit comments

Comments
 (0)