@@ -686,6 +686,43 @@ impl UnfundedChannelContext {
686686	}
687687}
688688
689+ /// Info about a transaction and its confirmation status, used mainly for funding transactions.
690+ pub(super) struct TransactionConfirmation {
691+ 	/// The transaction, or None.
692+ 	transaction: Option<Transaction>,
693+ 	/// The hash of the block in which the transaction was included, or None.
694+ 	confirmed_in: Option<BlockHash>,
695+ 	/// The height of the block in which the transaction was included, or 0.
696+ 	confirmation_height: u32,
697+ }
698+ 
699+ impl TransactionConfirmation {
700+ 	/// Construct with empty values
701+ 	fn default() -> Self {
702+ 		Self {
703+ 			transaction: None,
704+ 			confirmed_in: None,
705+ 			confirmation_height: 0,
706+ 		}
707+ 	}
708+ 
709+ 	/// Get the confirmation depth: height relative to the given current height.
710+ 	/// Also returns a flag indicating the special case when the confirmation is in the 'future'.
711+ 	/// If there is no confirmation height (it was not confirmed, or confirmed and reorged): (0, false)
712+ 	/// If the confirmation height is in the 'future' (e.g. due to a reorg): (0, true)
713+ 	/// Otherwise the result is height - confirmation_height + 1, a number always larger than 0.
714+ 	fn confirmation_depth(&self, current_height: u32) -> (u32, bool) {
715+ 		if self.confirmation_height == 0 {
716+ 			(0, false)
717+ 		} else {
718+ 			match current_height.checked_sub(self.confirmation_height) {
719+ 				None => (0, true),
720+ 				Some(d) => (d + 1, false),
721+ 			}
722+ 		}
723+ 	}
724+ }
725+ 
689726/// Contains everything about the channel including state, and various flags.
690727pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
691728	config: LegacyChannelConfig,
@@ -829,9 +866,6 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
829866	/// milliseconds, so any accidental force-closes here should be exceedingly rare.
830867	expecting_peer_commitment_signed: bool,
831868
832- 	/// The hash of the block in which the funding transaction was included.
833- 	funding_tx_confirmed_in: Option<BlockHash>,
834- 	funding_tx_confirmation_height: u32,
835869	short_channel_id: Option<u64>,
836870	/// Either the height at which this channel was created or the height at which it was last
837871	/// serialized if it was serialized by versions prior to 0.0.103.
@@ -875,7 +909,8 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
875909	counterparty_forwarding_info: Option<CounterpartyForwardingInfo>,
876910
877911	pub(crate) channel_transaction_parameters: ChannelTransactionParameters,
878- 	funding_transaction: Option<Transaction>,
912+ 	/// Info about the funding transaction and its confirmation status
913+ 	funding_tx_confirmation: TransactionConfirmation,
879914	is_batch_funding: Option<()>,
880915
881916	counterparty_cur_commitment_point: Option<PublicKey>,
@@ -1113,17 +1148,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
11131148
11141149	/// Returns the block hash in which our funding transaction was confirmed.
11151150	pub fn get_funding_tx_confirmed_in(&self) -> Option<BlockHash> {
1116- 		self.funding_tx_confirmed_in 
1151+ 		self.funding_tx_confirmation.confirmed_in 
11171152	}
11181153
11191154	/// Returns the current number of confirmations on the funding transaction.
11201155	pub fn get_funding_tx_confirmations(&self, height: u32) -> u32 {
1121- 		if self.funding_tx_confirmation_height == 0 {
1122- 			// We either haven't seen any confirmation yet, or observed a reorg.
1123- 			return 0;
1124- 		}
1125- 
1126- 		height.checked_sub(self.funding_tx_confirmation_height).map_or(0, |c| c + 1)
1156+ 		self.funding_tx_confirmation.confirmation_depth(height).0
11271157	}
11281158
11291159	fn get_holder_selected_contest_delay(&self) -> u16 {
@@ -2048,7 +2078,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
20482078	/// Returns the transaction if there is a pending funding transaction that is yet to be
20492079	/// broadcast.
20502080	pub fn unbroadcasted_funding(&self) -> Option<Transaction> {
2051- 		self.if_unbroadcasted_funding(|| self.funding_transaction .clone())
2081+ 		self.if_unbroadcasted_funding(|| self.funding_tx_confirmation.transaction .clone())
20522082	}
20532083
20542084	/// Returns the transaction ID if there is a pending funding transaction that is yet to be
@@ -3896,7 +3926,7 @@ impl<SP: Deref> Channel<SP> where
38963926		// first received the funding_signed.
38973927		let mut funding_broadcastable =
38983928			if self.context.is_outbound() && self.context.channel_state & !STATE_FLAGS >= ChannelState::FundingSent as u32 && self.context.channel_state & ChannelState::WaitingForBatch as u32 == 0 {
3899- 				self.context.funding_transaction .take()
3929+ 				self.context.funding_tx_confirmation.transaction .take()
39003930			} else { None };
39013931		// That said, if the funding transaction is already confirmed (ie we're active with a
39023932		// minimum_depth over 0) don't bother re-broadcasting the confirmed funding tx.
@@ -4885,7 +4915,7 @@ impl<SP: Deref> Channel<SP> where
48854915			// Because deciding we're awaiting initial broadcast spuriously could result in
48864916			// funds-loss (as we don't have a monitor, but have the funding transaction confirmed),
48874917			// we hard-assert here, even in production builds.
4888- 			if self.context.is_outbound() { assert!(self.context.funding_transaction .is_some()); }
4918+ 			if self.context.is_outbound() { assert!(self.context.funding_tx_confirmation.transaction .is_some()); }
48894919			assert!(self.context.monitor_pending_channel_ready);
48904920			assert_eq!(self.context.latest_monitor_update_id, 0);
48914921			return true;
@@ -4931,16 +4961,16 @@ impl<SP: Deref> Channel<SP> where
49314961		// Called:
49324962		//  * always when a new block/transactions are confirmed with the new height
49334963		//  * when funding is signed with a height of 0
4934- 		if self.context.funding_tx_confirmation_height  == 0 && self.context.minimum_depth != Some(0) {
4964+ 		if self.context.funding_tx_confirmation.confirmation_height  == 0 && self.context.minimum_depth != Some(0) {
49354965			return None;
49364966		}
49374967
4938- 		let funding_tx_confirmations = height as i64 -  self.context.funding_tx_confirmation_height as i64 + 1 ;
4939- 		if funding_tx_confirmations <= 0  {
4940- 			self.context.funding_tx_confirmation_height  = 0;
4968+ 		let ( funding_tx_confirmations, in_future) =  self.context.funding_tx_confirmation.confirmation_depth(height) ;
4969+ 		if in_future  {
4970+ 			self.context.funding_tx_confirmation.confirmation_height  = 0;
49414971		}
49424972
4943- 		if funding_tx_confirmations < self.context.minimum_depth.unwrap_or(0) as i64  {
4973+ 		if funding_tx_confirmations < self.context.minimum_depth.unwrap_or(0) {
49444974			return None;
49454975		}
49464976
@@ -4964,7 +4994,7 @@ impl<SP: Deref> Channel<SP> where
49644994			// We got a reorg but not enough to trigger a force close, just ignore.
49654995			false
49664996		} else {
4967- 			if self.context.funding_tx_confirmation_height  != 0 && self.context.channel_state & !STATE_FLAGS < ChannelState::ChannelReady as u32 {
4997+ 			if self.context.funding_tx_confirmation.confirmation_height  != 0 && self.context.channel_state & !STATE_FLAGS < ChannelState::ChannelReady as u32 {
49684998				// We should never see a funding transaction on-chain until we've received
49694999				// funding_signed (if we're an outbound channel), or seen funding_generated (if we're
49705000				// an inbound channel - before that we have no known funding TXID). The fuzzer,
@@ -5012,7 +5042,7 @@ impl<SP: Deref> Channel<SP> where
50125042			for &(index_in_block, tx) in txdata.iter() {
50135043				// Check if the transaction is the expected funding transaction, and if it is,
50145044				// check that it pays the right amount to the right script.
5015- 				if self.context.funding_tx_confirmation_height  == 0 {
5045+ 				if self.context.funding_tx_confirmation.confirmation_height  == 0 {
50165046					if tx.txid() == funding_txo.txid {
50175047						let txo_idx = funding_txo.index as usize;
50185048						if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_v0_p2wsh() ||
@@ -5042,8 +5072,8 @@ impl<SP: Deref> Channel<SP> where
50425072									}
50435073								}
50445074							}
5045- 							self.context.funding_tx_confirmation_height  = height;
5046- 							self.context.funding_tx_confirmed_in  = Some(*block_hash);
5075+ 							self.context.funding_tx_confirmation.confirmation_height  = height;
5076+ 							self.context.funding_tx_confirmation.confirmed_in  = Some(*block_hash);
50475077							self.context.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) {
50485078								Ok(scid) => Some(scid),
50495079								Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"),
@@ -5137,13 +5167,10 @@ impl<SP: Deref> Channel<SP> where
51375167		let non_shutdown_state = self.context.channel_state & (!MULTI_STATE_FLAGS);
51385168		if non_shutdown_state & !STATE_FLAGS >= ChannelState::ChannelReady as u32 ||
51395169		   (non_shutdown_state & ChannelState::OurChannelReady as u32) == ChannelState::OurChannelReady as u32 {
5140- 			let mut funding_tx_confirmations = height as i64 - self.context.funding_tx_confirmation_height as i64 + 1;
5141- 			if self.context.funding_tx_confirmation_height == 0 {
5142- 				// Note that check_get_channel_ready may reset funding_tx_confirmation_height to
5143- 				// zero if it has been reorged out, however in either case, our state flags
5144- 				// indicate we've already sent a channel_ready
5145- 				funding_tx_confirmations = 0;
5146- 			}
5170+ 			let (funding_tx_confirmations, _) = self.context.funding_tx_confirmation.confirmation_depth(height);
5171+ 			// Note that check_get_channel_ready may reset funding_tx_confirmation.confirmation_height to
5172+ 			// zero if it has been reorged out, however in either case, our state flags
5173+ 			// indicate we've already sent a channel_ready
51475174
51485175			// If we've sent channel_ready (or have both sent and received channel_ready), and
51495176			// the funding transaction has become unconfirmed,
@@ -5154,15 +5181,15 @@ impl<SP: Deref> Channel<SP> where
51545181			// 0-conf channel, but not doing so may lead to the
51555182			// `ChannelManager::short_to_chan_info` map  being inconsistent, so we currently have
51565183			// to.
5157- 			if funding_tx_confirmations == 0 && self.context.funding_tx_confirmed_in .is_some() {
5184+ 			if funding_tx_confirmations == 0 && self.context.funding_tx_confirmation.confirmed_in .is_some() {
51585185				let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.",
51595186					self.context.minimum_depth.unwrap(), funding_tx_confirmations);
51605187				return Err(ClosureReason::ProcessingError { err: err_reason });
51615188			}
5162- 		} else if !self.context.is_outbound() && self.context.funding_tx_confirmed_in .is_none() &&
5189+ 		} else if !self.context.is_outbound() && self.context.funding_tx_confirmation.confirmed_in .is_none() &&
51635190				height >= self.context.channel_creation_height + FUNDING_CONF_DEADLINE_BLOCKS {
51645191			log_info!(logger, "Closing channel {} due to funding timeout", &self.context.channel_id);
5165- 			// If funding_tx_confirmed_in  is unset, the channel must not be active
5192+ 			// If funding_tx_confirmation.confirmed_in  is unset, the channel must not be active
51665193			assert!(non_shutdown_state & !STATE_FLAGS <= ChannelState::ChannelReady as u32);
51675194			assert_eq!(non_shutdown_state & ChannelState::OurChannelReady as u32, 0);
51685195			return Err(ClosureReason::FundingTimedOut);
@@ -5178,10 +5205,10 @@ impl<SP: Deref> Channel<SP> where
51785205	/// force-close the channel, but may also indicate a harmless reorganization of a block or two
51795206	/// before the channel has reached channel_ready and we can just wait for more blocks.
51805207	pub fn funding_transaction_unconfirmed<L: Deref>(&mut self, logger: &L) -> Result<(), ClosureReason> where L::Target: Logger {
5181- 		if self.context.funding_tx_confirmation_height !=  0 {
5208+ 		if self.context.funding_tx_confirmation.confirmation_height >  0 {
51825209			// We handle the funding disconnection by calling best_block_updated with a height one
51835210			// below where our funding was connected, implying a reorg back to conf_height - 1.
5184- 			let reorg_height = self.context.funding_tx_confirmation_height  - 1;
5211+ 			let reorg_height = self.context.funding_tx_confirmation.confirmation_height  - 1;
51855212			// We use the time field to bump the current time we set on channel updates if its
51865213			// larger. If we don't know that time has moved forward, we can just set it to the last
51875214			// time we saw and it will be ignored.
@@ -5254,7 +5281,7 @@ impl<SP: Deref> Channel<SP> where
52545281		NS::Target: NodeSigner,
52555282		L::Target: Logger
52565283	{
5257- 		if self.context.funding_tx_confirmation_height  == 0 || self.context.funding_tx_confirmation_height  + 5 > best_block_height {
5284+ 		if self.context.funding_tx_confirmation.confirmation_height  == 0 || self.context.funding_tx_confirmation.confirmation_height  + 5 > best_block_height {
52585285			return None;
52595286		}
52605287
@@ -5365,7 +5392,7 @@ impl<SP: Deref> Channel<SP> where
53655392		}
53665393
53675394		self.context.announcement_sigs = Some((msg.node_signature, msg.bitcoin_signature));
5368- 		if self.context.funding_tx_confirmation_height  == 0 || self.context.funding_tx_confirmation_height  + 5 > best_block_height {
5395+ 		if self.context.funding_tx_confirmation.confirmation_height  == 0 || self.context.funding_tx_confirmation.confirmation_height  + 5 > best_block_height {
53695396			return Err(ChannelError::Ignore(
53705397				"Got announcement_signatures prior to the required six confirmations - we may not have received a block yet that our peer has".to_owned()));
53715398		}
@@ -5378,7 +5405,7 @@ impl<SP: Deref> Channel<SP> where
53785405	pub fn get_signed_channel_announcement<NS: Deref>(
53795406		&self, node_signer: &NS, chain_hash: ChainHash, best_block_height: u32, user_config: &UserConfig
53805407	) -> Option<msgs::ChannelAnnouncement> where NS::Target: NodeSigner {
5381- 		if self.context.funding_tx_confirmation_height  == 0 || self.context.funding_tx_confirmation_height  + 5 > best_block_height {
5408+ 		if self.context.funding_tx_confirmation.confirmation_height  == 0 || self.context.funding_tx_confirmation.confirmation_height  + 5 > best_block_height {
53825409			return None;
53835410		}
53845411		let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) {
@@ -6020,8 +6047,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
60206047				closing_fee_limits: None,
60216048				target_closing_feerate_sats_per_kw: None,
60226049
6023- 				funding_tx_confirmed_in: None,
6024- 				funding_tx_confirmation_height: 0,
60256050				short_channel_id: None,
60266051				channel_creation_height: current_chain_height,
60276052
@@ -6048,7 +6073,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
60486073					funding_outpoint: None,
60496074					channel_type_features: channel_type.clone()
60506075				},
6051- 				funding_transaction: None ,
6076+ 				funding_tx_confirmation: TransactionConfirmation::default() ,
60526077				is_batch_funding: None,
60536078
60546079				counterparty_cur_commitment_point: None,
@@ -6127,7 +6152,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
61276152			self.context.minimum_depth = Some(COINBASE_MATURITY);
61286153		}
61296154
6130- 		self.context.funding_transaction  = Some(funding_transaction);
6155+ 		self.context.funding_tx_confirmation.transaction  = Some(funding_transaction);
61316156		self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding);
61326157
61336158		let funding_created = self.context.get_funding_created_msg(logger);
@@ -6653,8 +6678,6 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
66536678				closing_fee_limits: None,
66546679				target_closing_feerate_sats_per_kw: None,
66556680
6656- 				funding_tx_confirmed_in: None,
6657- 				funding_tx_confirmation_height: 0,
66586681				short_channel_id: None,
66596682				channel_creation_height: current_chain_height,
66606683
@@ -6685,7 +6708,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
66856708					funding_outpoint: None,
66866709					channel_type_features: channel_type.clone()
66876710				},
6688- 				funding_transaction: None ,
6711+ 				funding_tx_confirmation: TransactionConfirmation::default() ,
66896712				is_batch_funding: None,
66906713
66916714				counterparty_cur_commitment_point: Some(msg.first_per_commitment_point),
@@ -7162,8 +7185,8 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
71627185		// consider the stale state on reload.
71637186		0u8.write(writer)?;
71647187
7165- 		self.context.funding_tx_confirmed_in .write(writer)?;
7166- 		self.context.funding_tx_confirmation_height .write(writer)?;
7188+ 		self.context.funding_tx_confirmation.confirmed_in .write(writer)?;
7189+ 		self.context.funding_tx_confirmation.confirmation_height .write(writer)?;
71677190		self.context.short_channel_id.write(writer)?;
71687191
71697192		self.context.counterparty_dust_limit_satoshis.write(writer)?;
@@ -7191,7 +7214,7 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
71917214		}
71927215
71937216		self.context.channel_transaction_parameters.write(writer)?;
7194- 		self.context.funding_transaction .write(writer)?;
7217+ 		self.context.funding_tx_confirmation.transaction .write(writer)?;
71957218
71967219		self.context.counterparty_cur_commitment_point.write(writer)?;
71977220		self.context.counterparty_prev_commitment_point.write(writer)?;
@@ -7725,8 +7748,6 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
77257748				closing_fee_limits: None,
77267749				target_closing_feerate_sats_per_kw,
77277750
7728- 				funding_tx_confirmed_in,
7729- 				funding_tx_confirmation_height,
77307751				short_channel_id,
77317752				channel_creation_height: channel_creation_height.unwrap(),
77327753
@@ -7744,7 +7765,11 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
77447765				counterparty_forwarding_info,
77457766
77467767				channel_transaction_parameters: channel_parameters,
7747- 				funding_transaction,
7768+ 				funding_tx_confirmation: TransactionConfirmation {
7769+ 					transaction: funding_transaction,
7770+ 					confirmed_in: funding_tx_confirmed_in,
7771+ 					confirmation_height: funding_tx_confirmation_height,
7772+ 				},
77487773				is_batch_funding,
77497774
77507775				counterparty_cur_commitment_point,
@@ -7799,7 +7824,7 @@ mod tests {
77997824	use crate::ln::PaymentHash;
78007825	use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
78017826	use crate::ln::channel::InitFeatures;
7802- 	use crate::ln::channel::{ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat};
7827+ 	use crate::ln::channel::{ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, TransactionConfirmation,  commit_tx_fee_msat};
78037828	use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
78047829	use crate::ln::features::ChannelTypeFeatures;
78057830	use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
@@ -7841,6 +7866,26 @@ mod tests {
78417866		        "MAX_FUNDING_SATOSHIS_NO_WUMBO is greater than all satoshis in existence");
78427867	}
78437868
7869+ 	#[test]
7870+ 	fn test_transaction_confirmation_depth() {
7871+ 		{
7872+ 			let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 0 };
7873+ 			assert_eq!(tx_conf.confirmation_depth(42), (0, false));
7874+ 		}
7875+ 		{
7876+ 			let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 100005 };
7877+ 			assert_eq!(tx_conf.confirmation_depth(100008), (4, false));
7878+ 		}
7879+ 		{
7880+ 			let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 100005 };
7881+ 			assert_eq!(tx_conf.confirmation_depth(100005), (1, false));
7882+ 		}
7883+ 		{
7884+ 			// confirmation_height is larger than current, 'in the future'
7885+ 			let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 100005 };
7886+ 			assert_eq!(tx_conf.confirmation_depth(100000), (0, true));
7887+ 		}
7888+ 	}
78447889	struct Keys {
78457890		signer: InMemorySigner,
78467891	}
0 commit comments