Skip to content

Commit 16311f9

Browse files
authored
Merge pull request #2382 from dunxen/2077-followups
Address outstanding 2077 feedback
2 parents 8a8f29a + 50a6d41 commit 16311f9

File tree

6 files changed

+329
-141
lines changed

6 files changed

+329
-141
lines changed

lightning/src/chain/onchaintx.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
11211121
}
11221122

11231123
//TODO: getting lastest holder transactions should be infallible and result in us "force-closing the channel", but we may
1124-
// have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
1124+
// have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after OutboundV1Channel::get_funding_created,
11251125
// before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
11261126
// to monitor before.
11271127
pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction {

lightning/src/events/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl_writeable_tlv_based_enum_upgradable!(PathFailure,
113113
);
114114

115115
#[derive(Clone, Debug, PartialEq, Eq)]
116-
/// The reason the channel was closed. See individual variants more details.
116+
/// The reason the channel was closed. See individual variants for more details.
117117
pub enum ClosureReason {
118118
/// Closure generated from receiving a peer error message.
119119
///
@@ -164,7 +164,10 @@ pub enum ClosureReason {
164164
///
165165
/// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
166166
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
167-
OutdatedChannelManager
167+
OutdatedChannelManager,
168+
/// The counterparty requested a cooperative close of a channel that had not been funded yet.
169+
/// The channel has been immediately closed.
170+
CounterpartyCoopClosedUnfundedChannel,
168171
}
169172

170173
impl core::fmt::Display for ClosureReason {
@@ -184,6 +187,7 @@ impl core::fmt::Display for ClosureReason {
184187
},
185188
ClosureReason::DisconnectedPeer => f.write_str("the peer disconnected prior to the channel being funded"),
186189
ClosureReason::OutdatedChannelManager => f.write_str("the ChannelManager read from disk was stale compared to ChannelMonitor(s)"),
190+
ClosureReason::CounterpartyCoopClosedUnfundedChannel => f.write_str("the peer requested the unfunded channel be closed"),
187191
}
188192
}
189193
}
@@ -197,6 +201,7 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
197201
(8, ProcessingError) => { (1, err, required) },
198202
(10, DisconnectedPeer) => {},
199203
(12, OutdatedChannelManager) => {},
204+
(13, CounterpartyCoopClosedUnfundedChannel) => {},
200205
);
201206

202207
/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`].

lightning/src/ln/channel.rs

+43-12
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,11 @@ pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;
590590
/// See [`ChannelContext::sent_message_awaiting_response`] for more information.
591591
pub(crate) const DISCONNECT_PEER_AWAITING_RESPONSE_TICKS: usize = 2;
592592

593+
/// The number of ticks that may elapse while we're waiting for an unfunded outbound/inbound channel
594+
/// to be promoted to a [`Channel`] since the unfunded channel was created. An unfunded channel
595+
/// exceeding this age limit will be force-closed and purged from memory.
596+
pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
597+
593598
struct PendingChannelMonitorUpdate {
594599
update: ChannelMonitorUpdate,
595600
}
@@ -598,6 +603,28 @@ impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
598603
(0, update, required),
599604
});
600605

606+
/// Contains all state common to unfunded inbound/outbound channels.
607+
pub(super) struct UnfundedChannelContext {
608+
/// A counter tracking how many ticks have elapsed since this unfunded channel was
609+
/// created. If this unfunded channel reaches peer has yet to respond after reaching
610+
/// `UNFUNDED_CHANNEL_AGE_LIMIT_TICKS`, it will be force-closed and purged from memory.
611+
///
612+
/// This is so that we don't keep channels around that haven't progressed to a funded state
613+
/// in a timely manner.
614+
unfunded_channel_age_ticks: usize,
615+
}
616+
617+
impl UnfundedChannelContext {
618+
/// Determines whether we should force-close and purge this unfunded channel from memory due to it
619+
/// having reached the unfunded channel age limit.
620+
///
621+
/// This should be called on every [`super::channelmanager::ChannelManager::timer_tick_occurred`].
622+
pub fn should_expire_unfunded_channel(&mut self) -> bool {
623+
self.unfunded_channel_age_ticks += 1;
624+
self.unfunded_channel_age_ticks >= UNFUNDED_CHANNEL_AGE_LIMIT_TICKS
625+
}
626+
}
627+
601628
/// Contains everything about the channel including state, and various flags.
602629
pub(super) struct ChannelContext<Signer: ChannelSigner> {
603630
config: LegacyChannelConfig,
@@ -995,7 +1022,7 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
9951022
}
9961023

9971024
/// Returns the funding_txo we either got from our peer, or were given by
998-
/// get_outbound_funding_created.
1025+
/// get_funding_created.
9991026
pub fn get_funding_txo(&self) -> Option<OutPoint> {
10001027
self.channel_transaction_parameters.funding_outpoint
10011028
}
@@ -1440,7 +1467,7 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
14401467
#[inline]
14411468
/// Creates a set of keys for build_commitment_transaction to generate a transaction which we
14421469
/// will sign and send to our counterparty.
1443-
/// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
1470+
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
14441471
fn build_remote_transaction_keys(&self) -> TxCreationKeys {
14451472
//TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we
14461473
//may see payments to it!
@@ -2026,7 +2053,7 @@ fn commit_tx_fee_msat(feerate_per_kw: u32, num_htlcs: usize, channel_type_featur
20262053

20272054
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
20282055
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
2029-
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
2056+
// calling channel_id() before we're set up or things like get_funding_signed on an
20302057
// inbound channel.
20312058
//
20322059
// Holder designates channel data owned for the benefit of the user client.
@@ -5477,6 +5504,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
54775504
/// A not-yet-funded outbound (from holder) channel using V1 channel establishment.
54785505
pub(super) struct OutboundV1Channel<Signer: ChannelSigner> {
54795506
pub context: ChannelContext<Signer>,
5507+
pub unfunded_context: UnfundedChannelContext,
54805508
}
54815509

54825510
impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
@@ -5678,12 +5706,13 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
56785706
channel_keys_id,
56795707

56805708
blocked_monitor_updates: Vec::new(),
5681-
}
5709+
},
5710+
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
56825711
})
56835712
}
56845713

5685-
/// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
5686-
fn get_outbound_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
5714+
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
5715+
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
56875716
let counterparty_keys = self.context.build_remote_transaction_keys();
56885717
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
56895718
Ok(self.context.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
@@ -5697,7 +5726,7 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
56975726
/// Note that channel_id changes during this call!
56985727
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
56995728
/// If an Err is returned, it is a ChannelError::Close.
5700-
pub fn get_outbound_funding_created<L: Deref>(mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L)
5729+
pub fn get_funding_created<L: Deref>(mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L)
57015730
-> Result<(Channel<Signer>, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger {
57025731
if !self.context.is_outbound() {
57035732
panic!("Tried to create outbound funding_created message on an inbound channel!");
@@ -5714,7 +5743,7 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
57145743
self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
57155744
self.context.holder_signer.provide_channel_parameters(&self.context.channel_transaction_parameters);
57165745

5717-
let signature = match self.get_outbound_funding_created_signature(logger) {
5746+
let signature = match self.get_funding_created_signature(logger) {
57185747
Ok(res) => res,
57195748
Err(e) => {
57205749
log_error!(logger, "Got bad signatures: {:?}!", e);
@@ -5983,6 +6012,7 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
59836012
/// A not-yet-funded inbound (from counterparty) channel using V1 channel establishment.
59846013
pub(super) struct InboundV1Channel<Signer: ChannelSigner> {
59856014
pub context: ChannelContext<Signer>,
6015+
pub unfunded_context: UnfundedChannelContext,
59866016
}
59876017

59886018
impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
@@ -6310,7 +6340,8 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
63106340
channel_keys_id,
63116341

63126342
blocked_monitor_updates: Vec::new(),
6313-
}
6343+
},
6344+
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
63146345
};
63156346

63166347
Ok(chan)
@@ -7598,7 +7629,7 @@ mod tests {
75987629
value: 10000000, script_pubkey: output_script.clone(),
75997630
}]};
76007631
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
7601-
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
7632+
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
76027633
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
76037634

76047635
// Node B --> Node A: funding signed
@@ -7725,7 +7756,7 @@ mod tests {
77257756
value: 10000000, script_pubkey: output_script.clone(),
77267757
}]};
77277758
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
7728-
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
7759+
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
77297760
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
77307761

77317762
// Node B --> Node A: funding signed
@@ -7913,7 +7944,7 @@ mod tests {
79137944
value: 10000000, script_pubkey: output_script.clone(),
79147945
}]};
79157946
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
7916-
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
7947+
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
79177948
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
79187949

79197950
// Node B --> Node A: funding signed

0 commit comments

Comments
 (0)