From: Arik Sosman Date: Fri, 21 Jul 2023 19:11:20 +0000 (-0700) Subject: Introduce ChannelSignerType. X-Git-Tag: v0.0.117-alpha1~47^2~1 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=b609bd92495b7a80d437ab5e9ab82a8bdcdd5e09;p=rust-lightning Introduce ChannelSignerType. Rather than using a holder_signer of a specific signer type in Channel and ChannelContext, this allows us to hold an enum such that depending on the type of channel, the appropriate signer could be held in its respective variant. Doing so required the reparametrization of Channel from using a Signer to using the SignerProvider trait. This percolated down to the ChannelManager and multiple tests. Now, when accessign various signer methods, there is a distinction between accessing methods defined for all signers on ChannelSigner, and accessing type-specific methods using accessors such as `as_ecdsa`. --- diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 8cb5e9e17..e6c559564 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, CLOSED_CHANNEL_UPDATE_ID}; use crate::chain::transaction::{OutPoint, TransactionData}; -use crate::sign::{WriteableEcdsaChannelSigner, EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient}; +use crate::sign::{EcdsaChannelSigner, WriteableEcdsaChannelSigner, EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient}; use crate::events::ClosureReason; use crate::routing::gossip::NodeId; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter}; @@ -51,6 +51,7 @@ use core::ops::Deref; #[cfg(any(test, fuzzing, debug_assertions))] use crate::sync::Mutex; use bitcoin::hashes::hex::ToHex; +use crate::sign::type_resolver::ChannelSignerType; #[cfg(test)] pub struct ChannelValueStat { @@ -624,7 +625,7 @@ impl UnfundedChannelContext { } /// Contains everything about the channel including state, and various flags. -pub(super) struct ChannelContext { +pub(super) struct ChannelContext where SP::Target: SignerProvider { config: LegacyChannelConfig, // Track the previous `ChannelConfig` so that we can continue forwarding HTLCs that were @@ -657,7 +658,7 @@ pub(super) struct ChannelContext { latest_monitor_update_id: u64, - holder_signer: Signer, + holder_signer: ChannelSignerType<::Signer>, shutdown_scriptpubkey: Option, destination_script: Script, @@ -883,7 +884,7 @@ pub(super) struct ChannelContext { blocked_monitor_updates: Vec, } -impl ChannelContext { +impl ChannelContext where SP::Target: SignerProvider { /// Allowed in any state (including after shutdown) pub fn get_update_time_counter(&self) -> u32 { self.update_time_counter @@ -1442,7 +1443,7 @@ impl ChannelContext { /// The result is a transaction which we can revoke broadcastership of (ie a "local" transaction) /// TODO Some magic rust shit to compile-time check this? fn build_holder_transaction_keys(&self, commitment_number: u64) -> TxCreationKeys { - let per_commitment_point = self.holder_signer.get_per_commitment_point(commitment_number, &self.secp_ctx); + let per_commitment_point = self.holder_signer.as_ref().get_per_commitment_point(commitment_number, &self.secp_ctx); let delayed_payment_base = &self.get_holder_pubkeys().delayed_payment_basepoint; let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint; let counterparty_pubkeys = self.get_counterparty_pubkeys(); @@ -2035,8 +2036,8 @@ fn commit_tx_fee_msat(feerate_per_kw: u32, num_htlcs: usize, channel_type_featur // // Holder designates channel data owned for the benefit of the user client. // Counterparty designates channel data owned by the another channel participant entity. -pub(super) struct Channel { - pub context: ChannelContext, +pub(super) struct Channel where SP::Target: SignerProvider { + pub context: ChannelContext, } #[cfg(any(test, fuzzing))] @@ -2048,7 +2049,10 @@ struct CommitmentTxInfoCached { feerate: u32, } -impl Channel { +impl Channel where + SP::Target: SignerProvider, + ::Signer: WriteableEcdsaChannelSigner +{ fn check_remote_fee( channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator, feerate_per_kw: u32, cur_feerate_per_kw: Option, logger: &L @@ -2463,11 +2467,10 @@ impl Channel { /// Handles a funding_signed message from the remote end. /// If this call is successful, broadcast the funding transaction (and not before!) - pub fn funding_signed( + pub fn funding_signed( &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result, ChannelError> + ) -> Result::Signer>, ChannelError> where - SP::Target: SignerProvider, L::Target: Logger { if !self.context.is_outbound() { @@ -2512,7 +2515,7 @@ impl Channel { self.context.counterparty_funding_pubkey() ); - self.context.holder_signer.validate_holder_commitment(&holder_commitment_tx, Vec::new()) + self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()) .map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?; @@ -2964,7 +2967,7 @@ impl Channel { self.context.counterparty_funding_pubkey() ); - self.context.holder_signer.validate_holder_commitment(&holder_commitment_tx, commitment_stats.preimages) + self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.preimages) .map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?; // Update state now that we've passed all the can-fail calls... @@ -3240,10 +3243,14 @@ impl Channel { *self.context.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None; } - self.context.holder_signer.validate_counterparty_revocation( - self.context.cur_counterparty_commitment_transaction_number + 1, - &secret - ).map_err(|_| ChannelError::Close("Failed to validate revocation from peer".to_owned()))?; + match &self.context.holder_signer { + ChannelSignerType::Ecdsa(ecdsa) => { + ecdsa.validate_counterparty_revocation( + self.context.cur_counterparty_commitment_transaction_number + 1, + &secret + ).map_err(|_| ChannelError::Close("Failed to validate revocation from peer".to_owned()))?; + } + }; self.context.commitment_secrets.provide_secret(self.context.cur_counterparty_commitment_transaction_number + 1, msg.per_commitment_secret) .map_err(|_| ChannelError::Close("Previous secrets did not match new one".to_owned()))?; @@ -3677,7 +3684,7 @@ impl Channel { assert!(!self.context.is_outbound() || self.context.minimum_depth == Some(0), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); self.context.monitor_pending_channel_ready = false; - let next_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); Some(msgs::ChannelReady { channel_id: self.context.channel_id(), next_per_commitment_point, @@ -3732,7 +3739,7 @@ impl Channel { if self.context.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(ChannelError::Close("Peer sent update_fee when we needed a channel_reestablish".to_owned())); } - Channel::::check_remote_fee(&self.context.channel_type, fee_estimator, msg.feerate_per_kw, Some(self.context.feerate_per_kw), logger)?; + Channel::::check_remote_fee(&self.context.channel_type, fee_estimator, msg.feerate_per_kw, Some(self.context.feerate_per_kw), logger)?; let feerate_over_dust_buffer = msg.feerate_per_kw > self.context.get_dust_buffer_feerate(None); self.context.pending_update_fee = Some((msg.feerate_per_kw, FeeUpdateState::RemoteAnnounced)); @@ -3759,8 +3766,8 @@ impl Channel { } fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK { - let next_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); - let per_commitment_secret = self.context.holder_signer.release_commitment_secret(self.context.cur_holder_commitment_transaction_number + 2); + let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.cur_holder_commitment_transaction_number + 2); msgs::RevokeAndACK { channel_id: self.context.channel_id, per_commitment_secret, @@ -3863,7 +3870,7 @@ impl Channel { } if msg.next_remote_commitment_number > 0 { - let expected_point = self.context.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.context.secp_ctx); + let expected_point = self.context.holder_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.context.secp_ctx); let given_secret = SecretKey::from_slice(&msg.your_last_per_commitment_secret) .map_err(|_| ChannelError::Close("Peer sent a garbage channel_reestablish with unparseable secret key".to_owned()))?; if expected_point != PublicKey::from_secret_key(&self.context.secp_ctx, &given_secret) { @@ -3928,7 +3935,7 @@ impl Channel { } // We have OurChannelReady set! - let next_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); return Ok(ReestablishResponses { channel_ready: Some(msgs::ChannelReady { channel_id: self.context.channel_id(), @@ -3968,7 +3975,7 @@ impl Channel { let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number == 1 { // We should never have to worry about MonitorUpdateInProgress resending ChannelReady - let next_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); Some(msgs::ChannelReady { channel_id: self.context.channel_id(), next_per_commitment_point, @@ -4112,20 +4119,24 @@ impl Channel { log_trace!(logger, "Proposing initial closing_signed for our counterparty with a fee range of {}-{} sat (with initial proposal {} sats)", our_min_fee, our_max_fee, total_fee_satoshis); - let sig = self.context.holder_signer - .sign_closing_transaction(&closing_tx, &self.context.secp_ctx) - .map_err(|()| ChannelError::Close("Failed to get signature for closing transaction.".to_owned()))?; + match &self.context.holder_signer { + ChannelSignerType::Ecdsa(ecdsa) => { + let sig = ecdsa + .sign_closing_transaction(&closing_tx, &self.context.secp_ctx) + .map_err(|()| ChannelError::Close("Failed to get signature for closing transaction.".to_owned()))?; - self.context.last_sent_closing_fee = Some((total_fee_satoshis, sig.clone())); - Ok((Some(msgs::ClosingSigned { - channel_id: self.context.channel_id, - fee_satoshis: total_fee_satoshis, - signature: sig, - fee_range: Some(msgs::ClosingSignedFeeRange { - min_fee_satoshis: our_min_fee, - max_fee_satoshis: our_max_fee, - }), - }), None)) + self.context.last_sent_closing_fee = Some((total_fee_satoshis, sig.clone())); + Ok((Some(msgs::ClosingSigned { + channel_id: self.context.channel_id, + fee_satoshis: total_fee_satoshis, + signature: sig, + fee_range: Some(msgs::ClosingSignedFeeRange { + min_fee_satoshis: our_min_fee, + max_fee_satoshis: our_max_fee, + }), + }), None)) + } + } } // Marks a channel as waiting for a response from the counterparty. If it's not received @@ -4150,10 +4161,9 @@ impl Channel { *ticks_elapsed >= DISCONNECT_PEER_AWAITING_RESPONSE_TICKS } - pub fn shutdown( + pub fn shutdown( &mut self, signer_provider: &SP, their_features: &InitFeatures, msg: &msgs::Shutdown ) -> Result<(Option, Option, Vec<(HTLCSource, PaymentHash)>), ChannelError> - where SP::Target: SignerProvider { if self.context.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish".to_owned())); @@ -4342,27 +4352,31 @@ impl Channel { self.build_closing_transaction($new_fee, false) }; - let sig = self.context.holder_signer - .sign_closing_transaction(&closing_tx, &self.context.secp_ctx) - .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?; - - let signed_tx = if $new_fee == msg.fee_satoshis { - self.context.channel_state = ChannelState::ShutdownComplete as u32; - self.context.update_time_counter += 1; - let tx = self.build_signed_closing_transaction(&closing_tx, &msg.signature, &sig); - Some(tx) - } else { None }; + return match &self.context.holder_signer { + ChannelSignerType::Ecdsa(ecdsa) => { + let sig = ecdsa + .sign_closing_transaction(&closing_tx, &self.context.secp_ctx) + .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?; - self.context.last_sent_closing_fee = Some((used_fee, sig.clone())); - return Ok((Some(msgs::ClosingSigned { - channel_id: self.context.channel_id, - fee_satoshis: used_fee, - signature: sig, - fee_range: Some(msgs::ClosingSignedFeeRange { - min_fee_satoshis: our_min_fee, - max_fee_satoshis: our_max_fee, - }), - }), signed_tx)) + let signed_tx = if $new_fee == msg.fee_satoshis { + self.context.channel_state = ChannelState::ShutdownComplete as u32; + self.context.update_time_counter += 1; + let tx = self.build_signed_closing_transaction(&closing_tx, &msg.signature, &sig); + Some(tx) + } else { None }; + + self.context.last_sent_closing_fee = Some((used_fee, sig.clone())); + Ok((Some(msgs::ClosingSigned { + channel_id: self.context.channel_id, + fee_satoshis: used_fee, + signature: sig, + fee_range: Some(msgs::ClosingSignedFeeRange { + min_fee_satoshis: our_min_fee, + max_fee_satoshis: our_max_fee, + }), + }), signed_tx)) + } + } } } @@ -4473,7 +4487,7 @@ impl Channel { } #[cfg(test)] - pub fn get_signer(&self) -> &Signer { + pub fn get_signer(&self) -> &ChannelSignerType<::Signer> { &self.context.holder_signer } @@ -4658,7 +4672,7 @@ impl Channel { if self.context.channel_state & (ChannelState::MonitorUpdateInProgress as u32) == 0 { if self.context.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { let next_per_commitment_point = - self.context.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.context.secp_ctx); + self.context.holder_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.context.secp_ctx); return Some(msgs::ChannelReady { channel_id: self.context.channel_id, next_per_commitment_point, @@ -4952,26 +4966,30 @@ impl Channel { }, Ok(v) => v }; - let our_bitcoin_sig = match self.context.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.context.secp_ctx) { - Err(_) => { - log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!"); - return None; - }, - Ok(v) => v - }; - let short_channel_id = match self.context.get_short_channel_id() { - Some(scid) => scid, - None => return None, - }; + match &self.context.holder_signer { + ChannelSignerType::Ecdsa(ecdsa) => { + let our_bitcoin_sig = match ecdsa.sign_channel_announcement_with_funding_key(&announcement, &self.context.secp_ctx) { + Err(_) => { + log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!"); + return None; + }, + Ok(v) => v + }; + let short_channel_id = match self.context.get_short_channel_id() { + Some(scid) => scid, + None => return None, + }; - self.context.announcement_sigs_state = AnnouncementSigsState::MessageSent; + self.context.announcement_sigs_state = AnnouncementSigsState::MessageSent; - Some(msgs::AnnouncementSignatures { - channel_id: self.context.channel_id(), - short_channel_id, - node_signature: our_node_sig, - bitcoin_signature: our_bitcoin_sig, - }) + Some(msgs::AnnouncementSignatures { + channel_id: self.context.channel_id(), + short_channel_id, + node_signature: our_node_sig, + bitcoin_signature: our_bitcoin_sig, + }) + } + } } /// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are @@ -4986,15 +5004,19 @@ impl Channel { 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.context.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.context.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 }, - node_signature_2: if were_node_one { their_node_sig } else { our_node_sig }, - bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { their_bitcoin_sig }, - bitcoin_signature_2: if were_node_one { their_bitcoin_sig } else { our_bitcoin_sig }, - contents: announcement, - }) + match &self.context.holder_signer { + ChannelSignerType::Ecdsa(ecdsa) => { + let our_bitcoin_sig = ecdsa.sign_channel_announcement_with_funding_key(&announcement, &self.context.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 }, + node_signature_2: if were_node_one { their_node_sig } else { our_node_sig }, + bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { their_bitcoin_sig }, + bitcoin_signature_2: if were_node_one { their_bitcoin_sig } else { our_bitcoin_sig }, + contents: announcement, + }) + } + } } else { Err(ChannelError::Ignore("Attempted to sign channel announcement before we'd received announcement_signatures".to_string())) } @@ -5320,40 +5342,45 @@ impl Channel { let counterparty_keys = self.context.build_remote_transaction_keys(); let commitment_stats = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger); let counterparty_commitment_txid = commitment_stats.tx.trust().txid(); - let (signature, htlc_signatures); - { - let mut htlcs = Vec::with_capacity(commitment_stats.htlcs_included.len()); - for &(ref htlc, _) in commitment_stats.htlcs_included.iter() { - htlcs.push(htlc); - } + match &self.context.holder_signer { + ChannelSignerType::Ecdsa(ecdsa) => { + let (signature, htlc_signatures); - let res = self.context.holder_signer.sign_counterparty_commitment(&commitment_stats.tx, commitment_stats.preimages, &self.context.secp_ctx) - .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?; - signature = res.0; - htlc_signatures = res.1; + { + let mut htlcs = Vec::with_capacity(commitment_stats.htlcs_included.len()); + for &(ref htlc, _) in commitment_stats.htlcs_included.iter() { + htlcs.push(htlc); + } - log_trace!(logger, "Signed remote commitment tx {} (txid {}) with redeemscript {} -> {} in channel {}", - encode::serialize_hex(&commitment_stats.tx.trust().built_transaction().transaction), - &counterparty_commitment_txid, encode::serialize_hex(&self.context.get_funding_redeemscript()), - log_bytes!(signature.serialize_compact()[..]), log_bytes!(self.context.channel_id())); + let res = ecdsa.sign_counterparty_commitment(&commitment_stats.tx, commitment_stats.preimages, &self.context.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?; + signature = res.0; + htlc_signatures = res.1; + + log_trace!(logger, "Signed remote commitment tx {} (txid {}) with redeemscript {} -> {} in channel {}", + encode::serialize_hex(&commitment_stats.tx.trust().built_transaction().transaction), + &counterparty_commitment_txid, encode::serialize_hex(&self.context.get_funding_redeemscript()), + log_bytes!(signature.serialize_compact()[..]), log_bytes!(self.context.channel_id())); + + for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) { + log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}", + encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.context.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)), + encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &counterparty_keys)), + log_bytes!(counterparty_keys.broadcaster_htlc_key.serialize()), + log_bytes!(htlc_sig.serialize_compact()[..]), log_bytes!(self.context.channel_id())); + } + } - for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) { - log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}", - encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.context.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)), - encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &counterparty_keys)), - log_bytes!(counterparty_keys.broadcaster_htlc_key.serialize()), - log_bytes!(htlc_sig.serialize_compact()[..]), log_bytes!(self.context.channel_id())); + Ok((msgs::CommitmentSigned { + channel_id: self.context.channel_id, + signature, + htlc_signatures, + #[cfg(taproot)] + partial_signature_with_nonce: None, + }, (counterparty_commitment_txid, commitment_stats.htlcs_included))) } } - - Ok((msgs::CommitmentSigned { - channel_id: self.context.channel_id, - signature, - htlc_signatures, - #[cfg(taproot)] - partial_signature_with_nonce: None, - }, (counterparty_commitment_txid, commitment_stats.htlcs_included))) } /// Adds a pending outbound HTLC to this channel, and builds a new remote commitment @@ -5399,10 +5426,10 @@ impl Channel { /// /// May jump to the channel being fully shutdown (see [`Self::is_shutdown`]) in which case no /// [`ChannelMonitorUpdate`] will be returned). - pub fn get_shutdown(&mut self, signer_provider: &SP, their_features: &InitFeatures, + pub fn get_shutdown(&mut self, signer_provider: &SP, their_features: &InitFeatures, target_feerate_sats_per_kw: Option, override_shutdown_script: Option) -> Result<(msgs::Shutdown, Option, Vec<(HTLCSource, PaymentHash)>), APIError> - where SP::Target: SignerProvider { + { for htlc in self.context.pending_outbound_htlcs.iter() { if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { return Err(APIError::APIMisuseError{err: "Cannot begin shutdown with pending HTLCs. Process pending events first".to_owned()}); @@ -5513,20 +5540,19 @@ impl Channel { } /// A not-yet-funded outbound (from holder) channel using V1 channel establishment. -pub(super) struct OutboundV1Channel { - pub context: ChannelContext, +pub(super) struct OutboundV1Channel where SP::Target: SignerProvider { + pub context: ChannelContext, pub unfunded_context: UnfundedChannelContext, } -impl OutboundV1Channel { - pub fn new( +impl OutboundV1Channel where SP::Target: SignerProvider { + pub fn new( fee_estimator: &LowerBoundedFeeEstimator, entropy_source: &ES, signer_provider: &SP, counterparty_node_id: PublicKey, their_features: &InitFeatures, channel_value_satoshis: u64, push_msat: u64, user_id: u128, config: &UserConfig, current_chain_height: u32, outbound_scid_alias: u64 - ) -> Result, APIError> + ) -> Result, APIError> where ES::Target: EntropySource, - SP::Target: SignerProvider, - F::Target: FeeEstimator, + F::Target: FeeEstimator { let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay; let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id); @@ -5615,7 +5641,7 @@ impl OutboundV1Channel { latest_monitor_update_id: 0, - holder_signer, + holder_signer: ChannelSignerType::Ecdsa(holder_signer), shutdown_scriptpubkey, destination_script, @@ -5724,8 +5750,13 @@ impl OutboundV1Channel { fn get_funding_created_signature(&mut self, logger: &L) -> Result where L::Target: Logger { let counterparty_keys = self.context.build_remote_transaction_keys(); let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx; - Ok(self.context.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx) - .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0) + match &self.context.holder_signer { + // TODO (taproot|arik): move match into calling method for Taproot + ChannelSignerType::Ecdsa(ecdsa) => { + Ok(ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0) + } + } } /// Updates channel state with knowledge of the funding transaction's txid/index, and generates @@ -5736,7 +5767,7 @@ impl OutboundV1Channel { /// Do NOT broadcast the funding transaction until after a successful funding_signed call! /// If an Err is returned, it is a ChannelError::Close. pub fn get_funding_created(mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L) - -> Result<(Channel, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger { + -> Result<(Channel, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger { if !self.context.is_outbound() { panic!("Tried to create outbound funding_created message on an inbound channel!"); } @@ -5750,7 +5781,7 @@ impl OutboundV1Channel { } self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo); - self.context.holder_signer.provide_channel_parameters(&self.context.channel_transaction_parameters); + self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters); let signature = match self.get_funding_created_signature(logger) { Ok(res) => res, @@ -5856,7 +5887,7 @@ impl OutboundV1Channel { panic!("Tried to send an open_channel for a channel that has already advanced"); } - let first_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); let keys = self.context.get_holder_pubkeys(); msgs::OpenChannel { @@ -6019,22 +6050,21 @@ impl OutboundV1Channel { } /// A not-yet-funded inbound (from counterparty) channel using V1 channel establishment. -pub(super) struct InboundV1Channel { - pub context: ChannelContext, +pub(super) struct InboundV1Channel where SP::Target: SignerProvider { + pub context: ChannelContext, pub unfunded_context: UnfundedChannelContext, } -impl InboundV1Channel { +impl InboundV1Channel where SP::Target: SignerProvider { /// Creates a new channel from a remote sides' request for one. /// Assumes chain_hash has already been checked and corresponds with what we expect! - pub fn new( + pub fn new( fee_estimator: &LowerBoundedFeeEstimator, entropy_source: &ES, signer_provider: &SP, counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures, their_features: &InitFeatures, msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L, is_0conf: bool, - ) -> Result, ChannelError> + ) -> Result, ChannelError> where ES::Target: EntropySource, - SP::Target: SignerProvider, F::Target: FeeEstimator, L::Target: Logger, { @@ -6104,7 +6134,7 @@ impl InboundV1Channel { if msg.htlc_minimum_msat >= full_channel_value_msat { return Err(ChannelError::Close(format!("Minimum htlc value ({}) was larger than full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat))); } - Channel::::check_remote_fee(&channel_type, fee_estimator, msg.feerate_per_kw, None, logger)?; + Channel::::check_remote_fee(&channel_type, fee_estimator, msg.feerate_per_kw, None, logger)?; let max_counterparty_selected_contest_delay = u16::min(config.channel_handshake_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); if msg.to_self_delay > max_counterparty_selected_contest_delay { @@ -6249,7 +6279,7 @@ impl InboundV1Channel { latest_monitor_update_id: 0, - holder_signer, + holder_signer: ChannelSignerType::Ecdsa(holder_signer), shutdown_scriptpubkey, destination_script, @@ -6384,7 +6414,7 @@ impl InboundV1Channel { /// /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel fn generate_accept_channel_message(&self) -> msgs::AcceptChannel { - let first_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); let keys = self.context.get_holder_pubkeys(); msgs::AcceptChannel { @@ -6446,18 +6476,22 @@ impl InboundV1Channel { log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}", log_bytes!(self.context.channel_id()), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); - let counterparty_signature = self.context.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx) - .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0; + match &self.context.holder_signer { + // TODO (arik): move match into calling method for Taproot + ChannelSignerType::Ecdsa(ecdsa) => { + let counterparty_signature = ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0; - // We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((counterparty_initial_bitcoin_tx.txid, initial_commitment_tx, counterparty_signature)) + // We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish. + Ok((counterparty_initial_bitcoin_tx.txid, initial_commitment_tx, counterparty_signature)) + } + } } - pub fn funding_created( + pub fn funding_created( mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result<(Channel, msgs::FundingSigned, ChannelMonitor), (Self, ChannelError)> + ) -> Result<(Channel, msgs::FundingSigned, ChannelMonitor<::Signer>), (Self, ChannelError)> where - SP::Target: SignerProvider, L::Target: Logger { if self.context.is_outbound() { @@ -6479,7 +6513,7 @@ impl InboundV1Channel { self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo); // This is an externally observable change before we finish all our checks. In particular // funding_created_signature may fail. - self.context.holder_signer.provide_channel_parameters(&self.context.channel_transaction_parameters); + self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters); let (counterparty_initial_commitment_txid, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) { Ok(res) => res, @@ -6502,7 +6536,7 @@ impl InboundV1Channel { self.context.counterparty_funding_pubkey() ); - if let Err(_) = self.context.holder_signer.validate_holder_commitment(&holder_commitment_tx, Vec::new()) { + if let Err(_) = self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()) { return Err((self, ChannelError::Close("Failed to validate our commitment".to_owned()))); } @@ -6606,7 +6640,7 @@ impl Readable for AnnouncementSigsState { } } -impl Writeable for Channel { +impl Writeable for Channel where SP::Target: SignerProvider { 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. @@ -6631,7 +6665,8 @@ impl Writeable for Channel { self.context.latest_monitor_update_id.write(writer)?; let mut key_data = VecWriter(Vec::new()); - self.context.holder_signer.write(&mut key_data)?; + // TODO (taproot|arik): Introduce serialization distinction for non-ECDSA signers. + self.context.holder_signer.as_ecdsa().expect("Only ECDSA signers may be serialized").write(&mut key_data)?; assert!(key_data.0.len() < core::usize::MAX); assert!(key_data.0.len() < core::u32::MAX as usize); (key_data.0.len() as u32).write(writer)?; @@ -6930,7 +6965,7 @@ impl Writeable for Channel { } const MAX_ALLOC_SIZE: usize = 64*1024; -impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)> for Channel<::Signer> +impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)> for Channel where ES::Target: EntropySource, SP::Target: SignerProvider @@ -7329,7 +7364,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch latest_monitor_update_id, - holder_signer, + holder_signer: ChannelSignerType::Ecdsa(holder_signer), shutdown_scriptpubkey, destination_script, @@ -7454,10 +7489,9 @@ mod tests { use crate::chain::transaction::OutPoint; use crate::routing::router::Path; 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 crate::util::test_utils::{OnGetShutdownScriptpubkey, TestKeysInterface}; use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; use bitcoin::secp256k1::ffi::Signature as FFISignature; use bitcoin::secp256k1::{SecretKey,PublicKey}; @@ -7490,7 +7524,7 @@ mod tests { // arithmetic, causing a panic with debug assertions enabled. let fee_est = TestFeeEstimator { fee_est: 42 }; let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_est); - assert!(Channel::::check_remote_fee( + assert!(Channel::<&TestKeysInterface>::check_remote_fee( &ChannelTypeFeatures::only_static_remote_key(), &bounded_fee_estimator, u32::max_value(), None, &&test_utils::TestLogger::new()).is_err()); } @@ -7551,7 +7585,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - match OutboundV1Channel::::new(&LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), &&keys_provider, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) { + match OutboundV1Channel::<&TestKeysInterface>::new(&LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), &&keys_provider, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) { Err(APIError::IncompatibleShutdownScript { script }) => { assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner()); }, @@ -7574,7 +7608,7 @@ mod tests { let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let node_a_chan = OutboundV1Channel::::new(&bounded_fee_estimator, &&keys_provider, &&keys_provider, node_a_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); + let node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&bounded_fee_estimator, &&keys_provider, &&keys_provider, node_a_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); // Now change the fee so we can check that the fee in the open_channel message is the // same as the old fee. @@ -7601,13 +7635,13 @@ mod tests { // Create Node A's channel pointing to Node B's pubkey let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); // Create Node B's channel by receiving Node A's open_channel message // Make sure A's dust limit is as we expect. let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let mut node_b_chan = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); // Node B --> Node A: accept channel, explicitly setting B's dust limit. let mut accept_channel_msg = node_b_chan.accept_inbound_channel(); @@ -7682,7 +7716,7 @@ mod tests { let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut chan = OutboundV1Channel::::new(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); + let mut chan = OutboundV1Channel::<&TestKeysInterface>::new(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); let commitment_tx_fee_0_htlcs = commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.context.get_channel_type()); let commitment_tx_fee_1_htlc = commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.context.get_channel_type()); @@ -7731,12 +7765,12 @@ mod tests { // Create Node A's channel pointing to Node B's pubkey let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); // Create Node B's channel by receiving Node A's open_channel message let open_channel_msg = node_a_chan.get_open_channel(chain_hash); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let mut node_b_chan = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); // Node B --> Node A: accept channel let accept_channel_msg = node_b_chan.accept_inbound_channel(); @@ -7794,12 +7828,12 @@ mod tests { // Test that `OutboundV1Channel::new` creates a channel with the correct value for // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value, // which is set to the lower bound + 1 (2%) of the `channel_value`. - let chan_1 = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_2_percent), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap(); + let chan_1 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_2_percent), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap(); let chan_1_value_msat = chan_1.context.channel_value_satoshis * 1000; assert_eq!(chan_1.context.holder_max_htlc_value_in_flight_msat, (chan_1_value_msat as f64 * 0.02) as u64); // Test with the upper bound - 1 of valid values (99%). - let chan_2 = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_99_percent), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap(); + let chan_2 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_99_percent), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap(); let chan_2_value_msat = chan_2.context.channel_value_satoshis * 1000; assert_eq!(chan_2.context.holder_max_htlc_value_in_flight_msat, (chan_2_value_msat as f64 * 0.99) as u64); @@ -7808,38 +7842,38 @@ mod tests { // Test that `InboundV1Channel::new` creates a channel with the correct value for // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value, // which is set to the lower bound - 1 (2%) of the `channel_value`. - let chan_3 = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_2_percent), &channelmanager::provided_init_features(&config_2_percent), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_3 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_2_percent), &channelmanager::provided_init_features(&config_2_percent), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); let chan_3_value_msat = chan_3.context.channel_value_satoshis * 1000; assert_eq!(chan_3.context.holder_max_htlc_value_in_flight_msat, (chan_3_value_msat as f64 * 0.02) as u64); // Test with the upper bound - 1 of valid values (99%). - let chan_4 = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_99_percent), &channelmanager::provided_init_features(&config_99_percent), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_4 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_99_percent), &channelmanager::provided_init_features(&config_99_percent), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); let chan_4_value_msat = chan_4.context.channel_value_satoshis * 1000; assert_eq!(chan_4.context.holder_max_htlc_value_in_flight_msat, (chan_4_value_msat as f64 * 0.99) as u64); // Test that `OutboundV1Channel::new` uses the lower bound of the configurable percentage values (1%) // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1. - let chan_5 = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_0_percent), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap(); + let chan_5 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_0_percent), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap(); let chan_5_value_msat = chan_5.context.channel_value_satoshis * 1000; assert_eq!(chan_5.context.holder_max_htlc_value_in_flight_msat, (chan_5_value_msat as f64 * 0.01) as u64); // Test that `OutboundV1Channel::new` uses the upper bound of the configurable percentage values // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value // than 100. - let chan_6 = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_101_percent), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap(); + let chan_6 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_101_percent), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap(); let chan_6_value_msat = chan_6.context.channel_value_satoshis * 1000; assert_eq!(chan_6.context.holder_max_htlc_value_in_flight_msat, chan_6_value_msat); // Test that `InboundV1Channel::new` uses the lower bound of the configurable percentage values (1%) // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1. - let chan_7 = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_0_percent), &channelmanager::provided_init_features(&config_0_percent), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_7 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_0_percent), &channelmanager::provided_init_features(&config_0_percent), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); let chan_7_value_msat = chan_7.context.channel_value_satoshis * 1000; assert_eq!(chan_7.context.holder_max_htlc_value_in_flight_msat, (chan_7_value_msat as f64 * 0.01) as u64); // Test that `InboundV1Channel::new` uses the upper bound of the configurable percentage values // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value // than 100. - let chan_8 = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_101_percent), &channelmanager::provided_init_features(&config_101_percent), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_8 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_101_percent), &channelmanager::provided_init_features(&config_101_percent), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); let chan_8_value_msat = chan_8.context.channel_value_satoshis * 1000; assert_eq!(chan_8.context.holder_max_htlc_value_in_flight_msat, chan_8_value_msat); } @@ -7879,7 +7913,7 @@ mod tests { let mut outbound_node_config = UserConfig::default(); outbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (outbound_selected_channel_reserve_perc * 1_000_000.0) as u32; - let chan = OutboundV1Channel::::new(&&fee_est, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&outbound_node_config), channel_value_satoshis, 100_000, 42, &outbound_node_config, 0, 42).unwrap(); + let chan = OutboundV1Channel::<&TestKeysInterface>::new(&&fee_est, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&outbound_node_config), channel_value_satoshis, 100_000, 42, &outbound_node_config, 0, 42).unwrap(); let expected_outbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.context.channel_value_satoshis as f64 * outbound_selected_channel_reserve_perc) as u64); assert_eq!(chan.context.holder_selected_channel_reserve_satoshis, expected_outbound_selected_chan_reserve); @@ -7889,7 +7923,7 @@ mod tests { inbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (inbound_selected_channel_reserve_perc * 1_000_000.0) as u32; if outbound_selected_channel_reserve_perc + inbound_selected_channel_reserve_perc < 1.0 { - let chan_inbound_node = InboundV1Channel::::new(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_inbound_node = InboundV1Channel::<&TestKeysInterface>::new(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, /*is_0conf=*/false).unwrap(); let expected_inbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.context.channel_value_satoshis as f64 * inbound_selected_channel_reserve_perc) as u64); @@ -7897,7 +7931,7 @@ mod tests { assert_eq!(chan_inbound_node.context.counterparty_selected_channel_reserve_satoshis.unwrap(), expected_outbound_selected_chan_reserve); } else { // Channel Negotiations failed - let result = InboundV1Channel::::new(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, /*is_0conf=*/false); + let result = InboundV1Channel::<&TestKeysInterface>::new(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, /*is_0conf=*/false); assert!(result.is_err()); } } @@ -7916,13 +7950,13 @@ mod tests { // Create Node A's channel pointing to Node B's pubkey let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); // Create Node B's channel by receiving Node A's open_channel message // Make sure A's dust limit is as we expect. let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let mut node_b_chan = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); // Node B --> Node A: accept channel, explicitly setting B's dust limit. let mut accept_channel_msg = node_b_chan.accept_inbound_channel(); @@ -8016,7 +8050,7 @@ mod tests { let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut config = UserConfig::default(); config.channel_handshake_config.announced_channel = false; - let mut chan = OutboundV1Channel::::new(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, &&keys_provider, counterparty_node_id, &channelmanager::provided_init_features(&config), 10_000_000, 0, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test + let mut chan = OutboundV1Channel::<&Keys>::new(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, &&keys_provider, counterparty_node_id, &channelmanager::provided_init_features(&config), 10_000_000, 0, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test chan.context.holder_dust_limit_satoshis = 546; chan.context.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel @@ -8049,10 +8083,10 @@ mod tests { // We can't just use build_holder_transaction_keys here as the per_commitment_secret is not // derived from a commitment_seed, so instead we copy it here and call // build_commitment_transaction. - let delayed_payment_base = &chan.context.holder_signer.pubkeys().delayed_payment_basepoint; + let delayed_payment_base = &chan.context.holder_signer.as_ref().pubkeys().delayed_payment_basepoint; let per_commitment_secret = SecretKey::from_slice(&hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); - let htlc_basepoint = &chan.context.holder_signer.pubkeys().htlc_basepoint; + let htlc_basepoint = &chan.context.holder_signer.as_ref().pubkeys().htlc_basepoint; let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint); macro_rules! test_commitment { @@ -8104,7 +8138,7 @@ mod tests { commitment_tx.clone(), counterparty_signature, counterparty_htlc_sigs, - &chan.context.holder_signer.pubkeys().funding_pubkey, + &chan.context.holder_signer.as_ref().pubkeys().funding_pubkey, chan.context.counterparty_funding_pubkey() ); let (holder_sig, htlc_sigs) = signer.sign_holder_commitment_and_htlcs(&holder_commitment_tx, &secp_ctx).unwrap(); @@ -8749,7 +8783,7 @@ mod tests { let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let node_a_chan = OutboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, + let node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap(); let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key(); @@ -8758,7 +8792,7 @@ mod tests { let mut open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); open_channel_msg.channel_type = Some(channel_type_features); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let res = InboundV1Channel::::new(&feeest, &&keys_provider, &&keys_provider, + let res = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false); assert!(res.is_ok()); @@ -8782,7 +8816,7 @@ mod tests { // It is not enough for just the initiator to signal `option_anchors_zero_fee_htlc_tx`, both // need to signal it. - let channel_a = OutboundV1Channel::::new( + let channel_a = OutboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &channelmanager::provided_init_features(&UserConfig::default()), 10000000, 100000, 42, &config, 0, 42 @@ -8793,13 +8827,13 @@ mod tests { expected_channel_type.set_static_remote_key_required(); expected_channel_type.set_anchors_zero_fee_htlc_tx_required(); - let channel_a = OutboundV1Channel::::new( + let channel_a = OutboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42 ).unwrap(); let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash()); - let channel_b = InboundV1Channel::::new( + let channel_b = InboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false @@ -8830,7 +8864,7 @@ mod tests { let raw_init_features = static_remote_key_required | simple_anchors_required; let init_features_with_simple_anchors = InitFeatures::from_le_bytes(raw_init_features.to_le_bytes().to_vec()); - let channel_a = OutboundV1Channel::::new( + let channel_a = OutboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42 ).unwrap(); @@ -8841,7 +8875,7 @@ mod tests { // Since A supports both `static_remote_key` and `option_anchors`, but B only accepts // `static_remote_key`, it will fail the channel. - let channel_b = InboundV1Channel::::new( + let channel_b = InboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, &channelmanager::provided_channel_type_features(&config), &init_features_with_simple_anchors, &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false @@ -8876,7 +8910,7 @@ mod tests { // First, we'll try to open a channel between A and B where A requests a channel type for // the original `option_anchors` feature (non zero fee htlc tx). This should be rejected by // B as it's not supported by LDK. - let channel_a = OutboundV1Channel::::new( + let channel_a = OutboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42 ).unwrap(); @@ -8884,7 +8918,7 @@ mod tests { let mut open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash()); open_channel_msg.channel_type = Some(simple_anchors_channel_type.clone()); - let res = InboundV1Channel::::new( + let res = InboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, &channelmanager::provided_channel_type_features(&config), &simple_anchors_init, &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false @@ -8895,14 +8929,14 @@ mod tests { // `anchors_zero_fee_htlc_tx`. B is malicious and tries to downgrade the channel type to the // original `option_anchors` feature, which should be rejected by A as it's not supported by // LDK. - let mut channel_a = OutboundV1Channel::::new( + let mut channel_a = OutboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &simple_anchors_init, 10000000, 100000, 42, &config, 0, 42 ).unwrap(); let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash()); - let channel_b = InboundV1Channel::::new( + let channel_b = InboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5d2fad1c7..1df16efb7 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -55,7 +55,7 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; use crate::ln::outbound_payment; use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs}; use crate::ln::wire::Encode; -use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, ChannelSigner, WriteableEcdsaChannelSigner}; +use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, WriteableEcdsaChannelSigner}; use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate}; use crate::util::wakers::{Future, Notifier}; use crate::util::scid_utils::fake_scid; @@ -659,23 +659,23 @@ impl_writeable_tlv_based_enum!(RAAMonitorUpdateBlockingAction, /// State we hold per-peer. -pub(super) struct PeerState { +pub(super) struct PeerState where SP::Target: SignerProvider { /// `channel_id` -> `Channel`. /// /// Holds all funded channels where the peer is the counterparty. - pub(super) channel_by_id: HashMap<[u8; 32], Channel>, + pub(super) channel_by_id: HashMap<[u8; 32], Channel>, /// `temporary_channel_id` -> `OutboundV1Channel`. /// /// Holds all outbound V1 channels where the peer is the counterparty. Once an outbound channel has /// been assigned a `channel_id`, the entry in this map is removed and one is created in /// `channel_by_id`. - pub(super) outbound_v1_channel_by_id: HashMap<[u8; 32], OutboundV1Channel>, + pub(super) outbound_v1_channel_by_id: HashMap<[u8; 32], OutboundV1Channel>, /// `temporary_channel_id` -> `InboundV1Channel`. /// /// Holds all inbound V1 channels where the peer is the counterparty. Once an inbound channel has /// been assigned a `channel_id`, the entry in this map is removed and one is created in /// `channel_by_id`. - pub(super) inbound_v1_channel_by_id: HashMap<[u8; 32], InboundV1Channel>, + pub(super) inbound_v1_channel_by_id: HashMap<[u8; 32], InboundV1Channel>, /// `temporary_channel_id` -> `InboundChannelRequest`. /// /// When manual channel acceptance is enabled, this holds all unaccepted inbound channels where @@ -721,7 +721,7 @@ pub(super) struct PeerState { is_connected: bool, } -impl PeerState { +impl PeerState where SP::Target: SignerProvider { /// Indicates that a peer meets the criteria where we're ok to remove it from our storage. /// If true is passed for `require_disconnected`, the function will return false if we haven't /// disconnected from the node already, ie. `PeerState::is_connected` is set to `true`. @@ -1146,9 +1146,9 @@ where /// /// See `ChannelManager` struct-level documentation for lock order requirements. #[cfg(not(any(test, feature = "_test_utils")))] - per_peer_state: FairRwLock::Signer>>>>, + per_peer_state: FairRwLock>>>, #[cfg(any(test, feature = "_test_utils"))] - pub(super) per_peer_state: FairRwLock::Signer>>>>, + pub(super) per_peer_state: FairRwLock>>>, /// The set of events which we need to give to the user to handle. In some cases an event may /// require some further action after the user handles it (currently only blocking a monitor @@ -1594,11 +1594,13 @@ impl ChannelDetails { self.short_channel_id.or(self.outbound_scid_alias) } - fn from_channel_context( - context: &ChannelContext, best_block_height: u32, latest_features: InitFeatures, + fn from_channel_context( + context: &ChannelContext, best_block_height: u32, latest_features: InitFeatures, fee_estimator: &LowerBoundedFeeEstimator ) -> Self - where F::Target: FeeEstimator + where + SP::Target: SignerProvider, + F::Target: FeeEstimator { let balance = context.get_available_balances(fee_estimator); let (to_remote_reserve_satoshis, to_self_reserve_satoshis) = @@ -2299,7 +2301,7 @@ where Ok(temporary_channel_id) } - fn list_funded_channels_with_filter::Signer>)) -> bool + Copy>(&self, f: Fn) -> Vec { + fn list_funded_channels_with_filter)) -> bool + Copy>(&self, f: Fn) -> Vec { // Allocate our best estimate of the number of channels we have in the `res` // Vec. Sadly the `short_to_chan_info` map doesn't cover channels without // a scid or a scid alias, and the `id_to_peer` shouldn't be used outside @@ -2425,7 +2427,7 @@ where } /// Helper function that issues the channel close events - fn issue_channel_close_events(&self, context: &ChannelContext<::Signer>, closure_reason: ClosureReason) { + fn issue_channel_close_events(&self, context: &ChannelContext, closure_reason: ClosureReason) { let mut pending_events_lock = self.pending_events.lock().unwrap(); match context.unbroadcasted_funding() { Some(transaction) => { @@ -3115,7 +3117,7 @@ where /// /// [`channel_update`]: msgs::ChannelUpdate /// [`internal_closing_signed`]: Self::internal_closing_signed - fn get_channel_update_for_broadcast(&self, chan: &Channel<::Signer>) -> Result { + fn get_channel_update_for_broadcast(&self, chan: &Channel) -> Result { if !chan.context.should_announce() { return Err(LightningError { err: "Cannot broadcast a channel_update for a private channel".to_owned(), @@ -3140,7 +3142,7 @@ where /// /// [`channel_update`]: msgs::ChannelUpdate /// [`internal_closing_signed`]: Self::internal_closing_signed - fn get_channel_update_for_unicast(&self, chan: &Channel<::Signer>) -> Result { + fn get_channel_update_for_unicast(&self, chan: &Channel) -> Result { log_trace!(self.logger, "Attempting to generate channel update for channel {}", log_bytes!(chan.context.channel_id())); let short_channel_id = match chan.context.get_short_channel_id().or(chan.context.latest_inbound_scid_alias()) { None => return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}), @@ -3150,7 +3152,7 @@ where self.get_channel_update_for_onion(short_channel_id, chan) } - fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel<::Signer>) -> Result { + fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel) -> Result { log_trace!(self.logger, "Generating channel update for channel {}", log_bytes!(chan.context.channel_id())); let were_node_one = self.our_network_pubkey.serialize()[..] < chan.context.get_counterparty_node_id().serialize()[..]; @@ -3444,7 +3446,7 @@ where /// Handles the generation of a funding transaction, optionally (for tests) with a function /// which checks the correctness of the funding transaction given the associated channel. - fn funding_transaction_generated_intern::Signer>, &Transaction) -> Result>( + fn funding_transaction_generated_intern, &Transaction) -> Result>( &self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, funding_transaction: Transaction, find_funding_output: FundingOutput ) -> Result<(), APIError> { let per_peer_state = self.per_peer_state.read().unwrap(); @@ -4362,7 +4364,7 @@ where let _ = self.process_background_events(); } - fn update_channel_fee(&self, chan_id: &[u8; 32], chan: &mut Channel<::Signer>, new_feerate: u32) -> NotifyOption { + fn update_channel_fee(&self, chan_id: &[u8; 32], chan: &mut Channel, new_feerate: u32) -> NotifyOption { if !chan.context.is_outbound() { return NotifyOption::SkipPersist; } // If the feerate has decreased by less than half, don't bother if new_feerate <= chan.context.get_feerate_sat_per_1000_weight() && new_feerate * 2 > chan.context.get_feerate_sat_per_1000_weight() { @@ -4521,7 +4523,7 @@ where let process_unfunded_channel_tick = | chan_id: &[u8; 32], - chan_context: &mut ChannelContext<::Signer>, + chan_context: &mut ChannelContext, unfunded_chan_context: &mut UnfundedChannelContext, pending_msg_events: &mut Vec, | { @@ -4711,7 +4713,7 @@ where /// /// This is for failures on the channel on which the HTLC was *received*, not failures /// forwarding - fn get_htlc_inbound_temp_fail_err_and_data(&self, desired_err_code: u16, chan: &Channel<::Signer>) -> (u16, Vec) { + fn get_htlc_inbound_temp_fail_err_and_data(&self, desired_err_code: u16, chan: &Channel) -> (u16, Vec) { // We can't be sure what SCID was used when relaying inbound towards us, so we have to // guess somewhat. If its a public channel, we figure best to just use the real SCID (as // we're not leaking that we have a channel with the counterparty), otherwise we try to use @@ -4731,7 +4733,7 @@ where /// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code /// that we want to return and a channel. - fn get_htlc_temp_fail_err_and_data(&self, desired_err_code: u16, scid: u64, chan: &Channel<::Signer>) -> (u16, Vec) { + fn get_htlc_temp_fail_err_and_data(&self, desired_err_code: u16, scid: u64, chan: &Channel) -> (u16, Vec) { debug_assert_eq!(desired_err_code & 0x1000, 0x1000); if let Ok(upd) = self.get_channel_update_for_onion(scid, chan) { let mut enc = VecWriter(Vec::with_capacity(upd.serialized_length() + 6)); @@ -5194,7 +5196,7 @@ where /// Handles a channel reentering a functional state, either due to reconnect or a monitor /// update completion. fn handle_channel_resumption(&self, pending_msg_events: &mut Vec, - channel: &mut Channel<::Signer>, raa: Option, + channel: &mut Channel, raa: Option, commitment_update: Option, order: RAACommitmentOrder, pending_forwards: Vec<(PendingHTLCInfo, u64)>, funding_broadcastable: Option, channel_ready: Option, announcement_sigs: Option) @@ -5429,7 +5431,7 @@ where /// The filter is called for each peer and provided with the number of unfunded, inbound, and /// non-0-conf channels we have with the peer. fn peers_without_funded_channels(&self, maybe_count_peer: Filter) -> usize - where Filter: Fn(&PeerState<::Signer>) -> bool { + where Filter: Fn(&PeerState) -> bool { let mut peers_without_funded_channels = 0; let best_block_height = self.best_block.read().unwrap().height(); { @@ -5447,7 +5449,7 @@ where } fn unfunded_channel_count( - peer: &PeerState<::Signer>, best_block_height: u32 + peer: &PeerState, best_block_height: u32 ) -> usize { let mut num_unfunded_channels = 0; for (_, chan) in peer.channel_by_id.iter() { @@ -5893,7 +5895,7 @@ where chan.get().context.config().accept_underpaying_htlcs, next_packet_pk_opt), Err(e) => PendingHTLCStatus::Fail(e) }; - let create_pending_htlc_status = |chan: &Channel<::Signer>, pending_forward_info: PendingHTLCStatus, error_code: u16| { + let create_pending_htlc_status = |chan: &Channel, pending_forward_info: PendingHTLCStatus, error_code: u16| { // If the update_add is completely bogus, the call will Err and we will close, // but if we've sent a shutdown and they haven't acknowledged it yet, we just // want to reject the new HTLC and fail it backwards instead of forwarding. @@ -7055,7 +7057,7 @@ where /// Calls a function which handles an on-chain event (blocks dis/connected, transactions /// un/confirmed, etc) on each channel, handling any resulting errors or messages generated by /// the function. - fn do_chain_event::Signer>) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason>> + fn do_chain_event) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason>> (&self, height_opt: Option, f: FN) { // Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called // during initialization prior to the chain_monitor being fully configured in some cases. @@ -8561,13 +8563,13 @@ where let channel_count: u64 = Readable::read(reader)?; let mut funding_txo_set = HashSet::with_capacity(cmp::min(channel_count as usize, 128)); - let mut peer_channels: HashMap::Signer>>> = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); + let mut peer_channels: HashMap>> = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); let mut id_to_peer = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); let mut channel_closures = VecDeque::new(); let mut close_background_events = Vec::new(); for _ in 0..channel_count { - let mut channel: Channel<::Signer> = Channel::read(reader, ( + let mut channel: Channel = Channel::read(reader, ( &args.entropy_source, &args.signer_provider, best_block_height, &provided_channel_type_features(&args.default_config) ))?; let funding_txo = channel.context.get_funding_txo().ok_or(DecodeError::InvalidValue)?; @@ -8712,7 +8714,7 @@ where }; let peer_count: u64 = Readable::read(reader)?; - let mut per_peer_state = HashMap::with_capacity(cmp::min(peer_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(PublicKey, Mutex::Signer>>)>())); + let mut per_peer_state = HashMap::with_capacity(cmp::min(peer_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(PublicKey, Mutex>)>())); for _ in 0..peer_count { let peer_pubkey = Readable::read(reader)?; let peer_chans = peer_channels.remove(&peer_pubkey).unwrap_or(HashMap::new()); diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 2997a178a..d9e9622ac 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -17,7 +17,7 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator; use crate::chain::channelmonitor; use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY}; use crate::chain::transaction::OutPoint; -use crate::sign::{ChannelSigner, EcdsaChannelSigner, EntropySource}; +use crate::sign::{EcdsaChannelSigner, EntropySource}; use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason}; use crate::ln::{PaymentPreimage, PaymentSecret, PaymentHash}; use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis, OutboundV1Channel, InboundV1Channel}; @@ -703,7 +703,7 @@ fn test_update_fee_that_funder_cannot_afford() { let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); let local_chan = chan_lock.channel_by_id.get(&chan.2).unwrap(); let chan_signer = local_chan.get_signer(); - let pubkeys = chan_signer.pubkeys(); + let pubkeys = chan_signer.as_ref().pubkeys(); (pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, pubkeys.funding_pubkey) }; @@ -712,9 +712,9 @@ fn test_update_fee_that_funder_cannot_afford() { let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); let remote_chan = chan_lock.channel_by_id.get(&chan.2).unwrap(); let chan_signer = remote_chan.get_signer(); - let pubkeys = chan_signer.pubkeys(); + let pubkeys = chan_signer.as_ref().pubkeys(); (pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, - chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), + chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), pubkeys.funding_pubkey) }; @@ -738,7 +738,7 @@ fn test_update_fee_that_funder_cannot_afford() { &mut htlcs, &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable() ); - local_chan_signer.sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap() + local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap() }; let commit_signed_msg = msgs::CommitmentSigned { @@ -1417,23 +1417,23 @@ fn test_fee_spike_violation_fails_htlc() { let local_chan = chan_lock.channel_by_id.get(&chan.2).unwrap(); let chan_signer = local_chan.get_signer(); // Make the signer believe we validated another commitment, so we can release the secret - chan_signer.get_enforcement_state().last_holder_commitment -= 1; + chan_signer.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; - let pubkeys = chan_signer.pubkeys(); + let pubkeys = chan_signer.as_ref().pubkeys(); (pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, - chan_signer.release_commitment_secret(INITIAL_COMMITMENT_NUMBER), - chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx), - chan_signer.pubkeys().funding_pubkey) + chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER), + chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx), + chan_signer.as_ref().pubkeys().funding_pubkey) }; let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point, remote_funding) = { let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); let remote_chan = chan_lock.channel_by_id.get(&chan.2).unwrap(); let chan_signer = remote_chan.get_signer(); - let pubkeys = chan_signer.pubkeys(); + let pubkeys = chan_signer.as_ref().pubkeys(); (pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, - chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), - chan_signer.pubkeys().funding_pubkey) + chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), + chan_signer.as_ref().pubkeys().funding_pubkey) }; // Assemble the set of keys we can use for signatures for our commitment_signed message. @@ -1469,7 +1469,7 @@ fn test_fee_spike_violation_fails_htlc() { &mut vec![(accepted_htlc_info, ())], &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable() ); - local_chan_signer.sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap() + local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), &secp_ctx).unwrap() }; let commit_signed_msg = msgs::CommitmentSigned { @@ -6110,7 +6110,7 @@ fn test_update_add_htlc_bolt2_receiver_zero_value_msat() { nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Remote side tried to send a 0-msat HTLC".to_string(), 1); check_closed_broadcast!(nodes[1], true).unwrap(); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "Remote side tried to send a 0-msat HTLC".to_string() }, + check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "Remote side tried to send a 0-msat HTLC".to_string() }, [nodes[0].node.get_our_node_id()], 100000); } @@ -7593,16 +7593,16 @@ fn test_counterparty_raa_skip_no_crash() { const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; // Make signer believe we got a counterparty signature, so that it allows the revocation - keys.get_enforcement_state().last_holder_commitment -= 1; - per_commitment_secret = keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER); + keys.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; + per_commitment_secret = keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER); // Must revoke without gaps - keys.get_enforcement_state().last_holder_commitment -= 1; - keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1); + keys.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; + keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1); - keys.get_enforcement_state().last_holder_commitment -= 1; + keys.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(), - &SecretKey::from_slice(&keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2)).unwrap()); + &SecretKey::from_slice(&keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2)).unwrap()); } nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index a71bdae88..b86519972 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -54,6 +54,8 @@ use crate::util::atomic_counter::AtomicCounter; use crate::util::chacha20::ChaCha20; use crate::util::invoice::construct_invoice_preimage; +pub(crate) mod type_resolver; + /// Used as initial key material, to be expanded into multiple secret keys (but not to be used /// directly). This is used within LDK to encrypt/decrypt inbound payment data. /// diff --git a/lightning/src/sign/type_resolver.rs b/lightning/src/sign/type_resolver.rs new file mode 100644 index 000000000..8b6e80917 --- /dev/null +++ b/lightning/src/sign/type_resolver.rs @@ -0,0 +1,32 @@ +use crate::sign::{ChannelSigner, EcdsaChannelSigner}; + +pub(crate) enum ChannelSignerType { + // in practice, this will only ever be an EcdsaChannelSigner (specifically, Writeable) + Ecdsa(ECS) +} + +impl ChannelSignerType{ + pub(crate) fn as_ref(&self) -> &dyn ChannelSigner { + match self { + ChannelSignerType::Ecdsa(ecs) => ecs + } + } + + pub(crate) fn as_mut(&mut self) -> &mut dyn ChannelSigner { + match self { + ChannelSignerType::Ecdsa(ecs) => ecs + } + } + + pub(crate) fn as_ecdsa(&self) -> Option<&ECS> { + match self { + ChannelSignerType::Ecdsa(ecs) => Some(ecs) + } + } + + pub(crate) fn as_mut_ecdsa(&mut self) -> Option<&mut ECS> { + match self { + ChannelSignerType::Ecdsa(ecs) => Some(ecs) + } + } +}