@@ -590,6 +590,11 @@ pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;
590
590
/// See [`ChannelContext::sent_message_awaiting_response`] for more information.
591
591
pub(crate) const DISCONNECT_PEER_AWAITING_RESPONSE_TICKS: usize = 2;
592
592
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
+
593
598
struct PendingChannelMonitorUpdate {
594
599
update: ChannelMonitorUpdate,
595
600
}
@@ -598,6 +603,28 @@ impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
598
603
(0, update, required),
599
604
});
600
605
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
+
601
628
/// Contains everything about the channel including state, and various flags.
602
629
pub(super) struct ChannelContext<Signer: ChannelSigner> {
603
630
config: LegacyChannelConfig,
@@ -995,7 +1022,7 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
995
1022
}
996
1023
997
1024
/// Returns the funding_txo we either got from our peer, or were given by
998
- /// get_outbound_funding_created .
1025
+ /// get_funding_created .
999
1026
pub fn get_funding_txo(&self) -> Option<OutPoint> {
1000
1027
self.channel_transaction_parameters.funding_outpoint
1001
1028
}
@@ -1440,7 +1467,7 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
1440
1467
#[inline]
1441
1468
/// Creates a set of keys for build_commitment_transaction to generate a transaction which we
1442
1469
/// 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 )
1444
1471
fn build_remote_transaction_keys(&self) -> TxCreationKeys {
1445
1472
//TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we
1446
1473
//may see payments to it!
@@ -2026,7 +2053,7 @@ fn commit_tx_fee_msat(feerate_per_kw: u32, num_htlcs: usize, channel_type_featur
2026
2053
2027
2054
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
2028
2055
// 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
2030
2057
// inbound channel.
2031
2058
//
2032
2059
// Holder designates channel data owned for the benefit of the user client.
@@ -5477,6 +5504,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
5477
5504
/// A not-yet-funded outbound (from holder) channel using V1 channel establishment.
5478
5505
pub(super) struct OutboundV1Channel<Signer: ChannelSigner> {
5479
5506
pub context: ChannelContext<Signer>,
5507
+ pub unfunded_context: UnfundedChannelContext,
5480
5508
}
5481
5509
5482
5510
impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
@@ -5678,12 +5706,13 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
5678
5706
channel_keys_id,
5679
5707
5680
5708
blocked_monitor_updates: Vec::new(),
5681
- }
5709
+ },
5710
+ unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
5682
5711
})
5683
5712
}
5684
5713
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 {
5687
5716
let counterparty_keys = self.context.build_remote_transaction_keys();
5688
5717
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
5689
5718
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> {
5697
5726
/// Note that channel_id changes during this call!
5698
5727
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
5699
5728
/// 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)
5701
5730
-> Result<(Channel<Signer>, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger {
5702
5731
if !self.context.is_outbound() {
5703
5732
panic!("Tried to create outbound funding_created message on an inbound channel!");
@@ -5714,7 +5743,7 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
5714
5743
self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
5715
5744
self.context.holder_signer.provide_channel_parameters(&self.context.channel_transaction_parameters);
5716
5745
5717
- let signature = match self.get_outbound_funding_created_signature (logger) {
5746
+ let signature = match self.get_funding_created_signature (logger) {
5718
5747
Ok(res) => res,
5719
5748
Err(e) => {
5720
5749
log_error!(logger, "Got bad signatures: {:?}!", e);
@@ -5983,6 +6012,7 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
5983
6012
/// A not-yet-funded inbound (from counterparty) channel using V1 channel establishment.
5984
6013
pub(super) struct InboundV1Channel<Signer: ChannelSigner> {
5985
6014
pub context: ChannelContext<Signer>,
6015
+ pub unfunded_context: UnfundedChannelContext,
5986
6016
}
5987
6017
5988
6018
impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
@@ -6310,7 +6340,8 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
6310
6340
channel_keys_id,
6311
6341
6312
6342
blocked_monitor_updates: Vec::new(),
6313
- }
6343
+ },
6344
+ unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
6314
6345
};
6315
6346
6316
6347
Ok(chan)
@@ -7598,7 +7629,7 @@ mod tests {
7598
7629
value: 10000000, script_pubkey: output_script.clone(),
7599
7630
}]};
7600
7631
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();
7602
7633
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7603
7634
7604
7635
// Node B --> Node A: funding signed
@@ -7725,7 +7756,7 @@ mod tests {
7725
7756
value: 10000000, script_pubkey: output_script.clone(),
7726
7757
}]};
7727
7758
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();
7729
7760
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7730
7761
7731
7762
// Node B --> Node A: funding signed
@@ -7913,7 +7944,7 @@ mod tests {
7913
7944
value: 10000000, script_pubkey: output_script.clone(),
7914
7945
}]};
7915
7946
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();
7917
7948
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7918
7949
7919
7950
// Node B --> Node A: funding signed
0 commit comments