From 11bbc0154a7378c760cd2e4934199fead901b8fb Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Fri, 17 Nov 2023 23:41:15 +0100 Subject: [PATCH] Refactor channel funding transaction fields --- lightning/src/ln/channel.rs | 244 +++++++++++++++++----- lightning/src/ln/priv_short_conf_tests.rs | 4 +- lightning/src/ln/reorg_tests.rs | 4 +- 3 files changed, 191 insertions(+), 61 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index f499127bc36..b9c8a8e1138 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -686,6 +686,79 @@ impl UnfundedChannelContext { } } +/// Info about a transaction and its confirmation status, used mainly for funding transactions. +#[derive(Default)] +struct TransactionConfirmation { + /// The transaction, or None. + transaction: Option, + /// The hash of the block in which the transaction was included, or None. + confirmed_in: Option, + /// The height of the block in which the transaction was included, or 0. + confirmation_height: u32, +} + +/// Confirmation depth: height relative to a current height. +#[derive(Debug, PartialEq)] +enum RelativeConfirmationDepth { + /// If fhere is no confirmation height (it was not confirmed, or confirmed then reorg'd). + Unconfirmed, + /// Confirmed by N blokcks, current_height - confirmation_height + 1; a number always larger than 0. + Confirmed(u32), + /// If the confirmation height is in the 'future' (e.g. due to a reorg). + ConfirmedInFuture, +} + +impl RelativeConfirmationDepth { + /// Check if confirmed + fn is_confirmed(&self) -> bool { + matches!(self, Self::Confirmed(_d)) + } + + /// Check if confirmed for a desired mimimum depth + fn is_confirmed_for(&self, min_depth: Option) -> bool { + match min_depth { + None => { + // min depth is unset + false + }, + Some(min_depth) => { + if min_depth == 0 { + // confirmation not needed + true + } else { + if let Self::Confirmed(depth) = self { + *depth >= min_depth + } else { + false + } + } + } + } + } + + /// Return a single number: the depth, or 0 for unconfirmed (or confirmed in future) + fn num(&self) -> u32 { + match self { + Self::Unconfirmed | Self::ConfirmedInFuture => 0, + Self::Confirmed(d) => *d, + } + } +} + +impl TransactionConfirmation { + /// Get the confirmation depth: height relative to the given current height. + fn confirmation_depth(&self, current_height: u32) -> RelativeConfirmationDepth { + if self.confirmation_height == 0 { + RelativeConfirmationDepth::Unconfirmed + } else { + match current_height.checked_sub(self.confirmation_height) { + None => RelativeConfirmationDepth::ConfirmedInFuture, + Some(d) => RelativeConfirmationDepth::Confirmed(d + 1), + } + } + } +} + /// Contains everything about the channel including state, and various flags. pub(super) struct ChannelContext where SP::Target: SignerProvider { config: LegacyChannelConfig, @@ -829,9 +902,6 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { /// milliseconds, so any accidental force-closes here should be exceedingly rare. expecting_peer_commitment_signed: bool, - /// The hash of the block in which the funding transaction was included. - funding_tx_confirmed_in: Option, - funding_tx_confirmation_height: u32, short_channel_id: Option, /// Either the height at which this channel was created or the height at which it was last /// serialized if it was serialized by versions prior to 0.0.103. @@ -875,7 +945,8 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { counterparty_forwarding_info: Option, pub(crate) channel_transaction_parameters: ChannelTransactionParameters, - funding_transaction: Option, + /// Info about the funding transaction and its confirmation status + funding_tx_confirmation: TransactionConfirmation, is_batch_funding: Option<()>, counterparty_cur_commitment_point: Option, @@ -1113,17 +1184,12 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns the block hash in which our funding transaction was confirmed. pub fn get_funding_tx_confirmed_in(&self) -> Option { - self.funding_tx_confirmed_in + self.funding_tx_confirmation.confirmed_in } /// Returns the current number of confirmations on the funding transaction. pub fn get_funding_tx_confirmations(&self, height: u32) -> u32 { - if self.funding_tx_confirmation_height == 0 { - // We either haven't seen any confirmation yet, or observed a reorg. - return 0; - } - - height.checked_sub(self.funding_tx_confirmation_height).map_or(0, |c| c + 1) + self.funding_tx_confirmation.confirmation_depth(height).num() } fn get_holder_selected_contest_delay(&self) -> u16 { @@ -2048,7 +2114,7 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns the transaction if there is a pending funding transaction that is yet to be /// broadcast. pub fn unbroadcasted_funding(&self) -> Option { - self.if_unbroadcasted_funding(|| self.funding_transaction.clone()) + self.if_unbroadcasted_funding(|| self.funding_tx_confirmation.transaction.clone()) } /// Returns the transaction ID if there is a pending funding transaction that is yet to be @@ -3896,7 +3962,7 @@ impl Channel where // first received the funding_signed. let mut funding_broadcastable = if self.context.is_outbound() && self.context.channel_state & !STATE_FLAGS >= ChannelState::FundingSent as u32 && self.context.channel_state & ChannelState::WaitingForBatch as u32 == 0 { - self.context.funding_transaction.take() + self.context.funding_tx_confirmation.transaction.take() } else { None }; // That said, if the funding transaction is already confirmed (ie we're active with a // minimum_depth over 0) don't bother re-broadcasting the confirmed funding tx. @@ -4885,7 +4951,7 @@ impl Channel where // Because deciding we're awaiting initial broadcast spuriously could result in // funds-loss (as we don't have a monitor, but have the funding transaction confirmed), // we hard-assert here, even in production builds. - if self.context.is_outbound() { assert!(self.context.funding_transaction.is_some()); } + if self.context.is_outbound() { assert!(self.context.funding_tx_confirmation.transaction.is_some()); } assert!(self.context.monitor_pending_channel_ready); assert_eq!(self.context.latest_monitor_update_id, 0); return true; @@ -4931,16 +4997,14 @@ impl Channel where // Called: // * always when a new block/transactions are confirmed with the new height // * when funding is signed with a height of 0 - if self.context.funding_tx_confirmation_height == 0 && self.context.minimum_depth != Some(0) { - return None; - } - let funding_tx_confirmations = height as i64 - self.context.funding_tx_confirmation_height as i64 + 1; - if funding_tx_confirmations <= 0 { - self.context.funding_tx_confirmation_height = 0; + // Check confirmation status + let confirmation_depth = self.context.funding_tx_confirmation.confirmation_depth(height); + if confirmation_depth == RelativeConfirmationDepth::ConfirmedInFuture { + // reset to unconfirmed + self.context.funding_tx_confirmation.confirmation_height = 0; } - - if funding_tx_confirmations < self.context.minimum_depth.unwrap_or(0) as i64 { + if !confirmation_depth.is_confirmed_for(self.context.minimum_depth) { return None; } @@ -4964,7 +5028,7 @@ impl Channel where // We got a reorg but not enough to trigger a force close, just ignore. false } else { - if self.context.funding_tx_confirmation_height != 0 && self.context.channel_state & !STATE_FLAGS < ChannelState::ChannelReady as u32 { + if self.context.funding_tx_confirmation.confirmation_height != 0 && self.context.channel_state & !STATE_FLAGS < ChannelState::ChannelReady as u32 { // We should never see a funding transaction on-chain until we've received // funding_signed (if we're an outbound channel), or seen funding_generated (if we're // an inbound channel - before that we have no known funding TXID). The fuzzer, @@ -5012,7 +5076,7 @@ impl Channel where for &(index_in_block, tx) in txdata.iter() { // Check if the transaction is the expected funding transaction, and if it is, // check that it pays the right amount to the right script. - if self.context.funding_tx_confirmation_height == 0 { + if self.context.funding_tx_confirmation.confirmation_height == 0 { if tx.txid() == funding_txo.txid { let txo_idx = funding_txo.index as usize; if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_v0_p2wsh() || @@ -5042,8 +5106,8 @@ impl Channel where } } } - self.context.funding_tx_confirmation_height = height; - self.context.funding_tx_confirmed_in = Some(*block_hash); + self.context.funding_tx_confirmation.confirmation_height = height; + self.context.funding_tx_confirmation.confirmed_in = Some(*block_hash); self.context.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) { Ok(scid) => Some(scid), Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"), @@ -5137,13 +5201,10 @@ impl Channel where let non_shutdown_state = self.context.channel_state & (!MULTI_STATE_FLAGS); if non_shutdown_state & !STATE_FLAGS >= ChannelState::ChannelReady as u32 || (non_shutdown_state & ChannelState::OurChannelReady as u32) == ChannelState::OurChannelReady as u32 { - let mut funding_tx_confirmations = height as i64 - self.context.funding_tx_confirmation_height as i64 + 1; - if self.context.funding_tx_confirmation_height == 0 { - // Note that check_get_channel_ready may reset funding_tx_confirmation_height to - // zero if it has been reorged out, however in either case, our state flags - // indicate we've already sent a channel_ready - funding_tx_confirmations = 0; - } + let confirmation_depth = self.context.funding_tx_confirmation.confirmation_depth(height); + // Note that check_get_channel_ready may reset funding_tx_confirmation.confirmation_height to + // zero if it has been reorged out, however in either case, our state flags + // indicate we've already sent a channel_ready // If we've sent channel_ready (or have both sent and received channel_ready), and // the funding transaction has become unconfirmed, @@ -5154,15 +5215,15 @@ impl Channel where // 0-conf channel, but not doing so may lead to the // `ChannelManager::short_to_chan_info` map being inconsistent, so we currently have // to. - if funding_tx_confirmations == 0 && self.context.funding_tx_confirmed_in.is_some() { - let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.", - self.context.minimum_depth.unwrap(), funding_tx_confirmations); + if !confirmation_depth.is_confirmed() && self.context.funding_tx_confirmation.confirmed_in.is_some() { + let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {:?} confs.", + self.context.minimum_depth.unwrap(), confirmation_depth); return Err(ClosureReason::ProcessingError { err: err_reason }); } - } else if !self.context.is_outbound() && self.context.funding_tx_confirmed_in.is_none() && + } else if !self.context.is_outbound() && self.context.funding_tx_confirmation.confirmed_in.is_none() && height >= self.context.channel_creation_height + FUNDING_CONF_DEADLINE_BLOCKS { log_info!(logger, "Closing channel {} due to funding timeout", &self.context.channel_id); - // If funding_tx_confirmed_in is unset, the channel must not be active + // If funding_tx_confirmation.confirmed_in is unset, the channel must not be active assert!(non_shutdown_state & !STATE_FLAGS <= ChannelState::ChannelReady as u32); assert_eq!(non_shutdown_state & ChannelState::OurChannelReady as u32, 0); return Err(ClosureReason::FundingTimedOut); @@ -5178,10 +5239,10 @@ impl Channel where /// force-close the channel, but may also indicate a harmless reorganization of a block or two /// before the channel has reached channel_ready and we can just wait for more blocks. pub fn funding_transaction_unconfirmed(&mut self, logger: &L) -> Result<(), ClosureReason> where L::Target: Logger { - if self.context.funding_tx_confirmation_height != 0 { + if self.context.funding_tx_confirmation.confirmation_height > 0 { // We handle the funding disconnection by calling best_block_updated with a height one // below where our funding was connected, implying a reorg back to conf_height - 1. - let reorg_height = self.context.funding_tx_confirmation_height - 1; + let reorg_height = self.context.funding_tx_confirmation.confirmation_height - 1; // We use the time field to bump the current time we set on channel updates if its // larger. If we don't know that time has moved forward, we can just set it to the last // time we saw and it will be ignored. @@ -5254,7 +5315,7 @@ impl Channel where NS::Target: NodeSigner, L::Target: Logger { - if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height { + if self.context.funding_tx_confirmation.confirmation_height == 0 || self.context.funding_tx_confirmation.confirmation_height + 5 > best_block_height { return None; } @@ -5365,7 +5426,7 @@ impl Channel where } self.context.announcement_sigs = Some((msg.node_signature, msg.bitcoin_signature)); - if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height { + if self.context.funding_tx_confirmation.confirmation_height == 0 || self.context.funding_tx_confirmation.confirmation_height + 5 > best_block_height { return Err(ChannelError::Ignore( "Got announcement_signatures prior to the required six confirmations - we may not have received a block yet that our peer has".to_owned())); } @@ -5378,7 +5439,7 @@ impl Channel where pub fn get_signed_channel_announcement( &self, node_signer: &NS, chain_hash: ChainHash, best_block_height: u32, user_config: &UserConfig ) -> Option where NS::Target: NodeSigner { - if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height { + if self.context.funding_tx_confirmation.confirmation_height == 0 || self.context.funding_tx_confirmation.confirmation_height + 5 > best_block_height { return None; } let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) { @@ -6020,8 +6081,6 @@ impl OutboundV1Channel where SP::Target: SignerProvider { closing_fee_limits: None, target_closing_feerate_sats_per_kw: None, - funding_tx_confirmed_in: None, - funding_tx_confirmation_height: 0, short_channel_id: None, channel_creation_height: current_chain_height, @@ -6048,7 +6107,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { funding_outpoint: None, channel_type_features: channel_type.clone() }, - funding_transaction: None, + funding_tx_confirmation: TransactionConfirmation::default(), is_batch_funding: None, counterparty_cur_commitment_point: None, @@ -6127,7 +6186,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { self.context.minimum_depth = Some(COINBASE_MATURITY); } - self.context.funding_transaction = Some(funding_transaction); + self.context.funding_tx_confirmation.transaction = Some(funding_transaction); self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding); let funding_created = self.context.get_funding_created_msg(logger); @@ -6653,8 +6712,6 @@ impl InboundV1Channel where SP::Target: SignerProvider { closing_fee_limits: None, target_closing_feerate_sats_per_kw: None, - funding_tx_confirmed_in: None, - funding_tx_confirmation_height: 0, short_channel_id: None, channel_creation_height: current_chain_height, @@ -6685,7 +6742,7 @@ impl InboundV1Channel where SP::Target: SignerProvider { funding_outpoint: None, channel_type_features: channel_type.clone() }, - funding_transaction: None, + funding_tx_confirmation: TransactionConfirmation::default(), is_batch_funding: None, counterparty_cur_commitment_point: Some(msg.first_per_commitment_point), @@ -7162,8 +7219,8 @@ impl Writeable for Channel where SP::Target: SignerProvider { // consider the stale state on reload. 0u8.write(writer)?; - self.context.funding_tx_confirmed_in.write(writer)?; - self.context.funding_tx_confirmation_height.write(writer)?; + self.context.funding_tx_confirmation.confirmed_in.write(writer)?; + self.context.funding_tx_confirmation.confirmation_height.write(writer)?; self.context.short_channel_id.write(writer)?; self.context.counterparty_dust_limit_satoshis.write(writer)?; @@ -7191,7 +7248,7 @@ impl Writeable for Channel where SP::Target: SignerProvider { } self.context.channel_transaction_parameters.write(writer)?; - self.context.funding_transaction.write(writer)?; + self.context.funding_tx_confirmation.transaction.write(writer)?; self.context.counterparty_cur_commitment_point.write(writer)?; self.context.counterparty_prev_commitment_point.write(writer)?; @@ -7725,8 +7782,6 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch closing_fee_limits: None, target_closing_feerate_sats_per_kw, - funding_tx_confirmed_in, - funding_tx_confirmation_height, short_channel_id, channel_creation_height: channel_creation_height.unwrap(), @@ -7744,7 +7799,11 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch counterparty_forwarding_info, channel_transaction_parameters: channel_parameters, - funding_transaction, + funding_tx_confirmation: TransactionConfirmation { + transaction: funding_transaction, + confirmed_in: funding_tx_confirmed_in, + confirmation_height: funding_tx_confirmation_height, + }, is_batch_funding, counterparty_cur_commitment_point, @@ -7799,7 +7858,7 @@ mod tests { use crate::ln::PaymentHash; use crate::ln::channelmanager::{self, HTLCSource, PaymentId}; use crate::ln::channel::InitFeatures; - use crate::ln::channel::{ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat}; + use crate::ln::channel::{ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, RelativeConfirmationDepth, TransactionConfirmation, commit_tx_fee_msat}; use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS}; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT}; @@ -7841,6 +7900,77 @@ mod tests { "MAX_FUNDING_SATOSHIS_NO_WUMBO is greater than all satoshis in existence"); } + #[test] + fn test_transaction_confirmation_depth() { + { + let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 0 }; + assert_eq!(tx_conf.confirmation_depth(42), RelativeConfirmationDepth::Unconfirmed); + } + { + let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 100005 }; + assert_eq!(tx_conf.confirmation_depth(100008), RelativeConfirmationDepth::Confirmed(4)); + } + { + let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 100005 }; + assert_eq!(tx_conf.confirmation_depth(100005), RelativeConfirmationDepth::Confirmed(1)); + } + { + // confirmation_height is larger than current, 'in the future' + let tx_conf = TransactionConfirmation { transaction: None, confirmed_in: None, confirmation_height: 100005 }; + assert_eq!(tx_conf.confirmation_depth(100000), RelativeConfirmationDepth::ConfirmedInFuture); + } + } + + #[test] + fn test_relative_confirmation_height_is_confirmed() { + assert_eq!(RelativeConfirmationDepth::Confirmed(3).is_confirmed(), true); + assert_eq!(RelativeConfirmationDepth::Unconfirmed.is_confirmed(), false); + assert_eq!(RelativeConfirmationDepth::ConfirmedInFuture.is_confirmed(), false); + } + + #[test] + fn test_relative_confirmation_height_is_confirmed_for() { + { + assert_eq!(RelativeConfirmationDepth::Confirmed(1).is_confirmed_for(Some(3)), false); + assert_eq!(RelativeConfirmationDepth::Confirmed(2).is_confirmed_for(Some(3)), false); + assert_eq!(RelativeConfirmationDepth::Confirmed(3).is_confirmed_for(Some(3)), true); + assert_eq!(RelativeConfirmationDepth::Confirmed(4).is_confirmed_for(Some(3)), true); + assert_eq!(RelativeConfirmationDepth::Unconfirmed.is_confirmed_for(Some(3)), false); + assert_eq!(RelativeConfirmationDepth::ConfirmedInFuture.is_confirmed_for(Some(3)), false); + } + { + assert_eq!(RelativeConfirmationDepth::Confirmed(1).is_confirmed_for(Some(1)), true); + assert_eq!(RelativeConfirmationDepth::Confirmed(2).is_confirmed_for(Some(1)), true); + assert_eq!(RelativeConfirmationDepth::Confirmed(3).is_confirmed_for(Some(1)), true); + assert_eq!(RelativeConfirmationDepth::Confirmed(4).is_confirmed_for(Some(1)), true); + assert_eq!(RelativeConfirmationDepth::Unconfirmed.is_confirmed_for(Some(1)), false); + assert_eq!(RelativeConfirmationDepth::ConfirmedInFuture.is_confirmed_for(Some(1)), false); + } + { + assert_eq!(RelativeConfirmationDepth::Confirmed(1).is_confirmed_for(Some(0)), true); + assert_eq!(RelativeConfirmationDepth::Confirmed(2).is_confirmed_for(Some(0)), true); + assert_eq!(RelativeConfirmationDepth::Confirmed(3).is_confirmed_for(Some(0)), true); + assert_eq!(RelativeConfirmationDepth::Confirmed(4).is_confirmed_for(Some(0)), true); + assert_eq!(RelativeConfirmationDepth::Unconfirmed.is_confirmed_for(Some(0)), true); + assert_eq!(RelativeConfirmationDepth::ConfirmedInFuture.is_confirmed_for(Some(0)), true); + } + { + assert_eq!(RelativeConfirmationDepth::Confirmed(1).is_confirmed_for(None), false); + assert_eq!(RelativeConfirmationDepth::Confirmed(2).is_confirmed_for(None), false); + assert_eq!(RelativeConfirmationDepth::Confirmed(3).is_confirmed_for(None), false); + assert_eq!(RelativeConfirmationDepth::Confirmed(4).is_confirmed_for(None), false); + assert_eq!(RelativeConfirmationDepth::Unconfirmed.is_confirmed_for(None), false); + assert_eq!(RelativeConfirmationDepth::ConfirmedInFuture.is_confirmed_for(None), false); + } + } + + #[test] + fn test_relative_confirmation_height_num() { + assert_eq!(RelativeConfirmationDepth::Confirmed(3).num(), 3); + assert_eq!(RelativeConfirmationDepth::Unconfirmed.num(), 0); + assert_eq!(RelativeConfirmationDepth::ConfirmedInFuture.num(), 0); + } + struct Keys { signer: InMemorySigner, } diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index 85e757204fe..ddab19617ae 100644 --- a/lightning/src/ln/priv_short_conf_tests.rs +++ b/lightning/src/ln/priv_short_conf_tests.rs @@ -860,12 +860,12 @@ fn test_0conf_channel_reorg() { // support simply un-setting the SCID and waiting until the channel gets re-confirmed, but for // now we force-close the channel here. check_closed_event!(&nodes[0], 1, ClosureReason::ProcessingError { - err: "Funding transaction was un-confirmed. Locked at 0 confs, now have 0 confs.".to_owned() + err: "Funding transaction was un-confirmed. Locked at 0 confs, now have Unconfirmed confs.".to_owned() }, [nodes[1].node.get_our_node_id()], 100000); check_closed_broadcast!(nodes[0], true); check_added_monitors(&nodes[0], 1); check_closed_event!(&nodes[1], 1, ClosureReason::ProcessingError { - err: "Funding transaction was un-confirmed. Locked at 0 confs, now have 0 confs.".to_owned() + err: "Funding transaction was un-confirmed. Locked at 0 confs, now have Unconfirmed confs.".to_owned() }, [nodes[0].node.get_our_node_id()], 100000); check_closed_broadcast!(nodes[1], true); check_added_monitors(&nodes[1], 1); diff --git a/lightning/src/ln/reorg_tests.rs b/lightning/src/ln/reorg_tests.rs index b745453a3c6..3e6db64c486 100644 --- a/lightning/src/ln/reorg_tests.rs +++ b/lightning/src/ln/reorg_tests.rs @@ -348,9 +348,9 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_ *nodes[0].chain_monitor.expect_channel_force_closed.lock().unwrap() = Some((chan.2, true)); nodes[0].node.test_process_background_events(); // Required to free the pending background monitor update check_added_monitors!(nodes[0], 1); - let expected_err = "Funding transaction was un-confirmed. Locked at 6 confs, now have 0 confs."; + let expected_err = "Funding transaction was un-confirmed. Locked at 6 confs, now have Unconfirmed confs."; if reorg_after_reload || !reload_node { - handle_announce_close_broadcast_events(&nodes, 0, 1, true, "Channel closed because of an exception: Funding transaction was un-confirmed. Locked at 6 confs, now have 0 confs."); + handle_announce_close_broadcast_events(&nodes, 0, 1, true, "Channel closed because of an exception: Funding transaction was un-confirmed. Locked at 6 confs, now have Unconfirmed confs."); check_added_monitors!(nodes[1], 1); check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Channel closed because of an exception: {}", expected_err)) } , [nodes[0].node.get_our_node_id()], 100000);