From ff9e4572b605968efbc8e0a035459a1f6f6d265d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 10 Feb 2022 00:09:42 +0000 Subject: [PATCH] Send funding_locked immediately for inbound channels with 0conf --- lightning/src/ln/channel.rs | 6 ++-- lightning/src/ln/channelmanager.rs | 13 ++++++-- lightning/src/ln/priv_short_conf_tests.rs | 40 ++++++++++++++++++++--- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index a49444f09..70a13f9eb 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -2093,7 +2093,7 @@ impl Channel { &self.get_counterparty_pubkeys().funding_pubkey } - pub fn funding_created(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> where L::Target: Logger { + pub fn funding_created(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor, Option), ChannelError> where L::Target: Logger { if self.is_outbound() { return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned())); } @@ -2168,7 +2168,7 @@ impl Channel { Ok((msgs::FundingSigned { channel_id: self.channel_id, signature - }, channel_monitor)) + }, channel_monitor, self.check_get_funding_locked(0))) } /// Handles a funding_signed message from the remote end. @@ -6692,7 +6692,7 @@ mod tests { }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap(); - let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap(); + let (funding_signed_msg, _, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap(); // Node B --> Node A: funding signed let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&logger); diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index acc1310fa..8193ba443 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2293,6 +2293,9 @@ impl ChannelMana action: msgs::ErrorAction::IgnoreError }); } + if chan.get_short_channel_id().is_none() { + return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}); + } log_trace!(self.logger, "Attempting to generate broadcast channel update for channel {}", log_bytes!(chan.channel_id())); self.get_channel_update_for_unicast(chan) } @@ -2304,7 +2307,7 @@ impl ChannelMana /// May be called with channel_state already locked! fn get_channel_update_for_unicast(&self, chan: &Channel) -> Result { log_trace!(self.logger, "Attempting to generate channel update for channel {}", log_bytes!(chan.channel_id())); - let short_channel_id = match chan.get_short_channel_id() { + let short_channel_id = match chan.get_short_channel_id().or(chan.latest_inbound_scid_alias()) { None => return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}), Some(id) => id, }; @@ -4262,7 +4265,7 @@ impl ChannelMana } fn internal_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> { - let ((funding_msg, monitor), mut chan) = { + let ((funding_msg, monitor, mut funding_locked), mut chan) = { let best_block = *self.best_block.read().unwrap(); let mut channel_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_lock; @@ -4297,7 +4300,8 @@ impl ChannelMana // hasn't persisted to disk yet - we can't lose money on a transaction that we haven't // accepted payment from yet. We do, however, need to wait to send our funding_locked // until we have persisted our monitor. - chan.monitor_update_failed(false, false, false, Vec::new(), Vec::new(), Vec::new()); + chan.monitor_update_failed(false, false, funding_locked.is_some(), Vec::new(), Vec::new(), Vec::new()); + funding_locked = None; // Don't send the funding_locked now }, } } @@ -4312,6 +4316,9 @@ impl ChannelMana node_id: counterparty_node_id.clone(), msg: funding_msg, }); + if let Some(msg) = funding_locked { + send_funding_locked!(channel_state.short_to_id, channel_state.pending_msg_events, chan, msg); + } e.insert(chan); } } diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index a7bc3e565..ed11b993f 100644 --- a/lightning/src/ln/priv_short_conf_tests.rs +++ b/lightning/src/ln/priv_short_conf_tests.rs @@ -570,6 +570,9 @@ fn test_simple_0conf_channel() { // If our peer tells us they will accept our channel with 0 confs, and we funded the channel, // we should trust the funding won't be double-spent (assuming `trust_own_funding_0conf` is // set)! + // Further, if we `accept_inbound_channel_from_trusted_peer_0conf`, funding locked messages + // should fly immediately and the channel should be available for use as soon as they are + // received. let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); @@ -602,11 +605,38 @@ fn test_simple_0conf_channel() { nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created); check_added_monitors!(nodes[1], 1); - 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); + let bs_signed_locked = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(bs_signed_locked.len(), 2); + let as_funding_locked; + match &bs_signed_locked[0] { + MessageSendEvent::SendFundingSigned { node_id, msg } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &msg); + check_added_monitors!(nodes[0], 1); + + assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); + assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], tx); + + as_funding_locked = get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id()); + } + _ => panic!("Unexpected event"), + } + match &bs_signed_locked[1] { + MessageSendEvent::SendFundingLocked { node_id, msg } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &msg); + } + _ => panic!("Unexpected event"), + } - let as_funding_locked = get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id()); nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &as_funding_locked); + + let as_channel_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); + let bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); + + nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &bs_channel_update); + nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &as_channel_update); + + assert_eq!(nodes[0].node.list_usable_channels().len(), 1); + assert_eq!(nodes[1].node.list_usable_channels().len(), 1); } -- 2.39.5