From cb5e32f5e80473a1643a99404d56a5d2c3054b44 Mon Sep 17 00:00:00 2001 From: jbesraa Date: Thu, 25 Apr 2024 18:49:59 +0300 Subject: [PATCH] Add `FundingSigned` event If `manually_broadcast_outbound_channels` is set, LDK will emit this event after the counterparty node send the `FundingSigned` msg without broadcasting the funding transaction. --- lightning/src/events/mod.rs | 49 ++++++ lightning/src/ln/channel.rs | 188 ++++++++++++++++++++-- lightning/src/ln/channelmanager.rs | 21 ++- lightning/src/ln/functional_test_utils.rs | 12 ++ lightning/src/ln/functional_tests.rs | 48 ++++++ 5 files changed, 305 insertions(+), 13 deletions(-) diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index e72bc0228f..a458bdde80 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -497,6 +497,29 @@ impl_writeable_tlv_based_enum!(PaymentFailureReason, /// written as it makes no sense to respond to it after reconnecting to peers). #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { + /// Used to indicate that the counterparty node has sent `FundingSigned` msg but we are yet to + /// broadcast the funding transaction. + /// + /// After you receive this event, you should broadcast the funding transaction and then call + //// [`ChannelManager::funding_transaction_broadcasted`]. <-- not implemtened yet + /// // should we have some timeout for this? + //// [`ChannelManager::funding_transaction_broadcasted`]: crate::ln::channelmanager::ChannelManager::funding_transaction_broadcasted + FundingSigned { + /// The `channel_id` indicating which channel has completed the `FundingSigned` stage. + channel_id: ChannelId, + /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound + /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if + /// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise + /// `user_channel_id` will be randomized for an inbound channel. This may be zero for objects + /// serialized with LDK versions prior to 0.0.113. + /// + /// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel + /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel + /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels + user_channel_id: u128, + /// The funding transaction which was signed by the counterparty. + funding_tx: Transaction, + }, /// Used to indicate that the client should generate a funding transaction with the given /// parameters and then call [`ChannelManager::funding_transaction_generated`]. /// Generated in [`ChannelManager`] message handling. @@ -1404,6 +1427,14 @@ impl Writeable for Event { 35u8.write(writer)?; // Never write ConnectionNeeded events as buffered onion messages aren't serialized. }, + &Event::FundingSigned { ref channel_id, ref user_channel_id, ref funding_tx } => { + 37u8.write(writer)?; + write_tlv_fields!(writer, { + (0, channel_id, required), + (2, user_channel_id, required), + (4, funding_tx, required), + }); + }, // Note that, going forward, all new events must only write data inside of // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write // data via `write_tlv_fields`. @@ -1814,6 +1845,24 @@ impl MaybeReadable for Event { }, // Note that we do not write a length-prefixed TLV for ConnectionNeeded events. 35u8 => Ok(None), + 37u8 => { + let mut f = || { + let mut channel_id = ChannelId::new_zero(); + let mut user_channel_id: u128 = 0; + let mut funding_tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + read_tlv_fields!(reader, { + (0, channel_id, required), + (2, user_channel_id, required), + (4, funding_tx, required), + }); + Ok(Some(Event::FundingSigned { + channel_id, + user_channel_id, + funding_tx, + })) + }; + f() + }, // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue. // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt // reads. diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index f83935a49d..4e3944dfeb 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -646,6 +646,7 @@ mod state_flags { pub const LOCAL_SHUTDOWN_SENT: u32 = 1 << 11; pub const SHUTDOWN_COMPLETE: u32 = 1 << 12; pub const WAITING_FOR_BATCH: u32 = 1 << 13; + pub const FUNDING_SIGNED: u32 = 1 << 14; } define_state_flags!( @@ -681,6 +682,10 @@ define_state_flags!( define_state_flags!( "Flags that only apply to [`ChannelState::AwaitingChannelReady`].", FUNDED_STATE, AwaitingChannelReadyFlags, [ + ("Indicates we sent them a `funding_created` message and received `funding_signed` message \ + but the broadcasting is manually handled.", + FUNDING_SIGNED, state_flags::FUNDING_SIGNED, + is_funding_signed, set_funding_signed, clear_funding_signed), ("Indicates they sent us a `channel_ready` message. Once both `THEIR_CHANNEL_READY` and \ `OUR_CHANNEL_READY` are set, our state moves on to `ChannelReady`.", THEIR_CHANNEL_READY, state_flags::THEIR_CHANNEL_READY, @@ -835,6 +840,7 @@ impl ChannelState { impl_state_flag!(is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready, AwaitingChannelReady); impl_state_flag!(is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch, AwaitingChannelReady); impl_state_flag!(is_awaiting_remote_revoke, set_awaiting_remote_revoke, clear_awaiting_remote_revoke, ChannelReady); + impl_state_flag!(is_funding_signed, set_funding_signed, clear_funding_signed, AwaitingChannelReady); } pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; @@ -1524,6 +1530,9 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { // We track whether we already emitted a `ChannelPending` event. channel_pending_event_emitted: bool, + + // We track whether we already emitted a `FundingSigned` event. + funding_signed_event_emitted: bool, // We track whether we already emitted a `ChannelReady` event. channel_ready_event_emitted: bool, @@ -1871,6 +1880,7 @@ impl ChannelContext where SP::Target: SignerProvider { outbound_scid_alias: 0, channel_pending_event_emitted: false, + funding_signed_event_emitted: false, channel_ready_event_emitted: false, #[cfg(any(test, fuzzing))] @@ -2094,6 +2104,7 @@ impl ChannelContext where SP::Target: SignerProvider { outbound_scid_alias, channel_pending_event_emitted: false, + funding_signed_event_emitted: false, channel_ready_event_emitted: false, #[cfg(any(test, fuzzing))] @@ -2125,6 +2136,10 @@ impl ChannelContext where SP::Target: SignerProvider { self.channel_transaction_parameters.is_outbound_from_holder } + pub fn get_funding_transaction(&self) -> Option<&Transaction> { + self.funding_transaction.as_ref() + } + /// Gets the fee we'd want to charge for adding an HTLC output to this Channel /// Allowed in any state (including after shutdown) pub fn get_outbound_forwarding_fee_base_msat(&self) -> u32 { @@ -2139,10 +2154,18 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns true if this channel is fully established and not known to be closing. /// Allowed in any state (including after shutdown) pub fn is_usable(&self) -> bool { - matches!(self.channel_state, ChannelState::ChannelReady(_)) && - !self.channel_state.is_local_shutdown_sent() && - !self.channel_state.is_remote_shutdown_sent() && - !self.monitor_pending_channel_ready + if self.manually_broadcast_outbound_channels.is_some() { + matches!(self.channel_state, ChannelState::AwaitingChannelReady(f) if f.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED)) + && !self.channel_state.is_local_shutdown_sent() + && !self.channel_state.is_remote_shutdown_sent() + && !self.monitor_pending_channel_ready + && self.get_funding_tx_confirmed_in().is_some() + } else { + matches!(self.channel_state, ChannelState::ChannelReady(_)) && + !self.channel_state.is_local_shutdown_sent() && + !self.channel_state.is_remote_shutdown_sent() && + !self.monitor_pending_channel_ready + } } /// shutdown state returns the state of the channel in its various stages of shutdown @@ -2378,10 +2401,22 @@ impl ChannelContext where SP::Target: SignerProvider { self.is_funding_broadcast() && !self.channel_pending_event_emitted } + // Checks whether we should emit a `FundingSigned` event. + pub(crate) fn should_emit_funding_signed_event(&self) -> bool { + !self.is_funding_broadcast() + && self.manually_broadcast_outbound_channels.is_some() + && !self.funding_signed_event_emitted + } + // Returns whether we already emitted a `ChannelPending` event. pub(crate) fn channel_pending_event_emitted(&self) -> bool { self.channel_pending_event_emitted } + + // Returns whether we already emitted a `FundingSigned` event. + pub(crate) fn funding_signed_event_emitted(&self) -> bool { + self.funding_signed_event_emitted + } // Remembers that we already emitted a `ChannelPending` event. pub(crate) fn set_channel_pending_event_emitted(&mut self) { @@ -2398,6 +2433,11 @@ impl ChannelContext where SP::Target: SignerProvider { self.channel_ready_event_emitted = true; } + // Remembers that we already emitted a `FundingSigned` event. + pub(crate) fn set_funding_signed_event_emitted(&mut self) { + self.funding_signed_event_emitted = true; + } + /// Tracks the number of ticks elapsed since the previous [`ChannelConfig`] was updated. Once /// [`EXPIRE_PREV_CONFIG_TICKS`] is reached, the previous config is considered expired and will /// no longer be considered when forwarding HTLCs. @@ -2439,6 +2479,7 @@ impl ChannelContext where SP::Target: SignerProvider { pub fn is_funding_broadcast(&self) -> bool { !self.channel_state.is_pre_funded_state() && !matches!(self.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) + && !matches!(self.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED)) } /// Transaction nomenclature is somewhat confusing here as there are many different cases - a @@ -3284,7 +3325,8 @@ impl ChannelContext where SP::Target: SignerProvider { match self.channel_state { ChannelState::FundingNegotiated => f(), ChannelState::AwaitingChannelReady(flags) => - if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) || + if flags.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED) || + flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) || flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) { f() @@ -4089,8 +4131,9 @@ impl Channel where if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY { // If we reconnected before sending our `channel_ready` they may still resend theirs. check_reconnection = true; - } else if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() { - self.context.channel_state.set_their_channel_ready(); + } else if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() + || flags == AwaitingChannelReadyFlags::FUNDING_SIGNED { + self.context.channel_state.set_their_channel_ready(); } else if flags == AwaitingChannelReadyFlags::OUR_CHANNEL_READY { self.context.channel_state = ChannelState::ChannelReady(self.context.channel_state.with_funded_state_flags_mask().into()); self.context.update_time_counter += 1; @@ -5185,6 +5228,12 @@ impl Channel where } 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. + + if matches!( + self.context.channel_state + ,ChannelState::AwaitingChannelReady(flag) if flag.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED)) { + funding_broadcastable = None; + } if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) && self.context.minimum_depth != Some(0) { funding_broadcastable = None; } @@ -6300,7 +6349,9 @@ impl Channel where if !self.is_awaiting_monitor_update() { return false; } if matches!( self.context.channel_state, ChannelState::AwaitingChannelReady(flags) - if flags.clone().clear(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY | FundedStateFlags::PEER_DISCONNECTED | FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS | AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() + if flags.clone().clear(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY | + FundedStateFlags::PEER_DISCONNECTED | FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS + | AwaitingChannelReadyFlags::WAITING_FOR_BATCH | AwaitingChannelReadyFlags::FUNDING_SIGNED).is_empty() ) { // If we're not a 0conf channel, we'll be waiting on a monitor update with only // AwaitingChannelReady set, though our peer could have sent their channel_ready. @@ -6391,7 +6442,12 @@ impl Channel where // Note that we don't include ChannelState::WaitingForBatch as we don't want to send // channel_ready until the entire batch is ready. - let need_commitment_update = if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()).is_empty()) { + let need_commitment_update = if matches!(self.context.channel_state, + ChannelState::AwaitingChannelReady(f) if f.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED)) { + self.context.channel_state.set_our_channel_ready(); + true + } + else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()).is_empty()) { self.context.channel_state.set_our_channel_ready(); true } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()) == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY) { @@ -6402,8 +6458,9 @@ 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 < ChannelState::ChannelReady(ChannelReadyFlags::new()) + if self.context.funding_tx_confirmation_height != 0 + && self.context.channel_state < ChannelState::ChannelReady(ChannelReadyFlags::new()) + && !self.context.channel_state.is_funding_signed() { // 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 @@ -7729,7 +7786,9 @@ impl OutboundV1Channel where SP::Target: SignerProvider { counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger); assert!(!self.context.channel_state.is_monitor_update_in_progress()); // We have no had any monitor(s) yet to fail update! - if self.context.is_batch_funding() { + if self.context.get_manually_broadcast_outbound_channels().is_some() { + self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::FUNDING_SIGNED); + } else if self.context.is_batch_funding() { self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH); } else { self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); @@ -8713,6 +8772,7 @@ impl Writeable for Channel where SP::Target: SignerProvider { let channel_pending_event_emitted = Some(self.context.channel_pending_event_emitted); let channel_ready_event_emitted = Some(self.context.channel_ready_event_emitted); + let funding_signed_event_emitted = Some(self.context.funding_signed_event_emitted); // `user_id` used to be a single u64 value. In order to remain backwards compatible with // versions prior to 0.0.113, the u128 is serialized as two separate u64 values. Therefore, @@ -8764,6 +8824,8 @@ impl Writeable for Channel where SP::Target: SignerProvider { (43, malformed_htlcs, optional_vec), // Added in 0.0.119 // 45 and 47 are reserved for async signing (49, self.context.local_initiated_shutdown, option), // Added in 0.0.122 + (51, self.context.manually_broadcast_outbound_channels, option), + (53, funding_signed_event_emitted, option) }); Ok(()) @@ -9052,6 +9114,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch let mut outbound_scid_alias = None; let mut channel_pending_event_emitted = None; let mut channel_ready_event_emitted = None; + let mut funding_signed_event_emitted = None; let mut user_id_high_opt: Option = None; let mut channel_keys_id: Option<[u8; 32]> = None; @@ -9107,6 +9170,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch // 45 and 47 are reserved for async signing (49, local_initiated_shutdown, option), (51, manually_broadcast_outbound_channels, option), + (53, funding_signed_event_emitted, option), }); let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id { @@ -9330,6 +9394,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch outbound_scid_alias: outbound_scid_alias.unwrap_or(0), channel_pending_event_emitted: channel_pending_event_emitted.unwrap_or(true), + funding_signed_event_emitted: funding_signed_event_emitted.unwrap_or(true), channel_ready_event_emitted: channel_ready_event_emitted.unwrap_or(true), #[cfg(any(test, fuzzing))] @@ -10992,6 +11057,105 @@ mod tests { assert!(res.is_err()); } + #[test] + fn test_funding_signed_event() { + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let logger = test_utils::TestLogger::new(); + let secp_ctx = Secp256k1::new(); + let seed = [42; 32]; + let network = Network::Testnet; + let best_block = BestBlock::from_network(network); + let chain_hash = ChainHash::using_genesis_block(network); + let keys_provider = test_utils::TestKeysInterface::new(&seed, network); + + let mut config = UserConfig::default(); + config.manually_broadcast_outbound_channels = true; + let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None + ).unwrap(); + + let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); + let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_channel_type_features(&config), + &channelmanager::provided_init_features(&config), + &open_channel_msg, + 7, + &config, + 0, + &&logger, + false, + ).unwrap(); + + let accept_channel_msg = node_b_chan.accept_inbound_channel(); + node_a_chan.accept_channel( + &accept_channel_msg, + &config.channel_handshake_limits, + &channelmanager::provided_init_features(&config), + ).unwrap(); + + let output_script = node_a_chan.context.get_funding_redeemscript(); + let tx = Transaction { + version: 1, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![ + TxOut { + value: 10000000, script_pubkey: output_script.clone(), + }, + TxOut { + value: 10000000, script_pubkey: Builder::new().into_script(), + }, + ]}; + let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; + let funding_created_msg = node_a_chan.get_funding_created( + tx.clone(), funding_outpoint, false, &&logger, + ).map_err(|_| ()).unwrap(); + let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created( + &funding_created_msg.unwrap(), + best_block, + &&keys_provider, + &&logger, + ).map_err(|_| ()).unwrap(); + let _ = node_b_chan.monitor_updating_restored( + &&logger, + &&keys_provider, + chain_hash, + &config, + 1, + ); + let res = node_a_chan.funding_signed( + &funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger, + ); + let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; + let node_a_updates = node_a_chan.monitor_updating_restored( + &&logger, + &&keys_provider, + chain_hash, + &config, + 1, + ); + assert!(node_a_updates.channel_ready.is_none()); + assert!(node_a_updates.funding_broadcastable.is_none()); + assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::FUNDING_SIGNED)); + } + #[test] fn test_waiting_for_batch() { let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 05d4351509..e5a6b59f88 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -18,6 +18,7 @@ //! imply it needs to fail HTLCs/payments/channels it manages). use bitcoin::blockdata::block::Header; +use bitcoin::blockdata::locktime::absolute::LockTime; use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::constants::ChainHash; use bitcoin::key::constants::SECRET_KEY_SIZE; @@ -2864,6 +2865,23 @@ macro_rules! send_channel_ready { } }} } +macro_rules! emit_funding_signed_event { + ($locked_events: expr, $channel: expr) => { + let funding_tx = $channel.context.get_funding_transaction(); // hmm.. this is always none? + let should_emit = $channel.context.should_emit_funding_signed_event(); + match (funding_tx, should_emit) { + (_, true) => { + $locked_events.push_back((events::Event::FundingSigned { + channel_id: $channel.context.channel_id(), + user_channel_id: $channel.context.get_user_id(), + funding_tx: Transaction { version: 2, lock_time: LockTime::ZERO, input: vec![], output: vec![] }, + }, None)); + $channel.context.set_funding_signed_event_emitted(); + } + _ => { } + } + } +} macro_rules! emit_channel_pending_event { ($locked_events: expr, $channel: expr) => { @@ -2884,7 +2902,7 @@ macro_rules! emit_channel_pending_event { macro_rules! emit_channel_ready_event { ($locked_events: expr, $channel: expr) => { if $channel.context.should_emit_channel_ready_event() { - debug_assert!($channel.context.channel_pending_event_emitted()); + debug_assert!($channel.context.channel_pending_event_emitted() || $channel.context.funding_signed_event_emitted()); $locked_events.push_back((events::Event::ChannelReady { channel_id: $channel.context.channel_id(), user_channel_id: $channel.context.get_user_id(), @@ -6840,6 +6858,7 @@ where { let mut pending_events = self.pending_events.lock().unwrap(); emit_channel_pending_event!(pending_events, channel); + emit_funding_signed_event!(pending_events, channel); emit_channel_ready_event!(pending_events, channel); } diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index cf52d946e3..1e1e5bea90 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -2339,6 +2339,18 @@ pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, } } +#[cfg(any(test, ldk_bench, feature = "_test_utils"))] +pub fn expect_funding_signed_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) -> ChannelId { + let events = node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match &events[0] { + crate::events::Event::FundingSigned { channel_id, .. } => { + *channel_id + }, + _ => panic!("Unexpected event"), + } +} + #[cfg(any(test, ldk_bench, feature = "_test_utils"))] pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) { let events = node.node.get_and_clear_pending_events(); diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 465d6288d9..02c11cfe50 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -11019,3 +11019,51 @@ fn test_accept_inbound_channel_errors_queued() { assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, open_channel_msg.common_fields.temporary_channel_id); } + +#[test] +fn test_funding_signed_event() { + let mut cfg = UserConfig::default(); + cfg.channel_handshake_config.minimum_depth = 1; + cfg.manually_broadcast_outbound_channels = true; + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg), Some(cfg)]); // should test nodes with different cfgs + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let _ = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); + let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel); + let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + + nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_channel); + + let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); + + nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + check_added_monitors!(nodes[0], 0); + let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + + nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created); + check_added_monitors!(nodes[1], 1); + expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); + + let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + + nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed); + check_added_monitors!(nodes[0], 1); + + expect_funding_signed_event(&nodes[0]); + nodes[0].node.get_and_clear_pending_msg_events(); + mine_transaction(&nodes[0], &tx); + expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id()); + mine_transaction(&nodes[1], &tx); + let events_a = nodes[0].node.get_and_clear_pending_events(); + dbg!(&events_a); + let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_channel_ready(&nodes[0].node.get_our_node_id(), &as_channel_ready); + expect_channel_ready_event(&nodes[1], &nodes[0].node.get_our_node_id()); + let _ = nodes[0].node.get_and_clear_pending_msg_events(); + let _ = nodes[1].node.get_and_clear_pending_msg_events(); +} +