X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=62a2b7b51e52b723231fec7bec63f088c4c793a2;hb=33720b07a06e70cef099639d054aada6bb96a3d5;hp=1f17c4dbac2c95ec67fbb3ed239e100dbe117416;hpb=d66c70eed4c71119f9a44aa31b9f00d3677e7333;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 1f17c4db..62a2b7b5 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -35,7 +35,8 @@ 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::{WriteableEcdsaChannelSigner, EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient}; +use crate::routing::gossip::NodeId; use crate::util::events::ClosureReason; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter}; use crate::util::logger::Logger; @@ -498,7 +499,7 @@ pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5; // // Holder designates channel data owned for the benefice of the user client. // Counterparty designates channel data owned by the another channel participant entity. -pub(super) struct Channel { +pub(super) struct Channel { config: LegacyChannelConfig, // Track the previous `ChannelConfig` so that we can continue forwarding HTLCs that were @@ -832,7 +833,7 @@ macro_rules! secp_check { }; } -impl Channel { +impl Channel { /// Returns the value to use for `holder_max_htlc_value_in_flight_msat` as a percentage of the /// `channel_value_satoshis` in msat, set through /// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`] @@ -2427,7 +2428,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())); @@ -2481,7 +2489,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 @@ -3785,7 +3793,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); @@ -3820,7 +3835,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); @@ -3972,9 +3987,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 @@ -4038,7 +4058,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. @@ -5010,9 +5030,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, @@ -5058,7 +5083,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)); } } @@ -5084,13 +5109,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 @@ -5111,8 +5148,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)); @@ -5152,8 +5189,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)) } @@ -5170,7 +5207,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?"); @@ -5370,7 +5407,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())); } @@ -5378,24 +5417,33 @@ impl Channel { return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned())); } - let were_node_one = node_id.serialize()[..] < self.counterparty_node_id.serialize()[..]; + let node_id = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node) + .map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?); + let counterparty_node_id = NodeId::from_pubkey(&self.get_counterparty_node_id()); + let were_node_one = node_id.as_slice() < counterparty_node_id.as_slice(); let msg = msgs::UnsignedChannelAnnouncement { features: channelmanager::provided_channel_features(&user_config), chain_hash, short_channel_id: self.get_short_channel_id().unwrap(), - node_id_1: if were_node_one { node_id } else { self.get_counterparty_node_id() }, - node_id_2: if were_node_one { self.get_counterparty_node_id() } else { node_id }, - bitcoin_key_1: if were_node_one { self.get_holder_pubkeys().funding_pubkey } else { self.counterparty_funding_pubkey().clone() }, - bitcoin_key_2: if were_node_one { self.counterparty_funding_pubkey().clone() } else { self.get_holder_pubkeys().funding_pubkey }, + node_id_1: if were_node_one { node_id } else { counterparty_node_id }, + node_id_2: if were_node_one { counterparty_node_id } else { node_id }, + bitcoin_key_1: NodeId::from_pubkey(if were_node_one { &self.get_holder_pubkeys().funding_pubkey } else { self.counterparty_funding_pubkey() }), + bitcoin_key_2: NodeId::from_pubkey(if were_node_one { self.counterparty_funding_pubkey() } else { &self.get_holder_pubkeys().funding_pubkey }), excess_data: Vec::new(), }; 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; } @@ -5414,14 +5462,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; @@ -5440,11 +5495,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 = NodeId::from_pubkey(&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 }, @@ -5461,8 +5522,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()[..])[..]); @@ -5483,20 +5547,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, } @@ -6069,7 +6135,7 @@ impl Readable for AnnouncementSigsState { } } -impl Writeable for Channel { +impl Writeable for Channel { fn write(&self, writer: &mut W) -> Result<(), io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been // called. @@ -6837,22 +6903,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::{ChannelSigner, 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::*; @@ -6891,21 +6954,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; @@ -7360,7 +7408,7 @@ mod tests { use bitcoin::hashes::hex::FromHex; use bitcoin::hash_types::Txid; use bitcoin::secp256k1::Message; - use crate::chain::keysinterface::BaseSign; + use crate::chain::keysinterface::EcdsaChannelSigner; use crate::ln::PaymentPreimage; use crate::ln::channel::{HTLCOutputInCommitment ,TxCreationKeys}; use crate::ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; @@ -7374,7 +7422,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(),