diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index b0b6910ae2f..5daebb35066 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -18,7 +18,7 @@ libfuzzer_fuzz = ["libfuzzer-sys"] stdin_fuzz = [] [dependencies] -lightning = { path = "../lightning", features = ["regex", "hashbrown"] } +lightning = { path = "../lightning", features = ["regex", "hashbrown", "_test_utils"] } lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" } bitcoin = { version = "0.29.0", features = ["secp-lowmemory"] } hex = "0.3" diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 3c174f3093f..2fd79819bc3 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -29,6 +29,7 @@ use bitcoin::network::constants::Network; use bitcoin::hashes::Hash as TraitImport; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{BlockHash, WPubkeyHash}; use lightning::chain; @@ -54,10 +55,9 @@ use lightning::routing::router::{InFlightHtlcs, Route, RouteHop, RouteParameters use crate::utils::test_logger::{self, Output}; use crate::utils::test_persister::TestPersister; -use bitcoin::secp256k1::{PublicKey, SecretKey, Scalar}; +use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1}; use bitcoin::secp256k1::ecdh::SharedSecret; -use bitcoin::secp256k1::ecdsa::RecoverableSignature; -use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use std::mem; use std::cmp::{self, Ordering}; @@ -174,7 +174,7 @@ impl chain::Watch for TestChainMonitor { } struct KeyProvider { - node_id: u8, + node_secret: SecretKey, rand_bytes_id: atomic::AtomicU32, enforcement_states: Mutex>>>, } @@ -182,37 +182,45 @@ struct KeyProvider { impl EntropySource for KeyProvider { fn get_secure_random_bytes(&self) -> [u8; 32] { let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed); - let mut res = [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, 11, self.node_id]; + let mut res = [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, 11, self.node_secret[31]]; res[30-4..30].copy_from_slice(&id.to_le_bytes()); res } } impl NodeSigner for KeyProvider { - fn get_node_secret(&self, _recipient: Recipient) -> Result { - Ok(SecretKey::from_slice(&[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, 1, self.node_id]).unwrap()) - } - fn get_node_id(&self, recipient: Recipient) -> Result { - let secp_ctx = Secp256k1::signing_only(); - Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?)) + 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<&Scalar>) -> Result { - let mut node_secret = self.get_node_secret(recipient)?; + 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).unwrap(); + node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?; } Ok(SharedSecret::new(other_key, &node_secret)) } fn get_inbound_payment_key_material(&self) -> KeyMaterial { - KeyMaterial([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, 1, self.node_id]) + KeyMaterial([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, 1, self.node_secret[31]]) } fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!() } + + fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result { + let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?; + let secp_ctx = Secp256k1::signing_only(); + Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret)) + } } impl SignerProvider for KeyProvider { @@ -228,13 +236,12 @@ impl SignerProvider for KeyProvider { let id = channel_keys_id[0]; let keys = InMemorySigner::new( &secp_ctx, - self.get_node_secret(Recipient::Node).unwrap(), - SecretKey::from_slice(&[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, 4, self.node_id]).unwrap(), - SecretKey::from_slice(&[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, 5, self.node_id]).unwrap(), - SecretKey::from_slice(&[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, 6, self.node_id]).unwrap(), - SecretKey::from_slice(&[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, 7, self.node_id]).unwrap(), - SecretKey::from_slice(&[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, 8, self.node_id]).unwrap(), - [id, 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, 9, self.node_id], + SecretKey::from_slice(&[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, 4, self.node_secret[31]]).unwrap(), + SecretKey::from_slice(&[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, 5, self.node_secret[31]]).unwrap(), + SecretKey::from_slice(&[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, 6, self.node_secret[31]]).unwrap(), + SecretKey::from_slice(&[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, 7, self.node_secret[31]]).unwrap(), + SecretKey::from_slice(&[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, 8, self.node_secret[31]]).unwrap(), + [id, 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, 9, self.node_secret[31]], channel_value_satoshis, channel_keys_id, ); @@ -245,7 +252,7 @@ impl SignerProvider for KeyProvider { fn read_chan_signer(&self, buffer: &[u8]) -> Result { let mut reader = std::io::Cursor::new(buffer); - let inner: InMemorySigner = ReadableArgs::read(&mut reader, self.get_node_secret(Recipient::Node).unwrap())?; + let inner: InMemorySigner = Readable::read(&mut reader)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); Ok(EnforcingSigner { @@ -257,14 +264,14 @@ impl SignerProvider for KeyProvider { fn get_destination_script(&self) -> Script { let secp_ctx = Secp256k1::signing_only(); - let channel_monitor_claim_key = SecretKey::from_slice(&[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, 2, self.node_id]).unwrap(); + let channel_monitor_claim_key = SecretKey::from_slice(&[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, 2, self.node_secret[31]]).unwrap(); let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() } fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { let secp_ctx = Secp256k1::signing_only(); - let secret_key = SecretKey::from_slice(&[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, 3, self.node_id]).unwrap(); + let secret_key = SecretKey::from_slice(&[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, 3, self.node_secret[31]]).unwrap(); let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize()); ShutdownScript::new_p2wpkh(&pubkey_hash) } @@ -402,7 +409,8 @@ pub fn do_test(data: &[u8], underlying_out: Out) { macro_rules! make_node { ($node_id: expr, $fee_estimator: expr) => { { let logger: Arc = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone())); - let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU32::new(0), enforcement_states: Mutex::new(HashMap::new()) }); + let node_secret = SecretKey::from_slice(&[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, 1, $node_id]).unwrap(); + let keys_manager = Arc::new(KeyProvider { node_secret, rand_bytes_id: atomic::AtomicU32::new(0), enforcement_states: Mutex::new(HashMap::new()) }); let monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), $fee_estimator.clone(), Arc::new(TestPersister { update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed) diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 6d952b42d3c..a1b1485ac45 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -26,6 +26,7 @@ use bitcoin::network::constants::Network; use bitcoin::hashes::Hash as TraitImport; use bitcoin::hashes::HashEngine as TraitImportEngine; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash}; use lightning::chain; @@ -47,15 +48,14 @@ use lightning::util::errors::APIError; use lightning::util::events::Event; use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; use lightning::util::logger::Logger; -use lightning::util::ser::ReadableArgs; +use lightning::util::ser::{Readable, Writeable}; use crate::utils::test_logger; use crate::utils::test_persister::TestPersister; -use bitcoin::secp256k1::{PublicKey, SecretKey, Scalar}; +use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1}; use bitcoin::secp256k1::ecdh::SharedSecret; -use bitcoin::secp256k1::ecdsa::RecoverableSignature; -use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use std::cell::RefCell; use hashbrown::{HashMap, hash_map}; @@ -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>, @@ -293,19 +293,21 @@ impl EntropySource for KeyProvider { } impl NodeSigner for KeyProvider { - fn get_node_secret(&self, _recipient: Recipient) -> Result { - Ok(self.node_secret.clone()) - } - fn get_node_id(&self, recipient: Recipient) -> Result { - let secp_ctx = Secp256k1::signing_only(); - Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?)) + 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<&Scalar>) -> Result { - let mut node_secret = self.get_node_secret(recipient)?; + 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).unwrap(); + node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?; } Ok(SharedSecret::new(other_key, &node_secret)) } @@ -317,6 +319,12 @@ impl NodeSigner for KeyProvider { fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!() } + + fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result { + let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?; + let secp_ctx = Secp256k1::signing_only(); + Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret)) + } } impl SignerProvider for KeyProvider { @@ -335,7 +343,6 @@ impl SignerProvider for KeyProvider { EnforcingSigner::new_with_revoked(if inbound { InMemorySigner::new( &secp_ctx, - self.node_secret.clone(), SecretKey::from_slice(&[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, 1, ctr]).unwrap(), SecretKey::from_slice(&[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, 2, ctr]).unwrap(), SecretKey::from_slice(&[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, 3, ctr]).unwrap(), @@ -348,7 +355,6 @@ impl SignerProvider for KeyProvider { } else { InMemorySigner::new( &secp_ctx, - self.node_secret.clone(), SecretKey::from_slice(&[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, 7, ctr]).unwrap(), SecretKey::from_slice(&[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, 8, ctr]).unwrap(), SecretKey::from_slice(&[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, 9, ctr]).unwrap(), @@ -362,7 +368,7 @@ impl SignerProvider for KeyProvider { } fn read_chan_signer(&self, mut data: &[u8]) -> Result { - let inner: InMemorySigner = ReadableArgs::read(&mut data, self.node_secret.clone())?; + let inner: InMemorySigner = Readable::read(&mut data)?; let state = Arc::new(Mutex::new(EnforcementState::new())); Ok(EnforcingSigner::new_with_revoked( @@ -446,7 +452,7 @@ pub fn do_test(data: &[u8], logger: &Arc) { // keys subsequently generated in this test. Rather than regenerating all the messages manually, // it's easier to just increment the counter here so the keys don't change. keys_manager.counter.fetch_sub(3, Ordering::AcqRel); - let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret(Recipient::Node).unwrap()); + let our_id = &keys_manager.get_node_id(Recipient::Node).unwrap(); let network_graph = Arc::new(NetworkGraph::new(genesis_block(network).block_hash(), Arc::clone(&logger))); let gossip_sync = Arc::new(P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger))); let scorer = FixedPenaltyScorer::with_penalty(0); @@ -456,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{})); + }, 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/fuzz/src/onion_message.rs b/fuzz/src/onion_message.rs index a86734d4575..9bbf8b9cdff 100644 --- a/fuzz/src/onion_message.rs +++ b/fuzz/src/onion_message.rs @@ -100,17 +100,19 @@ impl EntropySource for KeyProvider { } impl NodeSigner for KeyProvider { - fn get_node_secret(&self, _recipient: Recipient) -> Result { - Ok(self.node_secret.clone()) - } - fn get_node_id(&self, recipient: Recipient) -> Result { - let secp_ctx = Secp256k1::signing_only(); - Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?)) + 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<&Scalar>) -> Result { - let mut node_secret = self.get_node_secret(recipient)?; + 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(|_| ())?; } @@ -122,6 +124,10 @@ impl NodeSigner for KeyProvider { fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!() } + + fn sign_gossip_message(&self, _msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result { + unreachable!() + } } impl SignerProvider for KeyProvider { diff --git a/fuzz/src/peer_crypt.rs b/fuzz/src/peer_crypt.rs index 15e9486a35e..f6df392fcef 100644 --- a/fuzz/src/peer_crypt.rs +++ b/fuzz/src/peer_crypt.rs @@ -8,6 +8,7 @@ // licenses. use lightning::ln::peer_channel_encryptor::PeerChannelEncryptor; +use lightning::util::test_utils::TestNodeSigner; use bitcoin::secp256k1::{Secp256k1, PublicKey, SecretKey}; @@ -41,6 +42,7 @@ pub fn do_test(data: &[u8]) { Ok(key) => key, Err(_) => return, }; + let node_signer = TestNodeSigner::new(our_network_key); let ephemeral_key = match SecretKey::from_slice(get_slice!(32)) { Ok(key) => key, Err(_) => return, @@ -53,15 +55,15 @@ pub fn do_test(data: &[u8]) { }; let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey, ephemeral_key); crypter.get_act_one(&secp_ctx); - match crypter.process_act_two(get_slice!(50), &our_network_key, &secp_ctx) { + match crypter.process_act_two(get_slice!(50), &&node_signer) { Ok(_) => {}, Err(_) => return, } assert!(crypter.is_ready_for_encryption()); crypter } else { - let mut crypter = PeerChannelEncryptor::new_inbound(&our_network_key, &secp_ctx); - match crypter.process_act_one_with_keys(get_slice!(50), &our_network_key, ephemeral_key, &secp_ctx) { + let mut crypter = PeerChannelEncryptor::new_inbound(&&node_signer); + match crypter.process_act_one_with_keys(get_slice!(50), &&node_signer, ephemeral_key, &secp_ctx) { Ok(_) => {}, Err(_) => return, } diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 4759c272dc7..4bd5e463f93 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>, >( @@ -615,7 +615,7 @@ mod tests { use bitcoin::network::constants::Network; use lightning::chain::{BestBlock, Confirm, chainmonitor}; use lightning::chain::channelmonitor::ANTI_REORG_DELAY; - use lightning::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, KeysManager, NodeSigner}; + use lightning::chain::keysinterface::{InMemorySigner, EntropySource, KeysManager}; use lightning::chain::transaction::OutPoint; use lightning::get_event_msg; use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager}; @@ -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, 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-block-sync/Cargo.toml b/lightning-block-sync/Cargo.toml index 8b185ff3bab..c605f5ef3a2 100644 --- a/lightning-block-sync/Cargo.toml +++ b/lightning-block-sync/Cargo.toml @@ -27,4 +27,5 @@ serde_json = { version = "1.0", optional = true } chunked_transfer = { version = "1.4", optional = true } [dev-dependencies] +lightning = { version = "0.0.113", path = "../lightning", features = ["_test_utils"] } tokio = { version = "~1.14", features = [ "macros", "rt" ] } diff --git a/lightning-net-tokio/Cargo.toml b/lightning-net-tokio/Cargo.toml index 07f9f313307..8a518638c5f 100644 --- a/lightning-net-tokio/Cargo.toml +++ b/lightning-net-tokio/Cargo.toml @@ -21,3 +21,4 @@ tokio = { version = "1.0", features = [ "io-util", "macros", "rt", "sync", "net" [dev-dependencies] tokio = { version = "~1.14", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] } +lightning = { version = "0.0.113", path = "../lightning", features = ["_test_utils"] } diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index 45fe9b12f61..72ad4741607 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{}))); + }, 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{}))); + }, 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{}))); + }, 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/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 36c1eac1ab0..59b60132f4d 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -4185,7 +4185,6 @@ mod tests { SecretKey::from_slice(&[41; 32]).unwrap(), SecretKey::from_slice(&[41; 32]).unwrap(), SecretKey::from_slice(&[41; 32]).unwrap(), - SecretKey::from_slice(&[41; 32]).unwrap(), [41; 32], 0, [0; 32], diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 9fc00e25238..7063a38c4af 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -34,14 +34,14 @@ use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness}; use crate::util::transaction_utils; use crate::util::crypto::{hkdf_extract_expand_twice, sign}; -use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs}; +use crate::util::ser::{Writeable, Writer, Readable}; #[cfg(anchors)] use crate::util::events::HTLCDescriptor; use crate::chain::transaction::OutPoint; use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; use crate::ln::{chan_utils, PaymentPreimage}; use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction}; -use crate::ln::msgs::UnsignedChannelAnnouncement; +use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage}; use crate::ln::script::ShutdownScript; use crate::prelude::*; @@ -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. /// @@ -438,16 +439,6 @@ pub trait EntropySource { /// A trait that can handle cryptographic operations at the scope level of a node. pub trait NodeSigner { - /// Get node secret key based on the provided [`Recipient`]. - /// - /// The `node_id`/`network_key` is the public key that corresponds to this secret key. - /// - /// This method must return the same value each time it is called with a given [`Recipient`] - /// parameter. - /// - /// Errors if the [`Recipient`] variant is not supported by the implementation. - fn get_node_secret(&self, recipient: Recipient) -> Result; - /// Get secret key material as bytes for use in encrypting and decrypting inbound payment data. /// /// If the implementor of this trait supports [phantom node payments], then every node that is @@ -462,24 +453,22 @@ pub trait NodeSigner { /// [phantom node payments]: PhantomKeysManager fn get_inbound_payment_key_material(&self) -> KeyMaterial; - /// Get node id based on the provided [`Recipient`]. This public key corresponds to the secret in - /// [`get_node_secret`]. + /// Get node id based on the provided [`Recipient`]. /// /// This method must return the same value each time it is called with a given [`Recipient`] /// parameter. /// /// Errors if the [`Recipient`] variant is not supported by the implementation. - /// - /// [`get_node_secret`]: Self::get_node_secret fn get_node_id(&self, recipient: Recipient) -> Result; - /// Gets the ECDH shared secret of our [`node secret`] and `other_key`, multiplying by `tweak` if + /// Gets the ECDH shared secret of our node secret and `other_key`, multiplying by `tweak` if /// one is provided. Note that this tweak can be applied to `other_key` instead of our node /// secret, though this is less efficient. /// - /// Errors if the [`Recipient`] variant is not supported by the implementation. + /// Note that if this fails while attempting to forward an HTLC, LDK will panic. The error + /// should be resolved to allow LDK to resume forwarding HTLCs. /// - /// [`node secret`]: Self::get_node_secret + /// Errors if the [`Recipient`] variant is not supported by the implementation. fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result; /// Sign an invoice. @@ -494,6 +483,14 @@ pub trait NodeSigner { /// /// Errors if the [`Recipient`] variant is not supported by the implementation. fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result; + + /// Sign a gossip message. + /// + /// Note that if this fails, LDK may panic and the message will not be broadcast to the network + /// or a possible channel counterparty. If LDK panics, the error should be resolved to allow the + /// message to be broadcast, as otherwise it may prevent one from receiving funds over the + /// corresponding channel. + fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result; } /// A trait that can return signer instances for individual channels. @@ -566,8 +563,6 @@ pub struct InMemorySigner { pub commitment_seed: [u8; 32], /// Holder public keys and basepoints. pub(crate) holder_channel_pubkeys: ChannelPublicKeys, - /// Private key of our node secret, used for signing channel announcements. - node_secret: SecretKey, /// Counterparty public keys and counterparty/holder `selected_contest_delay`, populated on channel acceptance. channel_parameters: Option, /// The total value of this channel. @@ -580,7 +575,6 @@ impl InMemorySigner { /// Creates a new [`InMemorySigner`]. pub fn new( secp_ctx: &Secp256k1, - node_secret: SecretKey, funding_key: SecretKey, revocation_base_key: SecretKey, payment_key: SecretKey, @@ -601,7 +595,6 @@ impl InMemorySigner { delayed_payment_base_key, htlc_base_key, commitment_seed, - node_secret, channel_value_satoshis, holder_channel_pubkeys, channel_parameters: None, @@ -872,10 +865,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) { @@ -915,8 +909,8 @@ impl Writeable for InMemorySigner { } } -impl ReadableArgs for InMemorySigner { - fn read(reader: &mut R, node_secret: SecretKey) -> Result { +impl Readable for InMemorySigner { + fn read(reader: &mut R) -> Result { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let funding_key = Readable::read(reader)?; @@ -941,7 +935,6 @@ impl ReadableArgs for InMemorySigner { payment_key, delayed_payment_base_key, htlc_base_key, - node_secret, commitment_seed, channel_value_satoshis, holder_channel_pubkeys, @@ -1099,7 +1092,6 @@ impl KeysManager { InMemorySigner::new( &self.secp_ctx, - self.node_secret, funding_key, revocation_base_key, payment_key, @@ -1256,13 +1248,6 @@ impl EntropySource for KeysManager { } impl NodeSigner for KeysManager { - fn get_node_secret(&self, recipient: Recipient) -> Result { - match recipient { - Recipient::Node => Ok(self.node_secret.clone()), - Recipient::PhantomNode => Err(()) - } - } - fn get_node_id(&self, recipient: Recipient) -> Result { match recipient { Recipient::Node => Ok(self.node_id.clone()), @@ -1271,7 +1256,10 @@ impl NodeSigner for KeysManager { } fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result { - let mut node_secret = self.get_node_secret(recipient)?; + 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(|_| ())?; } @@ -1285,10 +1273,15 @@ impl NodeSigner for KeysManager { fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data); let secret = match recipient { - Recipient::Node => self.get_node_secret(Recipient::Node)?, - Recipient::PhantomNode => return Err(()), - }; - Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret)) + Recipient::Node => Ok(&self.node_secret), + Recipient::PhantomNode => Err(()) + }?; + Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret)) + } + + fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result { + let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); + Ok(sign(&self.secp_ctx, &msg_hash, &self.node_secret)) } } @@ -1316,7 +1309,7 @@ impl SignerProvider for KeysManager { } fn read_chan_signer(&self, reader: &[u8]) -> Result { - InMemorySigner::read(&mut io::Cursor::new(reader), self.node_secret.clone()) + InMemorySigner::read(&mut io::Cursor::new(reader)) } fn get_destination_script(&self) -> Script { @@ -1363,13 +1356,6 @@ impl EntropySource for PhantomKeysManager { } impl NodeSigner for PhantomKeysManager { - fn get_node_secret(&self, recipient: Recipient) -> Result { - match recipient { - Recipient::Node => self.inner.get_node_secret(Recipient::Node), - Recipient::PhantomNode => Ok(self.phantom_secret.clone()), - } - } - fn get_node_id(&self, recipient: Recipient) -> Result { match recipient { Recipient::Node => self.inner.get_node_id(Recipient::Node), @@ -1378,7 +1364,10 @@ impl NodeSigner for PhantomKeysManager { } fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result { - let mut node_secret = self.get_node_secret(recipient)?; + let mut node_secret = match recipient { + Recipient::Node => self.inner.node_secret.clone(), + Recipient::PhantomNode => self.phantom_secret.clone(), + }; if let Some(tweak) = tweak { node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?; } @@ -1391,8 +1380,15 @@ impl NodeSigner for PhantomKeysManager { fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data); - let secret = self.get_node_secret(recipient)?; - Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret)) + let secret = match recipient { + Recipient::Node => &self.inner.node_secret, + Recipient::PhantomNode => &self.phantom_secret, + }; + Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret)) + } + + fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result { + self.inner.sign_gossip_message(msg) } } diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 5dbae1bbbb6..6b14b4158de 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, } @@ -6807,22 +6871,19 @@ mod tests { use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight}; use crate::chain::BestBlock; use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget}; - use crate::chain::keysinterface::{BaseSign, InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider}; + use crate::chain::keysinterface::{BaseSign, InMemorySigner, EntropySource, SignerProvider}; use crate::chain::transaction::OutPoint; use crate::util::config::UserConfig; use crate::util::enforcing_trait_impls::EnforcingSigner; use crate::util::errors::APIError; use crate::util::test_utils; use crate::util::test_utils::OnGetShutdownScriptpubkey; - use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Scalar}; + use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; use bitcoin::secp256k1::ffi::Signature as FFISignature; use bitcoin::secp256k1::{SecretKey,PublicKey}; - use bitcoin::secp256k1::ecdh::SharedSecret; - use bitcoin::secp256k1::ecdsa::RecoverableSignature; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; use bitcoin::hash_types::WPubkeyHash; - use bitcoin::bech32::u5; use bitcoin::PackedLockTime; use bitcoin::util::address::WitnessVersion; use crate::prelude::*; @@ -6861,21 +6922,6 @@ mod tests { fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] } } - impl NodeSigner for Keys { - fn get_node_secret(&self, _recipient: Recipient) -> Result { panic!(); } - - fn get_node_id(&self, recipient: Recipient) -> Result { - let secp_ctx = Secp256k1::signing_only(); - Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?)) - } - - fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&Scalar>) -> Result { panic!(); } - - fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); } - - fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { panic!(); } - } - impl SignerProvider for Keys { type Signer = InMemorySigner; @@ -7344,7 +7390,6 @@ mod tests { let mut signer = InMemorySigner::new( &secp_ctx, - SecretKey::from_slice(&hex::decode("4242424242424242424242424242424242424242424242424242424242424242").unwrap()[..]).unwrap(), SecretKey::from_slice(&hex::decode("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(), SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(), diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5b312f04e4a..50f8e86a699 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -26,12 +26,10 @@ 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}; use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::{LockTime, secp256k1, Sequence}; use crate::chain; @@ -721,7 +719,6 @@ where #[cfg(not(test))] short_to_chan_info: FairRwLock>, - our_network_key: SecretKey, our_network_pubkey: PublicKey, inbound_payment_key: inbound_payment::ExpandedKey, @@ -1457,8 +1454,7 @@ where id_to_peer: Mutex::new(HashMap::new()), short_to_chan_info: FairRwLock::new(HashMap::new()), - our_network_key: node_signer.get_node_secret(Recipient::Node).unwrap(), - our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &node_signer.get_node_secret(Recipient::Node).unwrap()), + our_network_pubkey: node_signer.get_node_id(Recipient::Node).unwrap(), secp_ctx, inbound_payment_key: expanded_inbound_key, @@ -2017,7 +2013,9 @@ where return_malformed_err!("invalid ephemeral pubkey", 0x8000 | 0x4000 | 6); } - let shared_secret = SharedSecret::new(&msg.onion_routing_packet.public_key.unwrap(), &self.our_network_key).secret_bytes(); + let shared_secret = self.node_signer.ecdh( + Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), None + ).unwrap().secret_bytes(); if msg.onion_routing_packet.version != 0 { //TODO: Spec doesn't indicate if we should only hash hop_data here (and in other @@ -2266,7 +2264,7 @@ where } fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel<::Signer>) -> Result { log_trace!(self.logger, "Generating channel update for channel {}", log_bytes!(chan.channel_id())); - let were_node_one = PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).serialize()[..] < chan.get_counterparty_node_id().serialize()[..]; + let were_node_one = self.our_network_pubkey.serialize()[..] < chan.get_counterparty_node_id().serialize()[..]; let unsigned = msgs::UnsignedChannelUpdate { chain_hash: self.genesis_hash, @@ -2280,9 +2278,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, @@ -2923,9 +2923,9 @@ where } } if let PendingHTLCRouting::Forward { onion_packet, .. } = routing { - let phantom_secret_res = self.node_signer.get_node_secret(Recipient::PhantomNode); - if phantom_secret_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.genesis_hash) { - let phantom_shared_secret = SharedSecret::new(&onion_packet.public_key.unwrap(), &phantom_secret_res.unwrap()).secret_bytes(); + let phantom_pubkey_res = self.node_signer.get_node_id(Recipient::PhantomNode); + if phantom_pubkey_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.genesis_hash) { + let phantom_shared_secret = self.node_signer.ecdh(Recipient::PhantomNode, &onion_packet.public_key.unwrap(), None).unwrap().secret_bytes(); let next_hop = match onion_utils::decode_next_payment_hop(phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac, payment_hash) { Ok(res) => res, Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => { @@ -4060,7 +4060,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 +4397,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 +4879,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 +4951,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 +5630,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 +5654,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 +5676,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 +5787,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 +6177,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, @@ -7386,11 +7386,10 @@ where pending_events_read.append(&mut channel_closures); } - let our_network_key = match args.node_signer.get_node_secret(Recipient::Node) { + let our_network_pubkey = match args.node_signer.get_node_id(Recipient::Node) { Ok(key) => key, Err(()) => return Err(DecodeError::InvalidValue) }; - let our_network_pubkey = PublicKey::from_secret_key(&secp_ctx, &our_network_key); if let Some(network_pubkey) = received_network_pubkey { if network_pubkey != our_network_pubkey { log_error!(args.logger, "Key that was generated does not match the existing key."); @@ -7506,7 +7505,6 @@ where probing_cookie_secret: probing_cookie_secret.unwrap(), - our_network_key, our_network_pubkey, secp_ctx, diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 6cbcd978700..40817aa3c7d 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -632,6 +632,25 @@ impl Readable for NetAddress { } } +/// Represents the set of gossip messages that require a signature from a node's identity key. +pub enum UnsignedGossipMessage<'a> { + /// An unsigned channel announcement. + ChannelAnnouncement(&'a UnsignedChannelAnnouncement), + /// An unsigned channel update. + ChannelUpdate(&'a UnsignedChannelUpdate), + /// An unsigned node announcement. + NodeAnnouncement(&'a UnsignedNodeAnnouncement) +} + +impl<'a> Writeable for UnsignedGossipMessage<'a> { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + match self { + UnsignedGossipMessage::ChannelAnnouncement(ref msg) => msg.write(writer), + UnsignedGossipMessage::ChannelUpdate(ref msg) => msg.write(writer), + UnsignedGossipMessage::NodeAnnouncement(ref msg) => msg.write(writer), + } + } +} /// The unsigned part of a [`node_announcement`] message. /// diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs index 442dfc39985..243dcb677b4 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -35,8 +35,7 @@ use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1; -use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::{PublicKey, SecretKey}; +use bitcoin::secp256k1::{Secp256k1, SecretKey}; use crate::io; use crate::prelude::*; @@ -834,9 +833,7 @@ fn test_always_create_tlv_format_onion_payloads() { macro_rules! get_phantom_route { ($nodes: expr, $amt: expr, $channel: expr) => {{ - let secp_ctx = Secp256k1::new(); - let phantom_secret = $nodes[1].keys_manager.get_node_secret(Recipient::PhantomNode).unwrap(); - let phantom_pubkey = PublicKey::from_secret_key(&secp_ctx, &phantom_secret); + let phantom_pubkey = $nodes[1].keys_manager.get_node_id(Recipient::PhantomNode).unwrap(); let phantom_route_hint = $nodes[1].node.get_phantom_route_hints(); let payment_params = PaymentParameters::from_node_id(phantom_pubkey) .with_features($nodes[1].node.invoice_features()) diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index 277b0faf6a0..4632007a0ad 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -9,6 +9,7 @@ use crate::prelude::*; +use crate::chain::keysinterface::{NodeSigner, Recipient}; use crate::ln::msgs::LightningError; use crate::ln::msgs; use crate::ln::wire; @@ -26,6 +27,8 @@ use crate::util::crypto::hkdf_extract_expand_twice; use crate::util::ser::VecWriter; use bitcoin::hashes::hex::ToHex; +use core::ops::Deref; + /// Maximum Lightning message data length according to /// [BOLT-8](https://github.com/lightning/bolts/blob/v1.0/08-transport.md#lightning-message-specification) /// and [BOLT-1](https://github.com/lightning/bolts/blob/master/01-messaging.md#lightning-message-format): @@ -36,6 +39,11 @@ const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29 // Sha256(NOISE_CK || "lightning") const NOISE_H: [u8; 32] = [0xd1, 0xfb, 0xf6, 0xde, 0xe4, 0xf6, 0x86, 0xf1, 0x32, 0xfd, 0x70, 0x2c, 0x4a, 0xbf, 0x8f, 0xba, 0x4b, 0xb4, 0x20, 0xd8, 0x9d, 0x2a, 0x04, 0x8a, 0x3c, 0x4f, 0x4c, 0x09, 0x2e, 0x37, 0xb6, 0x76]; +enum NoiseSecretKey<'a, 'b, NS: Deref> where NS::Target: NodeSigner { + InMemory(&'a SecretKey), + NodeSigner(&'b NS) +} + pub enum NextNoiseStep { ActOne, ActTwo, @@ -109,10 +117,10 @@ impl PeerChannelEncryptor { } } - pub fn new_inbound(our_node_secret: &SecretKey, secp_ctx: &Secp256k1) -> PeerChannelEncryptor { + pub fn new_inbound(node_signer: &NS) -> PeerChannelEncryptor where NS::Target: NodeSigner { let mut sha = Sha256::engine(); sha.input(&NOISE_H); - let our_node_id = PublicKey::from_secret_key(&secp_ctx, our_node_secret); + let our_node_id = node_signer.get_node_id(Recipient::Node).unwrap(); sha.input(&our_node_id.serialize()[..]); let h = Sha256::from_engine(sha).into_inner(); @@ -201,7 +209,9 @@ impl PeerChannelEncryptor { } #[inline] - fn inbound_noise_act(state: &mut BidirectionalNoiseState, act: &[u8], our_key: &SecretKey) -> Result<(PublicKey, [u8; 32]), LightningError> { + fn inbound_noise_act<'a, 'b, NS: Deref>( + state: &mut BidirectionalNoiseState, act: &[u8], secret_key: NoiseSecretKey<'a, 'b, NS> + ) -> Result<(PublicKey, [u8; 32]), LightningError> where NS::Target: NodeSigner { assert_eq!(act.len(), 50); if act[0] != 0 { @@ -218,7 +228,15 @@ impl PeerChannelEncryptor { sha.input(&their_pub.serialize()[..]); state.h = Sha256::from_engine(sha).into_inner(); - let ss = SharedSecret::new(&their_pub, &our_key); + let ss = match secret_key { + NoiseSecretKey::InMemory(secret_key) => SharedSecret::new(&their_pub, secret_key), + NoiseSecretKey::NodeSigner(node_signer) => node_signer + .ecdh(Recipient::Node, &their_pub, None) + .map_err(|_| LightningError { + err: "Failed to derive shared secret".to_owned(), + action: msgs::ErrorAction::DisconnectPeer { msg: None } + })?, + }; let temp_k = PeerChannelEncryptor::hkdf(state, ss); let mut dec = [0; 0]; @@ -251,9 +269,9 @@ impl PeerChannelEncryptor { } } - pub fn process_act_one_with_keys( - &mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey, secp_ctx: &Secp256k1) - -> Result<[u8; 50], LightningError> { + pub fn process_act_one_with_keys( + &mut self, act_one: &[u8], node_signer: &NS, our_ephemeral: SecretKey, secp_ctx: &Secp256k1) + -> Result<[u8; 50], LightningError> where NS::Target: NodeSigner { assert_eq!(act_one.len(), 50); match self.noise_state { @@ -264,7 +282,7 @@ impl PeerChannelEncryptor { panic!("Requested act at wrong step"); } - let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, &our_node_secret)?; + let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, NoiseSecretKey::NodeSigner(node_signer))?; ie.get_or_insert(their_pub); re.get_or_insert(our_ephemeral); @@ -281,9 +299,9 @@ impl PeerChannelEncryptor { } } - pub fn process_act_two( - &mut self, act_two: &[u8], our_node_secret: &SecretKey, secp_ctx: &Secp256k1) - -> Result<([u8; 66], PublicKey), LightningError> { + pub fn process_act_two( + &mut self, act_two: &[u8], node_signer: &NS) + -> Result<([u8; 66], PublicKey), LightningError> where NS::Target: NodeSigner { assert_eq!(act_two.len(), 50); let final_hkdf; @@ -296,10 +314,13 @@ impl PeerChannelEncryptor { panic!("Requested act at wrong step"); } - let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, &ie)?; + let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, NoiseSecretKey::::InMemory(&ie))?; let mut res = [0; 66]; - let our_node_id = PublicKey::from_secret_key(secp_ctx, &our_node_secret); + let our_node_id = node_signer.get_node_id(Recipient::Node).map_err(|_| LightningError { + err: "Failed to encrypt message".to_owned(), + action: msgs::ErrorAction::DisconnectPeer { msg: None } + })?; PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]); @@ -308,7 +329,10 @@ impl PeerChannelEncryptor { sha.input(&res[1..50]); bidirectional_state.h = Sha256::from_engine(sha).into_inner(); - let ss = SharedSecret::new(&re, our_node_secret); + let ss = node_signer.ecdh(Recipient::Node, &re, None).map_err(|_| LightningError { + err: "Failed to derive shared secret".to_owned(), + action: msgs::ErrorAction::DisconnectPeer { msg: None } + })?; let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]); @@ -522,12 +546,13 @@ impl PeerChannelEncryptor { mod tests { use super::LN_MAX_MSG_LEN; - use bitcoin::secp256k1::{PublicKey,SecretKey}; + use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::secp256k1::Secp256k1; use hex; use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState}; + use crate::util::test_utils::TestNodeSigner; fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor { let their_node_id = PublicKey::from_slice(&hex::decode("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap(); @@ -542,12 +567,13 @@ mod tests { // transport-responder successful handshake let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); - let secp_ctx = Secp256k1::signing_only(); + let secp_ctx = Secp256k1::new(); + let node_signer = TestNodeSigner::new(our_node_id); - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); // test vector doesn't specify the initiator static key, but it's the same as the one @@ -572,14 +598,14 @@ mod tests { #[test] fn noise_initiator_test_vectors() { let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); - let secp_ctx = Secp256k1::signing_only(); + let node_signer = TestNodeSigner::new(our_node_id); { // transport-initiator successful handshake let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); + assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { @@ -602,7 +628,7 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).is_err()); + assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err()); } { @@ -610,7 +636,7 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).is_err()); + assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err()); } { @@ -618,7 +644,7 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).is_err()); + assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err()); } } @@ -626,7 +652,8 @@ mod tests { fn noise_responder_test_vectors() { let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); - let secp_ctx = Secp256k1::signing_only(); + let secp_ctx = Secp256k1::new(); + let node_signer = TestNodeSigner::new(our_node_id); { let _ = get_inbound_peer_for_test_vectors(); @@ -637,31 +664,31 @@ mod tests { } { // transport-responder act1 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).is_err()); + assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); } { // transport-responder act1 bad key serialization test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one =hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).is_err()); + assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); } { // transport-responder act1 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).is_err()); + assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); } { // transport-responder act3 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); @@ -672,30 +699,30 @@ mod tests { } { // transport-responder act3 bad MAC for ciphertext test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } { // transport-responder act3 bad rs test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } { // transport-responder act3 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id, &secp_ctx); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); @@ -708,13 +735,13 @@ mod tests { // We use the same keys as the initiator and responder test vectors, so we copy those tests // here and use them to encrypt. let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - let secp_ctx = Secp256k1::signing_only(); { let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); + let node_signer = TestNodeSigner::new(our_node_id); let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id, &secp_ctx).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); + assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index dffda9967ba..a63f764cd8f 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 @@ -557,12 +557,13 @@ pub struct PeerManager } @@ -592,10 +593,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 +611,19 @@ impl PeerManager Self { + pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, 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{}) + }, 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 +638,12 @@ impl PeerManager Self { + pub fn new_routing_only(routing_message_handler: RM, 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{}) + }, current_time, ephemeral_random_data, logger, IgnoringMessageHandler{}, node_signer) } } @@ -685,12 +688,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 +704,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, 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); @@ -713,12 +718,12 @@ impl) -> Result<(), PeerHandleError> { - let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.our_node_secret, &self.secp_ctx); + let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.node_signer); let pending_read_buffer = [0; 50].to_vec(); // Noise act one is 50 bytes let mut peers = self.peers.write().unwrap(); @@ -1079,14 +1084,14 @@ impl { let act_two = try_potential_handleerror!(peer, peer.channel_encryptor .process_act_one_with_keys(&peer.pending_read_buffer[..], - &self.our_node_secret, self.get_ephemeral_key(), &self.secp_ctx)).to_vec(); + &self.node_signer, self.get_ephemeral_key(), &self.secp_ctx)).to_vec(); peer.pending_outbound_buffer.push_back(act_two); peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long }, NextNoiseStep::ActTwo => { let (act_three, their_node_id) = try_potential_handleerror!(peer, peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], - &self.our_node_secret, &self.secp_ctx)); + &self.node_signer)); peer.pending_outbound_buffer.push_back(act_three.to_vec()); peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes peer.pending_read_is_header = true; @@ -2016,13 +2021,20 @@ impl sig, + Err(_) => { + log_error!(self.logger, "Failed to generate signature for node_announcement"); + return; + }, + }; let msg = msgs::NodeAnnouncement { signature: node_announce_sig, @@ -2050,14 +2062,14 @@ fn is_gossip_msg(type_id: u16) -> bool { #[cfg(test)] mod tests { + use crate::chain::keysinterface::{NodeSigner, Recipient}; use crate::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler, filter_addresses}; use crate::ln::{msgs, wire}; use crate::ln::msgs::NetAddress; use crate::util::events; use crate::util::test_utils; - use bitcoin::secp256k1::Secp256k1; - use bitcoin::secp256k1::{SecretKey, PublicKey}; + use bitcoin::secp256k1::SecretKey; use crate::prelude::*; use crate::sync::{Arc, Mutex}; @@ -2093,16 +2105,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,22 +2125,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, 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) { - let secp_ctx = Secp256k1::new(); - let a_id = PublicKey::from_secret_key(&secp_ctx, &peer_a.our_node_secret); + fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { + let a_id = peer_a.node_signer.get_node_id(Recipient::Node).unwrap(); let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let initial_data = peer_b.new_outbound_connection(a_id, fd_b.clone(), None).unwrap(); @@ -2157,8 +2170,7 @@ mod tests { establish_connection(&peers[0], &peers[1]); assert_eq!(peers[0].peers.read().unwrap().len(), 1); - let secp_ctx = Secp256k1::new(); - let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].our_node_secret); + let their_id = peers[1].node_signer.get_node_id(Recipient::Node).unwrap(); chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError { node_id: their_id, @@ -2182,8 +2194,7 @@ mod tests { let (fd_a, mut fd_b) = establish_connection(&peers[0], &peers[1]); assert_eq!(peers[0].peers.read().unwrap().len(), 1); - let secp_ctx = Secp256k1::new(); - let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].our_node_secret); + let their_id = peers[1].node_signer.get_node_id(Recipient::Node).unwrap(); let msg = msgs::Shutdown { channel_id: [42; 32], scriptpubkey: bitcoin::Script::new() }; a_chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::SendShutdown { @@ -2283,8 +2294,7 @@ mod tests { cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release); let peers = create_network(2, &cfgs); - let secp_ctx = Secp256k1::new(); - let a_id = PublicKey::from_secret_key(&secp_ctx, &peers[0].our_node_secret); + let a_id = peers[0].node_signer.get_node_id(Recipient::Node).unwrap(); let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let initial_data = peers[1].new_outbound_connection(a_id, fd_b.clone(), None).unwrap(); diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index 9bfed7e2c20..aca781b9fd6 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/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index 144b0e711b2..1309baf60ea 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -30,8 +30,7 @@ struct MessengerNode { impl MessengerNode { fn get_node_pk(&self) -> PublicKey { - let secp_ctx = Secp256k1::new(); - PublicKey::from_secret_key(&secp_ctx, &self.keys_manager.get_node_secret(Recipient::Node).unwrap()) + self.keys_manager.get_node_id(Recipient::Node).unwrap() } } diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs index dfec1be7e91..769d00ecf55 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 f528ae2d547..221cc1c6258 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -51,7 +51,7 @@ use crate::sync::{Mutex, Arc}; use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use core::mem; use bitcoin::bech32::u5; -use crate::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider}; +use crate::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, NodeSigner, SignerProvider}; #[cfg(feature = "std")] use std::time::{SystemTime, UNIX_EPOCH}; @@ -107,17 +107,6 @@ pub struct OnlyReadsKeysInterface {} impl EntropySource for OnlyReadsKeysInterface { fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }} -impl NodeSigner for OnlyReadsKeysInterface { - fn get_node_secret(&self, _recipient: Recipient) -> Result { unreachable!(); } - fn get_node_id(&self, recipient: Recipient) -> Result { - let secp_ctx = Secp256k1::signing_only(); - Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?)) - } - fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&Scalar>) -> Result { unreachable!(); } - fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!(); } - fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!(); } -} - impl SignerProvider for OnlyReadsKeysInterface { type Signer = EnforcingSigner; @@ -126,8 +115,7 @@ impl SignerProvider for OnlyReadsKeysInterface { fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer { unreachable!(); } fn read_chan_signer(&self, mut reader: &[u8]) -> Result { - let dummy_sk = SecretKey::from_slice(&[42; 32]).unwrap(); - let inner: InMemorySigner = ReadableArgs::read(&mut reader, dummy_sk)?; + let inner: InMemorySigner = Readable::read(&mut reader)?; let state = Arc::new(Mutex::new(EnforcementState::new())); Ok(EnforcingSigner::new_with_revoked( @@ -632,6 +620,49 @@ 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_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>, @@ -651,10 +682,6 @@ impl EntropySource for TestKeysInterface { } impl NodeSigner for TestKeysInterface { - fn get_node_secret(&self, recipient: Recipient) -> Result { - self.backing.get_node_secret(recipient) - } - fn get_node_id(&self, recipient: Recipient) -> Result { self.backing.get_node_id(recipient) } @@ -670,6 +697,10 @@ impl NodeSigner for TestKeysInterface { fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { self.backing.sign_invoice(hrp_bytes, invoice_data, recipient) } + + fn sign_gossip_message(&self, msg: msgs::UnsignedGossipMessage) -> Result { + self.backing.sign_gossip_message(msg) + } } impl SignerProvider for TestKeysInterface { @@ -688,7 +719,7 @@ impl SignerProvider for TestKeysInterface { fn read_chan_signer(&self, buffer: &[u8]) -> Result { let mut reader = io::Cursor::new(buffer); - let inner: InMemorySigner = ReadableArgs::read(&mut reader, self.get_node_secret(Recipient::Node).unwrap())?; + let inner: InMemorySigner = Readable::read(&mut reader)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); Ok(EnforcingSigner::new_with_revoked(