From: Wilmer Paulino Date: Wed, 18 Jan 2023 21:03:20 +0000 (-0800) Subject: Sign gossip messages with NodeSigner X-Git-Tag: v0.0.114-beta~50^2~2 X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=19c4468bfc3f77302afc4665043c50e89b1de24a;p=rust-lightning Sign gossip messages with NodeSigner --- diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 20a6e55cc..dd1f9f8cf 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -183,7 +183,7 @@ impl<'a> std::hash::Hash for Peer<'a> { type ChannelMan<'a> = ChannelManager< Arc, Arc, Arc, Arc, Arc>>, Arc, Arc, Arc, Arc, Arc, &'a FuzzRouter, Arc>; -type PeerMan<'a> = PeerManager, Arc>, Arc>>, Arc, Arc>>, IgnoringMessageHandler, Arc, IgnoringMessageHandler>; +type PeerMan<'a> = PeerManager, Arc>, Arc>>, Arc, Arc>>, IgnoringMessageHandler, Arc, IgnoringMessageHandler, Arc>; struct MoneyLossDetector<'a> { manager: Arc>, @@ -462,7 +462,7 @@ pub fn do_test(data: &[u8], logger: &Arc) { chan_handler: channelmanager.clone(), route_handler: gossip_sync.clone(), onion_message_handler: IgnoringMessageHandler {}, - }, our_network_key, 0, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger), IgnoringMessageHandler{})); + }, our_network_key, 0, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger), IgnoringMessageHandler{}, keys_manager.clone())); let mut should_forward = false; let mut payments_received: Vec = Vec::new(); diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 4759c272d..eaee26404 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -385,7 +385,7 @@ pub async fn process_events_async< PGS: 'static + Deref> + Send + Sync, RGS: 'static + Deref> + Send, UMH: 'static + Deref + Send + Sync, - PM: 'static + Deref> + Send + Sync, + PM: 'static + Deref> + Send + Sync, S: 'static + Deref + Send + Sync, SC: WriteableScore<'a>, SleepFuture: core::future::Future + core::marker::Unpin, @@ -514,7 +514,7 @@ impl BackgroundProcessor { PGS: 'static + Deref> + Send + Sync, RGS: 'static + Deref> + Send, UMH: 'static + Deref + Send + Sync, - PM: 'static + Deref> + Send + Sync, + PM: 'static + Deref> + Send + Sync, S: 'static + Deref + Send + Sync, SC: WriteableScore<'a>, >( @@ -663,7 +663,7 @@ mod tests { node: Arc>, p2p_gossip_sync: PGS, rapid_gossip_sync: RGS, - peer_manager: Arc, Arc, IgnoringMessageHandler, Arc, IgnoringMessageHandler>>, + peer_manager: Arc, Arc, IgnoringMessageHandler, Arc, IgnoringMessageHandler, Arc>>, chain_monitor: Arc, persister: Arc, tx_broadcaster: Arc, @@ -786,7 +786,7 @@ mod tests { let p2p_gossip_sync = Arc::new(P2PGossipSync::new(network_graph.clone(), Some(chain_source.clone()), logger.clone())); let rapid_gossip_sync = Arc::new(RapidGossipSync::new(network_graph.clone())); let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()), onion_message_handler: IgnoringMessageHandler{}}; - let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(Recipient::Node).unwrap(), 0, &seed, logger.clone(), IgnoringMessageHandler{})); + let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(Recipient::Node).unwrap(), 0, &seed, logger.clone(), IgnoringMessageHandler{}, keys_manager.clone())); let node = Node { node: manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, persister, tx_broadcaster, network_graph, logger, best_block, scorer }; nodes.push(node); } diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index 45fe9b12f..c979a3e70 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -32,6 +32,7 @@ //! type TxBroadcaster = dyn lightning::chain::chaininterface::BroadcasterInterface + Send + Sync; //! type FeeEstimator = dyn lightning::chain::chaininterface::FeeEstimator + Send + Sync; //! type Logger = dyn lightning::util::logger::Logger + Send + Sync; +//! type NodeSigner = dyn lightning::chain::keysinterface::NodeSigner + Send + Sync; //! type ChainAccess = dyn lightning::chain::Access + Send + Sync; //! type ChainFilter = dyn lightning::chain::Filter + Send + Sync; //! type DataPersister = dyn lightning::chain::chainmonitor::Persist + Send + Sync; @@ -80,6 +81,7 @@ use tokio::{io, time}; use tokio::sync::mpsc; use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt}; +use lightning::chain::keysinterface::NodeSigner; use lightning::ln::peer_handler; use lightning::ln::peer_handler::SocketDescriptor as LnSocketTrait; use lightning::ln::peer_handler::CustomMessageHandler; @@ -123,21 +125,23 @@ struct Connection { id: u64, } impl Connection { - async fn poll_event_process( + async fn poll_event_process( peer_manager: PM, mut event_receiver: mpsc::Receiver<()>, ) where - PM: Deref> + 'static + Send + Sync, + PM: Deref> + 'static + Send + Sync, CMH: Deref + 'static + Send + Sync, RMH: Deref + 'static + Send + Sync, OMH: Deref + 'static + Send + Sync, L: Deref + 'static + Send + Sync, UMH: Deref + 'static + Send + Sync, + NS: Deref + 'static + Send + Sync, CMH::Target: ChannelMessageHandler + Send + Sync, RMH::Target: RoutingMessageHandler + Send + Sync, OMH::Target: OnionMessageHandler + Send + Sync, L::Target: Logger + Send + Sync, UMH::Target: CustomMessageHandler + Send + Sync, + NS::Target: NodeSigner + Send + Sync, { loop { if event_receiver.recv().await.is_none() { @@ -147,24 +151,26 @@ impl Connection { } } - async fn schedule_read( + async fn schedule_read( peer_manager: PM, us: Arc>, mut reader: io::ReadHalf, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>, ) where - PM: Deref> + 'static + Send + Sync + Clone, + PM: Deref> + 'static + Send + Sync + Clone, CMH: Deref + 'static + Send + Sync, RMH: Deref + 'static + Send + Sync, OMH: Deref + 'static + Send + Sync, L: Deref + 'static + Send + Sync, UMH: Deref + 'static + Send + Sync, + NS: Deref + 'static + Send + Sync, CMH::Target: ChannelMessageHandler + 'static + Send + Sync, RMH::Target: RoutingMessageHandler + 'static + Send + Sync, OMH::Target: OnionMessageHandler + 'static + Send + Sync, L::Target: Logger + 'static + Send + Sync, UMH::Target: CustomMessageHandler + 'static + Send + Sync, + NS::Target: NodeSigner + 'static + Send + Sync, { // Create a waker to wake up poll_event_process, above let (event_waker, event_receiver) = mpsc::channel(1); @@ -283,21 +289,23 @@ fn get_addr_from_stream(stream: &StdTcpStream) -> Option { /// The returned future will complete when the peer is disconnected and associated handling /// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do /// not need to poll the provided future in order to make progress. -pub fn setup_inbound( +pub fn setup_inbound( peer_manager: PM, stream: StdTcpStream, ) -> impl std::future::Future where - PM: Deref> + 'static + Send + Sync + Clone, + PM: Deref> + 'static + Send + Sync + Clone, CMH: Deref + 'static + Send + Sync, RMH: Deref + 'static + Send + Sync, OMH: Deref + 'static + Send + Sync, L: Deref + 'static + Send + Sync, UMH: Deref + 'static + Send + Sync, + NS: Deref + 'static + Send + Sync, CMH::Target: ChannelMessageHandler + Send + Sync, RMH::Target: RoutingMessageHandler + Send + Sync, OMH::Target: OnionMessageHandler + Send + Sync, L::Target: Logger + Send + Sync, UMH::Target: CustomMessageHandler + Send + Sync, + NS::Target: NodeSigner + Send + Sync, { let remote_addr = get_addr_from_stream(&stream); let (reader, write_receiver, read_receiver, us) = Connection::new(stream); @@ -336,22 +344,24 @@ pub fn setup_inbound( /// The returned future will complete when the peer is disconnected and associated handling /// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do /// not need to poll the provided future in order to make progress. -pub fn setup_outbound( +pub fn setup_outbound( peer_manager: PM, their_node_id: PublicKey, stream: StdTcpStream, ) -> impl std::future::Future where - PM: Deref> + 'static + Send + Sync + Clone, + PM: Deref> + 'static + Send + Sync + Clone, CMH: Deref + 'static + Send + Sync, RMH: Deref + 'static + Send + Sync, OMH: Deref + 'static + Send + Sync, L: Deref + 'static + Send + Sync, UMH: Deref + 'static + Send + Sync, + NS: Deref + 'static + Send + Sync, CMH::Target: ChannelMessageHandler + Send + Sync, RMH::Target: RoutingMessageHandler + Send + Sync, OMH::Target: OnionMessageHandler + Send + Sync, L::Target: Logger + Send + Sync, UMH::Target: CustomMessageHandler + Send + Sync, + NS::Target: NodeSigner + Send + Sync, { let remote_addr = get_addr_from_stream(&stream); let (reader, mut write_receiver, read_receiver, us) = Connection::new(stream); @@ -419,22 +429,24 @@ pub fn setup_outbound( /// disconnected and associated handling futures are freed, though, because all processing in said /// futures are spawned with tokio::spawn, you do not need to poll the second future in order to /// make progress. -pub async fn connect_outbound( +pub async fn connect_outbound( peer_manager: PM, their_node_id: PublicKey, addr: SocketAddr, ) -> Option> where - PM: Deref> + 'static + Send + Sync + Clone, + PM: Deref> + 'static + Send + Sync + Clone, CMH: Deref + 'static + Send + Sync, RMH: Deref + 'static + Send + Sync, OMH: Deref + 'static + Send + Sync, L: Deref + 'static + Send + Sync, UMH: Deref + 'static + Send + Sync, + NS: Deref + 'static + Send + Sync, CMH::Target: ChannelMessageHandler + Send + Sync, RMH::Target: RoutingMessageHandler + Send + Sync, OMH::Target: OnionMessageHandler + Send + Sync, L::Target: Logger + Send + Sync, UMH::Target: CustomMessageHandler + Send + Sync, + NS::Target: NodeSigner + Send + Sync, { if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(10), async { TcpStream::connect(&addr).await.map(|s| s.into_std().unwrap()) }).await { Some(setup_outbound(peer_manager, their_node_id, stream)) @@ -573,6 +585,7 @@ mod tests { use lightning::ln::peer_handler::{MessageHandler, PeerManager}; use lightning::ln::features::NodeFeatures; use lightning::util::events::*; + use lightning::util::test_utils::TestNodeSigner; use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey}; use tokio::sync::mpsc; @@ -688,7 +701,7 @@ mod tests { chan_handler: Arc::clone(&a_handler), route_handler: Arc::clone(&a_handler), onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - }, a_key.clone(), 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}))); + }, a_key.clone(), 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), Arc::new(TestNodeSigner::new(a_key)))); let (b_connected_sender, mut b_connected) = mpsc::channel(1); let (b_disconnected_sender, mut b_disconnected) = mpsc::channel(1); @@ -703,7 +716,7 @@ mod tests { chan_handler: Arc::clone(&b_handler), route_handler: Arc::clone(&b_handler), onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - }, b_key.clone(), 0, &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}))); + }, b_key.clone(), 0, &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), Arc::new(TestNodeSigner::new(b_key)))); // We bind on localhost, hoping the environment is properly configured with a local // address. This may not always be the case in containers and the like, so if this test is @@ -756,7 +769,7 @@ mod tests { chan_handler: Arc::new(lightning::ln::peer_handler::ErroringMessageHandler::new()), onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), route_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - }, a_key, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}))); + }, a_key, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), Arc::new(TestNodeSigner::new(a_key)))); // Make two connections, one for an inbound and one for an outbound connection let conn_a = { diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 83243ee88..cb7b17292 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -383,17 +383,18 @@ pub trait BaseSign { fn sign_holder_anchor_input( &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1, ) -> Result; - /// Signs a channel announcement message with our funding key and our node secret key (aka - /// node_id or network_key), proving it comes from one of the channel participants. + /// Signs a channel announcement message with our funding key proving it comes from one of the + /// channel participants. /// - /// The first returned signature should be from our node secret key, the second from our - /// funding key. + /// Channel announcements also require a signature from each node's network key. Our node + /// signature is computed through [`NodeSigner::sign_gossip_message`]. /// /// Note that if this fails or is rejected, the channel will not be publicly announced and /// our counterparty may (though likely will not) close the channel on us for violating the /// protocol. - fn sign_channel_announcement(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1) - -> Result<(Signature, Signature), ()>; + fn sign_channel_announcement_with_funding_key( + &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 + ) -> Result; /// Set the counterparty static channel data, including basepoints, /// `counterparty_selected`/`holder_selected_contest_delay` and funding outpoint. /// @@ -880,10 +881,11 @@ impl BaseSign for InMemorySigner { Ok(sign(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key)) } - fn sign_channel_announcement(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1) - -> Result<(Signature, Signature), ()> { + fn sign_channel_announcement_with_funding_key( + &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 + ) -> Result { let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - Ok((sign(secp_ctx, &msghash, &self.node_secret), sign(secp_ctx, &msghash, &self.funding_key))) + Ok(sign(secp_ctx, &msghash, &self.funding_key)) } fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) { diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 8b323a3a9..c1e7c0bca 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -35,7 +35,7 @@ use crate::chain::BestBlock; use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator}; use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS}; use crate::chain::transaction::{OutPoint, TransactionData}; -use crate::chain::keysinterface::{Sign, EntropySource, BaseSign, SignerProvider}; +use crate::chain::keysinterface::{Sign, EntropySource, BaseSign, NodeSigner, Recipient, SignerProvider}; use crate::util::events::ClosureReason; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter}; use crate::util::logger::Logger; @@ -2394,7 +2394,14 @@ impl Channel { /// Handles a channel_ready message from our peer. If we've already sent our channel_ready /// and the channel is now usable (and public), this may generate an announcement_signatures to /// reply with. - pub fn channel_ready(&mut self, msg: &msgs::ChannelReady, node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock, logger: &L) -> Result, ChannelError> where L::Target: Logger { + pub fn channel_ready( + &mut self, msg: &msgs::ChannelReady, node_signer: &NS, genesis_block_hash: BlockHash, + user_config: &UserConfig, best_block: &BestBlock, logger: &L + ) -> Result, ChannelError> + where + NS::Target: NodeSigner, + L::Target: Logger + { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { self.workaround_lnd_bug_4006 = Some(msg.clone()); return Err(ChannelError::Ignore("Peer sent channel_ready when we needed a channel_reestablish. The peer is likely lnd, see https://github.com/lightningnetwork/lnd/issues/4006".to_owned())); @@ -2448,7 +2455,7 @@ impl Channel { log_info!(logger, "Received channel_ready from peer for channel {}", log_bytes!(self.channel_id())); - Ok(self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, best_block.height(), logger)) + Ok(self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger)) } /// Returns transaction if there is pending funding transaction that is yet to broadcast @@ -3752,7 +3759,14 @@ impl Channel { /// Indicates that the latest ChannelMonitor update has been committed by the client /// successfully and we should restore normal operation. Returns messages which should be sent /// to the remote side. - pub fn monitor_updating_restored(&mut self, logger: &L, node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block_height: u32) -> MonitorRestoreUpdates where L::Target: Logger { + pub fn monitor_updating_restored( + &mut self, logger: &L, node_signer: &NS, genesis_block_hash: BlockHash, + user_config: &UserConfig, best_block_height: u32 + ) -> MonitorRestoreUpdates + where + L::Target: Logger, + NS::Target: NodeSigner + { assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32); self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32); @@ -3787,7 +3801,7 @@ impl Channel { }) } else { None }; - let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, best_block_height, logger); + let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block_height, logger); let mut accepted_htlcs = Vec::new(); mem::swap(&mut accepted_htlcs, &mut self.monitor_pending_forwards); @@ -3939,9 +3953,14 @@ impl Channel { /// `cargo doc --document-private-items`): /// [`super::channelmanager::ChannelManager::force_close_without_broadcasting_txn`] and /// [`super::channelmanager::ChannelManager::force_close_all_channels_without_broadcasting_txn`]. - pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish, logger: &L, - node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock) - -> Result where L::Target: Logger { + pub fn channel_reestablish( + &mut self, msg: &msgs::ChannelReestablish, logger: &L, node_signer: &NS, + genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock + ) -> Result + where + L::Target: Logger, + NS::Target: NodeSigner + { if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { // While BOLT 2 doesn't indicate explicitly we should error this channel here, it // almost certainly indicates we are going to end up out-of-sync in some way, so we @@ -4005,7 +4024,7 @@ impl Channel { }) } else { None }; - let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, best_block.height(), logger); + let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger); if self.channel_state & (ChannelState::FundingSent as u32) == ChannelState::FundingSent as u32 { // If we're waiting on a monitor update, we shouldn't re-send any channel_ready's. @@ -4977,9 +4996,14 @@ impl Channel { /// When a transaction is confirmed, we check whether it is or spends the funding transaction /// In the first case, we store the confirmation height and calculating the short channel id. /// In the second, we simply return an Err indicating we need to be force-closed now. - pub fn transactions_confirmed(&mut self, block_hash: &BlockHash, height: u32, - txdata: &TransactionData, genesis_block_hash: BlockHash, node_pk: PublicKey, user_config: &UserConfig, logger: &L) - -> Result<(Option, Option), ClosureReason> where L::Target: Logger { + pub fn transactions_confirmed( + &mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData, + genesis_block_hash: BlockHash, node_signer: &NS, user_config: &UserConfig, logger: &L + ) -> Result<(Option, Option), ClosureReason> + where + NS::Target: NodeSigner, + L::Target: Logger + { if let Some(funding_txo) = self.get_funding_txo() { for &(index_in_block, tx) in txdata.iter() { // Check if the transaction is the expected funding transaction, and if it is, @@ -5025,7 +5049,7 @@ impl Channel { // may have already happened for this block). if let Some(channel_ready) = self.check_get_channel_ready(height) { log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.channel_id)); - let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, user_config, height, logger); + let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger); return Ok((Some(channel_ready), announcement_sigs)); } } @@ -5051,13 +5075,25 @@ impl Channel { /// /// May return some HTLCs (and their payment_hash) which have timed out and should be failed /// back. - pub fn best_block_updated(&mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash, node_pk: PublicKey, user_config: UserConfig, logger: &L) - -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where L::Target: Logger { - self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_pk, user_config)), logger) + pub fn best_block_updated( + &mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash, + node_signer: &NS, user_config: &UserConfig, logger: &L + ) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> + where + NS::Target: NodeSigner, + L::Target: Logger + { + self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_signer, user_config)), logger) } - fn do_best_block_updated(&mut self, height: u32, highest_header_time: u32, genesis_node_pk: Option<(BlockHash, PublicKey, UserConfig)>, logger: &L) - -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where L::Target: Logger { + fn do_best_block_updated( + &mut self, height: u32, highest_header_time: u32, + genesis_node_signer: Option<(BlockHash, &NS, &UserConfig)>, logger: &L + ) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> + where + NS::Target: NodeSigner, + L::Target: Logger + { let mut timed_out_htlcs = Vec::new(); // This mirrors the check in ChannelManager::decode_update_add_htlc_onion, refusing to // forward an HTLC when our counterparty should almost certainly just fail it for expiring @@ -5078,8 +5114,8 @@ impl Channel { self.update_time_counter = cmp::max(self.update_time_counter, highest_header_time); if let Some(channel_ready) = self.check_get_channel_ready(height) { - let announcement_sigs = if let Some((genesis_block_hash, node_pk, user_config)) = genesis_node_pk { - self.get_announcement_sigs(node_pk, genesis_block_hash, &user_config, height, logger) + let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer { + self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger) } else { None }; log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.channel_id)); return Ok((Some(channel_ready), timed_out_htlcs, announcement_sigs)); @@ -5119,8 +5155,8 @@ impl Channel { return Err(ClosureReason::FundingTimedOut); } - let announcement_sigs = if let Some((genesis_block_hash, node_pk, user_config)) = genesis_node_pk { - self.get_announcement_sigs(node_pk, genesis_block_hash, &user_config, height, logger) + let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer { + self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger) } else { None }; Ok((None, timed_out_htlcs, announcement_sigs)) } @@ -5137,7 +5173,7 @@ impl Channel { // 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. let best_time = self.update_time_counter; - match self.do_best_block_updated(reorg_height, best_time, None, logger) { + match self.do_best_block_updated(reorg_height, best_time, None::<(BlockHash, &&NodeSigner, &UserConfig)>, logger) { Ok((channel_ready, timed_out_htlcs, announcement_sigs)) => { assert!(channel_ready.is_none(), "We can't generate a funding with 0 confirmations?"); assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?"); @@ -5337,7 +5373,9 @@ impl Channel { /// closing). /// /// This will only return ChannelError::Ignore upon failure. - fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash, user_config: &UserConfig) -> Result { + fn get_channel_announcement( + &self, node_signer: &NS, chain_hash: BlockHash, user_config: &UserConfig, + ) -> Result where NS::Target: NodeSigner { if !self.config.announced_channel { return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned())); } @@ -5345,6 +5383,8 @@ impl Channel { return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned())); } + let node_id = node_signer.get_node_id(Recipient::Node) + .map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?; let were_node_one = node_id.serialize()[..] < self.counterparty_node_id.serialize()[..]; let msg = msgs::UnsignedChannelAnnouncement { @@ -5361,8 +5401,14 @@ impl Channel { Ok(msg) } - fn get_announcement_sigs(&mut self, node_pk: PublicKey, genesis_block_hash: BlockHash, user_config: &UserConfig, best_block_height: u32, logger: &L) - -> Option where L::Target: Logger { + fn get_announcement_sigs( + &mut self, node_signer: &NS, genesis_block_hash: BlockHash, user_config: &UserConfig, + best_block_height: u32, logger: &L + ) -> Option + where + NS::Target: NodeSigner, + L::Target: Logger + { if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height { return None; } @@ -5381,14 +5427,21 @@ impl Channel { } log_trace!(logger, "Creating an announcement_signatures message for channel {}", log_bytes!(self.channel_id())); - let announcement = match self.get_channel_announcement(node_pk, genesis_block_hash, user_config) { + let announcement = match self.get_channel_announcement(node_signer, genesis_block_hash, user_config) { Ok(a) => a, - Err(_) => { - log_trace!(logger, "Cannot create an announcement_signatures as channel is not public."); + Err(e) => { + log_trace!(logger, "{:?}", e); return None; } }; - let (our_node_sig, our_bitcoin_sig) = match self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx) { + let our_node_sig = match node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) { + Err(_) => { + log_error!(logger, "Failed to generate node signature for channel_announcement. Channel will not be announced!"); + return None; + }, + Ok(v) => v + }; + let our_bitcoin_sig = match self.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.secp_ctx) { Err(_) => { log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!"); return None; @@ -5407,11 +5460,17 @@ impl Channel { /// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are /// available. - fn sign_channel_announcement(&self, our_node_id: PublicKey, announcement: msgs::UnsignedChannelAnnouncement) -> Result { + fn sign_channel_announcement( + &self, node_signer: &NS, announcement: msgs::UnsignedChannelAnnouncement + ) -> Result where NS::Target: NodeSigner { if let Some((their_node_sig, their_bitcoin_sig)) = self.announcement_sigs { - let were_node_one = announcement.node_id_1 == our_node_id; + let our_node_key = node_signer.get_node_id(Recipient::Node) + .map_err(|_| ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()))?; + let were_node_one = announcement.node_id_1 == our_node_key; - let (our_node_sig, our_bitcoin_sig) = self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx) + let our_node_sig = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) + .map_err(|_| ChannelError::Ignore("Failed to generate node signature for channel_announcement".to_owned()))?; + let our_bitcoin_sig = self.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.secp_ctx) .map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?; Ok(msgs::ChannelAnnouncement { node_signature_1: if were_node_one { our_node_sig } else { their_node_sig }, @@ -5428,8 +5487,11 @@ impl Channel { /// Processes an incoming announcement_signatures message, providing a fully-signed /// channel_announcement message which we can broadcast and storing our counterparty's /// signatures for later reconstruction/rebroadcast of the channel_announcement. - pub fn announcement_signatures(&mut self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32, msg: &msgs::AnnouncementSignatures, user_config: &UserConfig) -> Result { - let announcement = self.get_channel_announcement(our_node_id.clone(), chain_hash, user_config)?; + pub fn announcement_signatures( + &mut self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32, + msg: &msgs::AnnouncementSignatures, user_config: &UserConfig + ) -> Result where NS::Target: NodeSigner { + let announcement = self.get_channel_announcement(node_signer, chain_hash, user_config)?; let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]); @@ -5450,20 +5512,22 @@ impl Channel { "Got announcement_signatures prior to the required six confirmations - we may not have received a block yet that our peer has".to_owned())); } - self.sign_channel_announcement(our_node_id, announcement) + self.sign_channel_announcement(node_signer, announcement) } /// Gets a signed channel_announcement for this channel, if we previously received an /// announcement_signatures from our counterparty. - pub fn get_signed_channel_announcement(&self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32, user_config: &UserConfig) -> Option { + pub fn get_signed_channel_announcement( + &self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32, user_config: &UserConfig + ) -> Option where NS::Target: NodeSigner { if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height { return None; } - let announcement = match self.get_channel_announcement(our_node_id.clone(), chain_hash, user_config) { + let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) { Ok(res) => res, Err(_) => return None, }; - match self.sign_channel_announcement(our_node_id, announcement) { + match self.sign_channel_announcement(node_signer, announcement) { Ok(res) => Some(res), Err(_) => None, } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5b312f04e..abec2c95a 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -26,7 +26,6 @@ use bitcoin::network::constants::Network; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::secp256k1::{SecretKey,PublicKey}; @@ -2280,9 +2279,11 @@ where fee_proportional_millionths: chan.get_fee_proportional_millionths(), excess_data: Vec::new(), }; - - let msg_hash = Sha256dHash::hash(&unsigned.encode()[..]); - let sig = self.secp_ctx.sign_ecdsa(&hash_to_message!(&msg_hash[..]), &self.our_network_key); + // Panic on failure to signal LDK should be restarted to retry signing the `ChannelUpdate`. + // If we returned an error and the `node_signer` cannot provide a signature for whatever + // reason`, we wouldn't be able to receive inbound payments through the corresponding + // channel. + let sig = self.node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&unsigned)).unwrap(); Ok(msgs::ChannelUpdate { signature: sig, @@ -4060,7 +4061,7 @@ where return; } - let updates = channel.get_mut().monitor_updating_restored(&self.logger, self.get_our_node_id(), self.genesis_hash, &self.default_configuration, self.best_block.read().unwrap().height()); + let updates = channel.get_mut().monitor_updating_restored(&self.logger, &self.node_signer, self.genesis_hash, &self.default_configuration, self.best_block.read().unwrap().height()); let channel_update = if updates.channel_ready.is_some() && channel.get().is_usable() { // We only send a channel_update in the case where we are just now sending a // channel_ready and the channel is in a usable state. We may re-send a @@ -4397,7 +4398,7 @@ where let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { hash_map::Entry::Occupied(mut chan) => { - let announcement_sigs_opt = try_chan_entry!(self, chan.get_mut().channel_ready(&msg, self.get_our_node_id(), + let announcement_sigs_opt = try_chan_entry!(self, chan.get_mut().channel_ready(&msg, &self.node_signer, self.genesis_hash.clone(), &self.default_configuration, &self.best_block.read().unwrap(), &self.logger), chan); if let Some(announcement_sigs) = announcement_sigs_opt { log_trace!(self.logger, "Sending announcement_signatures for channel {}", log_bytes!(chan.get().channel_id())); @@ -4879,8 +4880,8 @@ where peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement { msg: try_chan_entry!(self, chan.get_mut().announcement_signatures( - self.get_our_node_id(), self.genesis_hash.clone(), - self.best_block.read().unwrap().height(), msg, &self.default_configuration + &self.node_signer, self.genesis_hash.clone(), self.best_block.read().unwrap().height(), + msg, &self.default_configuration ), chan), // Note that announcement_signatures fails if the channel cannot be announced, // so get_channel_update_for_broadcast will never fail by the time we get here. @@ -4951,7 +4952,7 @@ where // freed HTLCs to fail backwards. If in the future we no longer drop pending // add-HTLCs on disconnect, we may be handed HTLCs to fail backwards here. let responses = try_chan_entry!(self, chan.get_mut().channel_reestablish( - msg, &self.logger, self.our_network_pubkey.clone(), self.genesis_hash, + msg, &self.logger, &self.node_signer, self.genesis_hash, &self.default_configuration, &*self.best_block.read().unwrap()), chan); let mut channel_update = None; if let Some(msg) = responses.shutdown_msg { @@ -5630,7 +5631,7 @@ where *best_block = BestBlock::new(header.prev_blockhash, new_height) } - self.do_chain_event(Some(new_height), |channel| channel.best_block_updated(new_height, header.time, self.genesis_hash.clone(), self.get_our_node_id(), self.default_configuration.clone(), &self.logger)); + self.do_chain_event(Some(new_height), |channel| channel.best_block_updated(new_height, header.time, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger)); } } @@ -5654,13 +5655,13 @@ where log_trace!(self.logger, "{} transactions included in block {} at height {} provided", txdata.len(), block_hash, height); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, self.genesis_hash.clone(), self.get_our_node_id(), &self.default_configuration, &self.logger) + self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger) .map(|(a, b)| (a, Vec::new(), b))); let last_best_block_height = self.best_block.read().unwrap().height(); if height < last_best_block_height { let timestamp = self.highest_seen_timestamp.load(Ordering::Acquire); - self.do_chain_event(Some(last_best_block_height), |channel| channel.best_block_updated(last_best_block_height, timestamp as u32, self.genesis_hash.clone(), self.get_our_node_id(), self.default_configuration.clone(), &self.logger)); + self.do_chain_event(Some(last_best_block_height), |channel| channel.best_block_updated(last_best_block_height, timestamp as u32, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger)); } } @@ -5676,7 +5677,7 @@ where *self.best_block.write().unwrap() = BestBlock::new(block_hash, height); - self.do_chain_event(Some(height), |channel| channel.best_block_updated(height, header.time, self.genesis_hash.clone(), self.get_our_node_id(), self.default_configuration.clone(), &self.logger)); + self.do_chain_event(Some(height), |channel| channel.best_block_updated(height, header.time, self.genesis_hash.clone(), &self.node_signer, &self.default_configuration, &self.logger)); macro_rules! max_time { ($timestamp: expr) => { @@ -5787,7 +5788,7 @@ where msg: announcement_sigs, }); if let Some(height) = height_opt { - if let Some(announcement) = channel.get_signed_channel_announcement(self.get_our_node_id(), self.genesis_hash, height, &self.default_configuration) { + if let Some(announcement) = channel.get_signed_channel_announcement(&self.node_signer, self.genesis_hash, height, &self.default_configuration) { pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement { msg: announcement, // Note that announcement_signatures fails if the channel cannot be announced, @@ -6177,7 +6178,7 @@ where } } else { true }; if retain && chan.get_counterparty_node_id() != *counterparty_node_id { - if let Some(msg) = chan.get_signed_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone(), self.best_block.read().unwrap().height(), &self.default_configuration) { + if let Some(msg) = chan.get_signed_channel_announcement(&self.node_signer, self.genesis_hash.clone(), self.best_block.read().unwrap().height(), &self.default_configuration) { if let Ok(update_msg) = self.get_channel_update_for_broadcast(chan) { pending_msg_events.push(events::MessageSendEvent::SendChannelAnnouncement { node_id: *counterparty_node_id, diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index dffda9967..9983f6f90 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -17,6 +17,7 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey}; +use crate::chain::keysinterface::{KeysManager, NodeSigner, Recipient}; use crate::ln::features::{InitFeatures, NodeFeatures}; use crate::ln::msgs; use crate::ln::msgs::{ChannelMessageHandler, LightningError, NetAddress, OnionMessageHandler, RoutingMessageHandler}; @@ -28,7 +29,6 @@ use crate::ln::wire::Encode; use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger}; use crate::routing::gossip::{NetworkGraph, P2PGossipSync}; use crate::util::atomic_counter::AtomicCounter; -use crate::util::crypto::sign; use crate::util::events::{MessageSendEvent, MessageSendEventsProvider, OnionMessageProvider}; use crate::util::logger::Logger; @@ -43,7 +43,6 @@ use core::convert::Infallible; #[cfg(feature = "std")] use std::error; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hashes::sha256::HashEngine as Sha256Engine; use bitcoin::hashes::{HashEngine, Hash}; @@ -491,7 +490,7 @@ impl Peer { /// issues such as overly long function definitions. /// /// (C-not exported) as `Arc`s don't make sense in bindings. -pub type SimpleArcPeerManager = PeerManager>, Arc>>, Arc, Arc>>, Arc>, Arc, IgnoringMessageHandler>; +pub type SimpleArcPeerManager = PeerManager>, Arc>>, Arc, Arc>>, Arc>, Arc, IgnoringMessageHandler, Arc>; /// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference /// counterpart to the SimpleArcPeerManager type alias. Use this type by default when you don't @@ -501,7 +500,7 @@ pub type SimpleArcPeerManager = PeerManager = PeerManager, &'f P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, &'i SimpleRefOnionMessenger<'j, 'k, L>, &'f L, IgnoringMessageHandler>; +pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, SD, M, T, F, C, L> = PeerManager, &'f P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, &'i SimpleRefOnionMessenger<'j, 'k, L>, &'f L, IgnoringMessageHandler, &'c KeysManager>; /// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls /// socket events into messages which it passes on to its [`MessageHandler`]. @@ -522,12 +521,13 @@ pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm /// you're using lightning-net-tokio. /// /// [`read_event`]: PeerManager::read_event -pub struct PeerManager where +pub struct PeerManager where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, L::Target: Logger, - CMH::Target: CustomMessageHandler { + CMH::Target: CustomMessageHandler, + NS::Target: NodeSigner { message_handler: MessageHandler, /// Connection state for each connected peer - we have an outer read-write lock which is taken /// as read while we're doing processing for a peer and taken write when a peer is being added @@ -563,6 +563,8 @@ pub struct PeerManager } @@ -592,10 +594,11 @@ macro_rules! encode_msg { }} } -impl PeerManager where +impl PeerManager where CM::Target: ChannelMessageHandler, OM::Target: OnionMessageHandler, - L::Target: Logger { + L::Target: Logger, + NS::Target: NodeSigner { /// Constructs a new `PeerManager` with the given `ChannelMessageHandler` and /// `OnionMessageHandler`. No routing message handler is used and network graph messages are /// ignored. @@ -609,18 +612,19 @@ impl PeerManager Self { + pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self { Self::new(MessageHandler { chan_handler: channel_message_handler, route_handler: IgnoringMessageHandler{}, onion_message_handler, - }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{}) + }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{}, node_signer) } } -impl PeerManager where +impl PeerManager where RM::Target: RoutingMessageHandler, - L::Target: Logger { + L::Target: Logger, + NS::Target: NodeSigner { /// Constructs a new `PeerManager` with the given `RoutingMessageHandler`. No channel message /// handler or onion message handler is used and onion and channel messages will be ignored (or /// generate error messages). Note that some other lightning implementations time-out connections @@ -635,12 +639,12 @@ impl PeerManager Self { + pub fn new_routing_only(routing_message_handler: RM, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self { Self::new(MessageHandler { chan_handler: ErroringMessageHandler::new(), route_handler: routing_message_handler, onion_message_handler: IgnoringMessageHandler{}, - }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{}) + }, our_node_secret, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{}, node_signer) } } @@ -685,12 +689,14 @@ fn filter_addresses(ip_address: Option) -> Option { } } -impl PeerManager where +impl PeerManager where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, L::Target: Logger, - CMH::Target: CustomMessageHandler { + CMH::Target: CustomMessageHandler, + NS::Target: NodeSigner +{ /// Constructs a new PeerManager with the given message handlers and node_id secret key /// ephemeral_random_data is used to derive per-connection ephemeral keys and must be /// cryptographically secure random bytes. @@ -699,7 +705,7 @@ impl, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self { + pub fn new(message_handler: MessageHandler, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH, node_signer: NS) -> Self { let mut ephemeral_key_midstate = Sha256::engine(); ephemeral_key_midstate.input(ephemeral_random_data); @@ -719,6 +725,7 @@ impl sig, + Err(_) => { + log_error!(self.logger, "Failed to generate signature for node_announcement"); + return; + }, + }; let msg = msgs::NodeAnnouncement { signature: node_announce_sig, @@ -2093,16 +2107,19 @@ mod tests { chan_handler: test_utils::TestChannelMessageHandler, routing_handler: test_utils::TestRoutingMessageHandler, logger: test_utils::TestLogger, + node_signer: test_utils::TestNodeSigner, } fn create_peermgr_cfgs(peer_count: usize) -> Vec { let mut cfgs = Vec::new(); - for _ in 0..peer_count { + for i in 0..peer_count { + let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap(); cfgs.push( PeerManagerCfg{ chan_handler: test_utils::TestChannelMessageHandler::new(), logger: test_utils::TestLogger::new(), routing_handler: test_utils::TestRoutingMessageHandler::new(), + node_signer: test_utils::TestNodeSigner::new(node_secret), } ); } @@ -2110,20 +2127,20 @@ mod tests { cfgs } - fn create_network<'a>(peer_count: usize, cfgs: &'a Vec) -> Vec> { + fn create_network<'a>(peer_count: usize, cfgs: &'a Vec) -> Vec> { let mut peers = Vec::new(); for i in 0..peer_count { let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap(); let ephemeral_bytes = [i as u8; 32]; let msg_handler = MessageHandler { chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler, onion_message_handler: IgnoringMessageHandler {} }; - let peer = PeerManager::new(msg_handler, node_secret, 0, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {}); + let peer = PeerManager::new(msg_handler, node_secret, 0, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {}, &cfgs[i].node_signer); peers.push(peer); } peers } - fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { + fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { let secp_ctx = Secp256k1::new(); let a_id = PublicKey::from_secret_key(&secp_ctx, &peer_a.our_node_secret); let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index 9bfed7e2c..aca781b9f 100644 --- a/lightning/src/ln/priv_short_conf_tests.rs +++ b/lightning/src/ln/priv_short_conf_tests.rs @@ -12,7 +12,7 @@ //! LSP). use crate::chain::ChannelMonitorUpdateStatus; -use crate::chain::keysinterface::{Recipient, NodeSigner}; +use crate::chain::keysinterface::NodeSigner; use crate::ln::channelmanager::{ChannelManager, MIN_CLTV_EXPIRY_DELTA, PaymentId}; use crate::routing::gossip::RoutingFees; use crate::routing::router::{PaymentParameters, RouteHint, RouteHintHop}; @@ -31,10 +31,7 @@ use core::default::Default; use crate::ln::functional_test_utils::*; use bitcoin::blockdata::constants::genesis_block; -use bitcoin::hashes::Hash; -use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::network::constants::Network; -use bitcoin::secp256k1::Secp256k1; #[test] fn test_priv_forwarding_rejection() { @@ -493,8 +490,7 @@ fn test_scid_alias_returned() { fee_proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths, excess_data: Vec::new(), }; - let msg_hash = Sha256dHash::hash(&contents.encode()[..]); - let signature = Secp256k1::new().sign_ecdsa(&hash_to_message!(&msg_hash[..]), &nodes[1].keys_manager.get_node_secret(Recipient::Node).unwrap()); + let signature = nodes[1].keys_manager.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&contents)).unwrap(); let msg = msgs::ChannelUpdate { signature, contents }; let mut err_data = Vec::new(); diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs index dfec1be7e..769d00ecf 100644 --- a/lightning/src/util/enforcing_trait_impls.rs +++ b/lightning/src/util/enforcing_trait_impls.rs @@ -223,9 +223,10 @@ impl BaseSign for EnforcingSigner { self.inner.sign_holder_anchor_input(anchor_tx, input, secp_ctx) } - fn sign_channel_announcement(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1) - -> Result<(Signature, Signature), ()> { - self.inner.sign_channel_announcement(msg, secp_ctx) + fn sign_channel_announcement_with_funding_key( + &self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 + ) -> Result { + self.inner.sign_channel_announcement_with_funding_key(msg, secp_ctx) } fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) { diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 9fb5178ad..9b0816543 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -621,6 +621,57 @@ impl Logger for TestLogger { } } +pub struct TestNodeSigner { + node_secret: SecretKey, +} + +impl TestNodeSigner { + pub fn new(node_secret: SecretKey) -> Self { + Self { node_secret } + } +} + +impl NodeSigner for TestNodeSigner { + fn get_node_secret(&self, recipient: Recipient) -> Result { + let node_secret = match recipient { + Recipient::Node => Ok(self.node_secret.clone()), + Recipient::PhantomNode => Err(()) + }?; + Ok(node_secret) + } + + fn get_inbound_payment_key_material(&self) -> crate::chain::keysinterface::KeyMaterial { + unreachable!() + } + + fn get_node_id(&self, recipient: Recipient) -> Result { + let node_secret = match recipient { + Recipient::Node => Ok(&self.node_secret), + Recipient::PhantomNode => Err(()) + }?; + Ok(PublicKey::from_secret_key(&Secp256k1::signing_only(), node_secret)) + } + + fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&bitcoin::secp256k1::Scalar>) -> Result { + let mut node_secret = match recipient { + Recipient::Node => Ok(self.node_secret.clone()), + Recipient::PhantomNode => Err(()) + }?; + if let Some(tweak) = tweak { + node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?; + } + Ok(SharedSecret::new(other_key, &node_secret)) + } + + fn sign_invoice(&self, _: &[u8], _: &[bitcoin::bech32::u5], _: Recipient) -> Result { + unreachable!() + } + + fn sign_gossip_message(&self, _msg: msgs::UnsignedGossipMessage) -> Result { + unreachable!() + } +} + pub struct TestKeysInterface { pub backing: keysinterface::PhantomKeysManager, pub override_random_bytes: Mutex>,