X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=9455a76140b5b627a21bb0a948caefa85dc3c1c7;hb=c7a89598fe28aa3f68cc73817752a6cdb6be2534;hp=740d26448073492e5fcaad20170231a8e9012681;hpb=c8ff32197aa78c3e66f4156b44bc3d6580202321;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 740d2644..9455a761 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -35,13 +35,14 @@ use crate::ln::chan_utils; use crate::ln::onion_utils::HTLCFailReason; 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::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, WithChannelMonitor, LATENCY_GRACE_PERIOD_BLOCKS, CLOSED_CHANNEL_UPDATE_ID}; use crate::chain::transaction::{OutPoint, TransactionData}; -use crate::sign::{EcdsaChannelSigner, WriteableEcdsaChannelSigner, EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient}; +use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; +use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient}; use crate::events::ClosureReason; use crate::routing::gossip::NodeId; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; -use crate::util::logger::Logger; +use crate::util::logger::{Logger, Record, WithContext}; use crate::util::errors::APIError; use crate::util::config::{UserConfig, ChannelConfig, LegacyChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits, MaxDustHTLCExposure}; use crate::util::scid_utils::scid_from_parts; @@ -55,6 +56,8 @@ use core::ops::Deref; use crate::sync::Mutex; use crate::sign::type_resolver::ChannelSignerType; +use super::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint}; + #[cfg(test)] pub struct ChannelValueStat { pub value_to_self_msat: u64, @@ -163,6 +166,7 @@ struct InboundHTLCOutput { state: InboundHTLCState, } +#[cfg_attr(test, derive(Clone, Debug, PartialEq))] enum OutboundHTLCState { /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we /// created it we would have put it in the holding cell instead). When they next revoke_and_ack @@ -196,6 +200,7 @@ enum OutboundHTLCState { } #[derive(Clone)] +#[cfg_attr(test, derive(Debug, PartialEq))] enum OutboundHTLCOutcome { /// LDK version 0.0.105+ will always fill in the preimage here. Success(Option), @@ -220,6 +225,7 @@ impl<'a> Into> for &'a OutboundHTLCOutcome { } } +#[cfg_attr(test, derive(Clone, Debug, PartialEq))] struct OutboundHTLCOutput { htlc_id: u64, amount_msat: u64, @@ -227,10 +233,12 @@ struct OutboundHTLCOutput { payment_hash: PaymentHash, state: OutboundHTLCState, source: HTLCSource, + blinding_point: Option, skimmed_fee_msat: Option, } /// See AwaitingRemoteRevoke ChannelState for more info +#[cfg_attr(test, derive(Clone, Debug, PartialEq))] enum HTLCUpdateAwaitingACK { AddHTLC { // TODO: Time out if we're getting close to cltv_expiry // always outbound @@ -241,6 +249,7 @@ enum HTLCUpdateAwaitingACK { onion_routing_packet: msgs::OnionPacket, // The extra fee we're skimming off the top of this HTLC. skimmed_fee_msat: Option, + blinding_point: Option, }, ClaimHTLC { payment_preimage: PaymentPreimage, @@ -405,6 +414,33 @@ impl fmt::Display for ChannelError { } } +pub(super) struct WithChannelContext<'a, L: Deref> where L::Target: Logger { + pub logger: &'a L, + pub peer_id: Option, + pub channel_id: Option, +} + +impl<'a, L: Deref> Logger for WithChannelContext<'a, L> where L::Target: Logger { + fn log(&self, mut record: Record) { + record.peer_id = self.peer_id; + record.channel_id = self.channel_id; + self.logger.log(record) + } +} + +impl<'a, 'b, L: Deref> WithChannelContext<'a, L> +where L::Target: Logger { + pub(super) fn from(logger: &'a L, context: &'b ChannelContext) -> Self + where S::Target: SignerProvider + { + WithChannelContext { + logger, + peer_id: Some(context.counterparty_node_id), + channel_id: Some(context.channel_id), + } + } +} + macro_rules! secp_check { ($res: expr, $err: expr) => { match $res { @@ -476,7 +512,8 @@ struct CommitmentStats<'a> { htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction local_balance_msat: u64, // local balance before fees but considering dust limits remote_balance_msat: u64, // remote balance before fees but considering dust limits - preimages: Vec, // preimages for successful offered HTLCs since last commitment + outbound_htlc_preimages: Vec, // preimages for successful offered HTLCs since last commitment + inbound_htlc_preimages: Vec, // preimages for successful received HTLCs since last commitment } /// Used when calculating whether we or the remote can afford an additional HTLC. @@ -563,6 +600,8 @@ pub(crate) struct ShutdownResult { /// An unbroadcasted batch funding transaction id. The closure of this channel should be /// propagated to the remainder of the batch. pub(crate) unbroadcasted_batch_funding_txid: Option, + pub(crate) channel_id: ChannelId, + pub(crate) counterparty_node_id: PublicKey, } /// If the majority of the channels funds are to the fundee and the initiator holds only just @@ -645,7 +684,7 @@ pub(super) enum ChannelPhase where SP::Target: SignerProvider { impl<'a, SP: Deref> ChannelPhase where SP::Target: SignerProvider, - ::Signer: ChannelSigner, + ::EcdsaSigner: ChannelSigner, { pub fn context(&'a self) -> &'a ChannelContext { match self { @@ -723,7 +762,7 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { latest_monitor_update_id: u64, - holder_signer: ChannelSignerType<::Signer>, + holder_signer: ChannelSignerType, shutdown_scriptpubkey: Option, destination_script: ScriptBuf, @@ -1093,7 +1132,7 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns the holder signer for this channel. #[cfg(test)] - pub fn get_signer(&self) -> &ChannelSignerType<::Signer> { + pub fn get_signer(&self) -> &ChannelSignerType { return &self.holder_signer } @@ -1390,6 +1429,8 @@ impl ChannelContext where SP::Target: SignerProvider { } } + let mut inbound_htlc_preimages: Vec = Vec::new(); + for ref htlc in self.pending_inbound_htlcs.iter() { let (include, state_name) = match htlc.state { InboundHTLCState::RemoteAnnounced(_) => (!generated_by_local, "RemoteAnnounced"), @@ -1407,7 +1448,8 @@ impl ChannelContext where SP::Target: SignerProvider { match &htlc.state { &InboundHTLCState::LocalRemoved(ref reason) => { if generated_by_local { - if let &InboundHTLCRemovalReason::Fulfill(_) = reason { + if let &InboundHTLCRemovalReason::Fulfill(preimage) = reason { + inbound_htlc_preimages.push(preimage); value_to_self_msat_offset += htlc.amount_msat as i64; } } @@ -1417,7 +1459,8 @@ impl ChannelContext where SP::Target: SignerProvider { } } - let mut preimages: Vec = Vec::new(); + + let mut outbound_htlc_preimages: Vec = Vec::new(); for ref htlc in self.pending_outbound_htlcs.iter() { let (include, state_name) = match htlc.state { @@ -1436,7 +1479,7 @@ impl ChannelContext where SP::Target: SignerProvider { }; if let Some(preimage) = preimage_opt { - preimages.push(preimage); + outbound_htlc_preimages.push(preimage); } if include { @@ -1542,7 +1585,8 @@ impl ChannelContext where SP::Target: SignerProvider { htlcs_included, local_balance_msat: value_to_self_msat as u64, remote_balance_msat: value_to_remote_msat as u64, - preimages + inbound_htlc_preimages, + outbound_htlc_preimages, } } @@ -2128,6 +2172,8 @@ impl ChannelContext where SP::Target: SignerProvider { monitor_update, dropped_outbound_htlcs, unbroadcasted_batch_funding_txid, + channel_id: self.channel_id, + counterparty_node_id: self.counterparty_node_id, } } @@ -2138,9 +2184,12 @@ impl ChannelContext where SP::Target: SignerProvider { let signature = match &self.holder_signer { // TODO (taproot|arik): move match into calling method for Taproot ChannelSignerType::Ecdsa(ecdsa) => { - ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.secp_ctx) + ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx) .map(|(sig, _)| sig).ok()? - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() }; if self.signer_pending_funding { @@ -2173,7 +2222,7 @@ impl ChannelContext where SP::Target: SignerProvider { match &self.holder_signer { // TODO (arik): move match into calling method for Taproot ChannelSignerType::Ecdsa(ecdsa) => { - let funding_signed = ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.secp_ctx) + let funding_signed = ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx) .map(|(signature, _)| msgs::FundingSigned { channel_id: self.channel_id(), signature, @@ -2192,7 +2241,10 @@ impl ChannelContext where SP::Target: SignerProvider { // We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish. (counterparty_initial_commitment_tx, funding_signed) - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() } } } @@ -2271,7 +2323,7 @@ struct CommitmentTxInfoCached { impl Channel where SP::Target: SignerProvider, - ::Signer: WriteableEcdsaChannelSigner + ::EcdsaSigner: WriteableEcdsaChannelSigner { fn check_remote_fee( channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator, @@ -2667,7 +2719,7 @@ impl Channel where /// If this call is successful, broadcast the funding transaction (and not before!) pub fn funding_signed( &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result::Signer>, ChannelError> + ) -> Result::EcdsaSigner>, ChannelError> where L::Target: Logger { @@ -2731,14 +2783,14 @@ impl Channel where funding_redeemscript.clone(), self.context.channel_value_satoshis, obscure_factor, holder_commitment_tx, best_block, self.context.counterparty_node_id); - + let logger_with_chan_monitor = WithChannelMonitor::from(logger, &channel_monitor); channel_monitor.provide_initial_counterparty_commitment_tx( counterparty_initial_bitcoin_tx.txid, Vec::new(), self.context.cur_counterparty_commitment_transaction_number, self.context.counterparty_cur_commitment_point.unwrap(), counterparty_initial_commitment_tx.feerate_per_kw(), counterparty_initial_commitment_tx.to_broadcaster_value_sat(), - counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger); + counterparty_initial_commitment_tx.to_countersignatory_value_sat(), &&logger_with_chan_monitor); assert_eq!(self.context.channel_state & (ChannelState::MonitorUpdateInProgress as u32), 0); // We have no had any monitor(s) yet to fail update! if self.context.is_batch_funding() { @@ -3174,9 +3226,9 @@ impl Channel where let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]); log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.", - log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.serialize()), + log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id()); - if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key) { + if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) { return Err(ChannelError::Close("Invalid HTLC tx signature from peer".to_owned())); } if !separate_nondust_htlc_sources { @@ -3201,7 +3253,7 @@ impl Channel where self.context.counterparty_funding_pubkey() ); - self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.preimages) + self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages) .map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?; // Update state now that we've passed all the can-fail calls... @@ -3347,11 +3399,12 @@ impl Channel where match &htlc_update { &HTLCUpdateAwaitingACK::AddHTLC { amount_msat, cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet, - skimmed_fee_msat, .. + skimmed_fee_msat, blinding_point, .. } => { - match self.send_htlc(amount_msat, *payment_hash, cltv_expiry, source.clone(), - onion_routing_packet.clone(), false, skimmed_fee_msat, fee_estimator, logger) - { + match self.send_htlc( + amount_msat, *payment_hash, cltv_expiry, source.clone(), onion_routing_packet.clone(), + false, skimmed_fee_msat, blinding_point, fee_estimator, logger + ) { Ok(_) => update_add_count += 1, Err(e) => { match e { @@ -3483,7 +3536,10 @@ impl Channel where self.context.cur_counterparty_commitment_transaction_number + 1, &secret ).map_err(|_| ChannelError::Close("Failed to validate revocation from peer".to_owned()))?; - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() }; self.context.commitment_secrets.provide_secret(self.context.cur_counterparty_commitment_transaction_number + 1, msg.per_commitment_secret) @@ -4064,6 +4120,7 @@ impl Channel where cltv_expiry: htlc.cltv_expiry, onion_routing_packet: (**onion_packet).clone(), skimmed_fee_msat: htlc.skimmed_fee_msat, + blinding_point: htlc.blinding_point, }); } } @@ -4164,6 +4221,7 @@ impl Channel where return Err(ChannelError::Close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned())); } + let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number - 1; if msg.next_remote_commitment_number > 0 { 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) @@ -4171,7 +4229,7 @@ impl Channel where if expected_point != PublicKey::from_secret_key(&self.context.secp_ctx, &given_secret) { return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided".to_owned())); } - if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number { + if msg.next_remote_commitment_number > our_commitment_transaction { macro_rules! log_and_panic { ($err_msg: expr) => { log_error!(logger, $err_msg, &self.context.channel_id, log_pubkey!(self.context.counterparty_node_id)); @@ -4191,11 +4249,12 @@ impl Channel where // Before we change the state of the channel, we check if the peer is sending a very old // commitment transaction number, if yes we send a warning message. - let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number - 1; - if msg.next_remote_commitment_number + 1 < our_commitment_transaction { - return Err( - ChannelError::Warn(format!("Peer attempted to reestablish channel with a very old local commitment transaction: {} (received) vs {} (expected)", msg.next_remote_commitment_number, our_commitment_transaction)) - ); + if msg.next_remote_commitment_number + 1 < our_commitment_transaction { + return Err(ChannelError::Warn(format!( + "Peer attempted to reestablish channel with a very old local commitment transaction: {} (received) vs {} (expected)", + msg.next_remote_commitment_number, + our_commitment_transaction + ))); } // Go ahead and unmark PeerDisconnected as various calls we may make check for it (and all @@ -4237,11 +4296,11 @@ impl Channel where }); } - let required_revoke = if msg.next_remote_commitment_number + 1 == INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number { + let required_revoke = if msg.next_remote_commitment_number == our_commitment_transaction { // Remote isn't waiting on any RevokeAndACK from us! // Note that if we need to repeat our ChannelReady we'll do that in the next if block. None - } else if msg.next_remote_commitment_number + 1 == (INITIAL_COMMITMENT_NUMBER - 1) - self.context.cur_holder_commitment_transaction_number { + } else if msg.next_remote_commitment_number + 1 == our_commitment_transaction { if self.context.channel_state & (ChannelState::MonitorUpdateInProgress as u32) != 0 { self.context.monitor_pending_revoke_and_ack = true; None @@ -4249,7 +4308,12 @@ impl Channel where Some(self.get_last_revoke_and_ack()) } } else { - return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old local commitment transaction".to_owned())); + debug_assert!(false, "All values should have been handled in the four cases above"); + return Err(ChannelError::Close(format!( + "Peer attempted to reestablish channel expecting a future local commitment transaction: {} (received) vs {} (expected)", + msg.next_remote_commitment_number, + our_commitment_transaction + ))); }; // We increment cur_counterparty_commitment_transaction_number only upon receipt of @@ -4307,8 +4371,18 @@ impl Channel where order: self.context.resend_order.clone(), }) } + } else if msg.next_local_commitment_number < next_counterparty_commitment_number { + Err(ChannelError::Close(format!( + "Peer attempted to reestablish channel with a very old remote commitment transaction: {} (received) vs {} (expected)", + msg.next_local_commitment_number, + next_counterparty_commitment_number, + ))) } else { - Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction".to_owned())) + Err(ChannelError::Close(format!( + "Peer attempted to reestablish channel with a future remote commitment transaction: {} (received) vs {} (expected)", + msg.next_local_commitment_number, + next_counterparty_commitment_number, + ))) } } @@ -4436,7 +4510,10 @@ impl Channel where max_fee_satoshis: our_max_fee, }), }), None, None)) - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() } } @@ -4640,6 +4717,8 @@ impl Channel where monitor_update: None, dropped_outbound_htlcs: Vec::new(), unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(), + channel_id: self.context.channel_id, + counterparty_node_id: self.context.counterparty_node_id, }; let tx = self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig); self.context.channel_state = ChannelState::ShutdownComplete as u32; @@ -4668,6 +4747,8 @@ impl Channel where monitor_update: None, dropped_outbound_htlcs: Vec::new(), unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(), + channel_id: self.context.channel_id, + counterparty_node_id: self.context.counterparty_node_id, }; self.context.channel_state = ChannelState::ShutdownComplete as u32; self.context.update_time_counter += 1; @@ -4687,7 +4768,10 @@ impl Channel where max_fee_satoshis: our_max_fee, }), }), signed_tx, shutdown_result)) - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() } } } @@ -4799,7 +4883,7 @@ impl Channel where } #[cfg(test)] - pub fn get_signer(&self) -> &ChannelSignerType<::Signer> { + pub fn get_signer(&self) -> &ChannelSignerType { &self.context.holder_signer } @@ -5318,7 +5402,10 @@ impl Channel where node_signature: our_node_sig, bitcoin_signature: our_bitcoin_sig, }) - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() } } @@ -5345,7 +5432,10 @@ impl Channel where bitcoin_signature_2: if were_node_one { their_bitcoin_sig } else { our_bitcoin_sig }, contents: announcement, }) - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() } } else { Err(ChannelError::Ignore("Attempted to sign channel announcement before we'd received announcement_signatures".to_string())) @@ -5463,13 +5553,13 @@ impl Channel where pub fn queue_add_htlc( &mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option, - fee_estimator: &LowerBoundedFeeEstimator, logger: &L + blinding_point: Option, fee_estimator: &LowerBoundedFeeEstimator, logger: &L ) -> Result<(), ChannelError> where F::Target: FeeEstimator, L::Target: Logger { self .send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, true, - skimmed_fee_msat, fee_estimator, logger) + skimmed_fee_msat, blinding_point, fee_estimator, logger) .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?")) .map_err(|err| { if let ChannelError::Ignore(_) = err { /* fine */ } @@ -5497,7 +5587,8 @@ impl Channel where fn send_htlc( &mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, mut force_holding_cell: bool, - skimmed_fee_msat: Option, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + skimmed_fee_msat: Option, blinding_point: Option, + fee_estimator: &LowerBoundedFeeEstimator, logger: &L ) -> Result, ChannelError> where F::Target: FeeEstimator, L::Target: Logger { @@ -5554,6 +5645,7 @@ impl Channel where source, onion_routing_packet, skimmed_fee_msat, + blinding_point, }); return Ok(None); } @@ -5565,6 +5657,7 @@ impl Channel where cltv_expiry, state: OutboundHTLCState::LocalAnnounced(Box::new(onion_routing_packet.clone())), source, + blinding_point, skimmed_fee_msat, }); @@ -5576,6 +5669,7 @@ impl Channel where cltv_expiry, onion_routing_packet, skimmed_fee_msat, + blinding_point, }; self.context.next_holder_htlc_id += 1; @@ -5692,8 +5786,12 @@ impl Channel where htlcs.push(htlc); } - let res = ecdsa.sign_counterparty_commitment(&commitment_stats.tx, commitment_stats.preimages, &self.context.secp_ctx) - .map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?; + let res = ecdsa.sign_counterparty_commitment( + &commitment_stats.tx, + commitment_stats.inbound_htlc_preimages, + commitment_stats.outbound_htlc_preimages, + &self.context.secp_ctx, + ).map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?; signature = res.0; htlc_signatures = res.1; @@ -5706,7 +5804,7 @@ impl Channel where 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!(counterparty_keys.broadcaster_htlc_key.to_public_key().serialize()), log_bytes!(htlc_sig.serialize_compact()[..]), &self.context.channel_id()); } } @@ -5718,7 +5816,10 @@ impl Channel where #[cfg(taproot)] partial_signature_with_nonce: None, }, (counterparty_commitment_txid, commitment_stats.htlcs_included))) - } + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() } } @@ -5735,7 +5836,7 @@ impl Channel where where F::Target: FeeEstimator, L::Target: Logger { let send_res = self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, - onion_routing_packet, false, skimmed_fee_msat, fee_estimator, logger); + onion_routing_packet, false, skimmed_fee_msat, None, fee_estimator, logger); if let Err(e) = &send_res { if let ChannelError::Ignore(_) = e {} else { debug_assert!(false, "Sending cannot trigger channel failure"); } } match send_res? { Some(_) => { @@ -5830,6 +5931,8 @@ impl Channel where monitor_update: None, dropped_outbound_htlcs: Vec::new(), unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(), + channel_id: self.context.channel_id, + counterparty_node_id: self.context.counterparty_node_id, }; self.context.channel_state = ChannelState::ShutdownComplete as u32; Some(shutdown_result) @@ -5960,7 +6063,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { } } - let destination_script = match signer_provider.get_destination_script() { + let destination_script = match signer_provider.get_destination_script(channel_keys_id) { Ok(script) => script, Err(_) => return Err(APIError::ChannelUnavailable { err: "Failed to get destination script".to_owned()}), }; @@ -6242,10 +6345,10 @@ impl OutboundV1Channel where SP::Target: SignerProvider { to_self_delay: self.context.get_holder_selected_contest_delay(), max_accepted_htlcs: self.context.holder_max_accepted_htlcs, funding_pubkey: keys.funding_pubkey, - revocation_basepoint: keys.revocation_basepoint, + revocation_basepoint: keys.revocation_basepoint.to_public_key(), payment_point: keys.payment_point, - delayed_payment_basepoint: keys.delayed_payment_basepoint, - htlc_basepoint: keys.htlc_basepoint, + delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(), + htlc_basepoint: keys.htlc_basepoint.to_public_key(), first_per_commitment_point, channel_flags: if self.context.config.announced_channel {1} else {0}, shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey { @@ -6367,10 +6470,10 @@ impl OutboundV1Channel where SP::Target: SignerProvider { let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: msg.funding_pubkey, - revocation_basepoint: msg.revocation_basepoint, + revocation_basepoint: RevocationBasepoint::from(msg.revocation_basepoint), payment_point: msg.payment_point, - delayed_payment_basepoint: msg.delayed_payment_basepoint, - htlc_basepoint: msg.htlc_basepoint + delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.delayed_payment_basepoint), + htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint) }; self.context.channel_transaction_parameters.counterparty_parameters = Some(CounterpartyChannelTransactionParameters { @@ -6407,6 +6510,7 @@ impl InboundV1Channel where SP::Target: SignerProvider { F::Target: FeeEstimator, L::Target: Logger, { + let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.temporary_channel_id)); let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false }; // First check the channel type is known, failing before we do anything else if we don't @@ -6443,10 +6547,10 @@ impl InboundV1Channel where SP::Target: SignerProvider { let pubkeys = holder_signer.pubkeys().clone(); let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: msg.funding_pubkey, - revocation_basepoint: msg.revocation_basepoint, + revocation_basepoint: RevocationBasepoint::from(msg.revocation_basepoint), payment_point: msg.payment_point, - delayed_payment_basepoint: msg.delayed_payment_basepoint, - htlc_basepoint: msg.htlc_basepoint + delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.delayed_payment_basepoint), + htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint) }; if config.channel_handshake_config.our_to_self_delay < BREAKDOWN_TIMEOUT { @@ -6473,7 +6577,7 @@ impl InboundV1Channel where SP::Target: SignerProvider { 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 { @@ -6587,7 +6691,7 @@ impl InboundV1Channel where SP::Target: SignerProvider { } } - let destination_script = match signer_provider.get_destination_script() { + let destination_script = match signer_provider.get_destination_script(channel_keys_id) { Ok(script) => script, Err(_) => return Err(ChannelError::Close("Failed to get destination script".to_owned())), }; @@ -6776,10 +6880,10 @@ impl InboundV1Channel where SP::Target: SignerProvider { to_self_delay: self.context.get_holder_selected_contest_delay(), max_accepted_htlcs: self.context.holder_max_accepted_htlcs, funding_pubkey: keys.funding_pubkey, - revocation_basepoint: keys.revocation_basepoint, + revocation_basepoint: keys.revocation_basepoint.to_public_key(), payment_point: keys.payment_point, - delayed_payment_basepoint: keys.delayed_payment_basepoint, - htlc_basepoint: keys.htlc_basepoint, + delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(), + htlc_basepoint: keys.htlc_basepoint.to_public_key(), first_per_commitment_point, shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey { Some(script) => script.clone().into_inner(), @@ -6820,7 +6924,7 @@ impl InboundV1Channel where SP::Target: SignerProvider { pub fn funding_created( mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result<(Channel, Option, ChannelMonitor<::Signer>), (Self, ChannelError)> + ) -> Result<(Channel, Option, ChannelMonitor<::EcdsaSigner>), (Self, ChannelError)> where L::Target: Logger { @@ -6892,13 +6996,13 @@ impl InboundV1Channel where SP::Target: SignerProvider { funding_redeemscript.clone(), self.context.channel_value_satoshis, obscure_factor, holder_commitment_tx, best_block, self.context.counterparty_node_id); - + let logger_with_chan_monitor = WithChannelMonitor::from(logger, &channel_monitor); channel_monitor.provide_initial_counterparty_commitment_tx( counterparty_initial_commitment_tx.trust().txid(), Vec::new(), self.context.cur_counterparty_commitment_transaction_number + 1, self.context.counterparty_cur_commitment_point.unwrap(), self.context.feerate_per_kw, counterparty_initial_commitment_tx.to_broadcaster_value_sat(), - counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger); + counterparty_initial_commitment_tx.to_countersignatory_value_sat(), &&logger_with_chan_monitor); log_info!(logger, "{} funding_signed for peer for channel {}", if funding_signed.is_some() { "Generated" } else { "Waiting for signature on" }, &self.context.channel_id()); @@ -7045,6 +7149,7 @@ impl Writeable for Channel where SP::Target: SignerProvider { let mut preimages: Vec<&Option> = vec![]; let mut pending_outbound_skimmed_fees: Vec> = Vec::new(); + let mut pending_outbound_blinding_points: Vec> = Vec::new(); (self.context.pending_outbound_htlcs.len() as u64).write(writer)?; for (idx, htlc) in self.context.pending_outbound_htlcs.iter().enumerate() { @@ -7091,15 +7196,17 @@ impl Writeable for Channel where SP::Target: SignerProvider { } else if !pending_outbound_skimmed_fees.is_empty() { pending_outbound_skimmed_fees.push(None); } + pending_outbound_blinding_points.push(htlc.blinding_point); } let mut holding_cell_skimmed_fees: Vec> = Vec::new(); + let mut holding_cell_blinding_points: Vec> = Vec::new(); (self.context.holding_cell_htlc_updates.len() as u64).write(writer)?; for (idx, update) in self.context.holding_cell_htlc_updates.iter().enumerate() { match update { &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, ref cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet, - skimmed_fee_msat, + blinding_point, skimmed_fee_msat, } => { 0u8.write(writer)?; amount_msat.write(writer)?; @@ -7114,6 +7221,8 @@ impl Writeable for Channel where SP::Target: SignerProvider { } holding_cell_skimmed_fees.push(Some(skimmed_fee)); } else if !holding_cell_skimmed_fees.is_empty() { holding_cell_skimmed_fees.push(None); } + + holding_cell_blinding_points.push(blinding_point); }, &HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, ref htlc_id } => { 1u8.write(writer)?; @@ -7283,6 +7392,8 @@ impl Writeable for Channel where SP::Target: SignerProvider { (35, pending_outbound_skimmed_fees, optional_vec), (37, holding_cell_skimmed_fees, optional_vec), (38, self.context.is_batch_funding, option), + (39, pending_outbound_blinding_points, optional_vec), + (41, holding_cell_blinding_points, optional_vec), }); Ok(()) @@ -7394,6 +7505,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch _ => return Err(DecodeError::InvalidValue), }, skimmed_fee_msat: None, + blinding_point: None, }); } @@ -7408,6 +7520,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch source: Readable::read(reader)?, onion_routing_packet: Readable::read(reader)?, skimmed_fee_msat: None, + blinding_point: None, }, 1 => HTLCUpdateAwaitingACK::ClaimHTLC { payment_preimage: Readable::read(reader)?, @@ -7568,6 +7681,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch let mut is_batch_funding: Option<()> = None; + let mut pending_outbound_blinding_points_opt: Option>> = None; + let mut holding_cell_blinding_points_opt: Option>> = None; + read_tlv_fields!(reader, { (0, announcement_sigs, option), (1, minimum_depth, option), @@ -7594,6 +7710,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch (35, pending_outbound_skimmed_fees_opt, optional_vec), (37, holding_cell_skimmed_fees_opt, optional_vec), (38, is_batch_funding, option), + (39, pending_outbound_blinding_points_opt, optional_vec), + (41, holding_cell_blinding_points_opt, optional_vec), }); let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id { @@ -7670,6 +7788,24 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch // We expect all skimmed fees to be consumed above if iter.next().is_some() { return Err(DecodeError::InvalidValue) } } + if let Some(blinding_pts) = pending_outbound_blinding_points_opt { + let mut iter = blinding_pts.into_iter(); + for htlc in pending_outbound_htlcs.iter_mut() { + htlc.blinding_point = iter.next().ok_or(DecodeError::InvalidValue)?; + } + // We expect all blinding points to be consumed above + if iter.next().is_some() { return Err(DecodeError::InvalidValue) } + } + if let Some(blinding_pts) = holding_cell_blinding_points_opt { + let mut iter = blinding_pts.into_iter(); + for htlc in holding_cell_htlc_updates.iter_mut() { + if let HTLCUpdateAwaitingACK::AddHTLC { ref mut blinding_point, .. } = htlc { + *blinding_point = iter.next().ok_or(DecodeError::InvalidValue)?; + } + } + // We expect all blinding points to be consumed above + if iter.next().is_some() { return Err(DecodeError::InvalidValue) } + } Ok(Channel { context: ChannelContext { @@ -7805,23 +7941,25 @@ mod tests { use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::blockdata::opcodes; use bitcoin::network::constants::Network; - use crate::ln::PaymentHash; + use crate::ln::{PaymentHash, PaymentPreimage}; + use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint}; use crate::ln::channelmanager::{self, HTLCSource, PaymentId}; use crate::ln::channel::InitFeatures; - use crate::ln::channel::{ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat}; + use crate::ln::channel::{Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_msat}; use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS}; - use crate::ln::features::ChannelTypeFeatures; + use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; + use crate::ln::msgs; use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT}; use crate::ln::script::ShutdownScript; - use crate::ln::chan_utils; - use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight}; + use crate::ln::chan_utils::{self, htlc_success_tx_weight, htlc_timeout_tx_weight}; use crate::chain::BestBlock; use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget}; use crate::sign::{ChannelSigner, InMemorySigner, EntropySource, SignerProvider}; use crate::chain::transaction::OutPoint; - use crate::routing::router::Path; + use crate::routing::router::{Path, RouteHop}; use crate::util::config::UserConfig; use crate::util::errors::APIError; + use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_utils; use crate::util::test_utils::{OnGetShutdownScriptpubkey, TestKeysInterface}; use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; @@ -7860,19 +7998,21 @@ mod tests { } impl SignerProvider for Keys { - type Signer = InMemorySigner; + type EcdsaSigner = InMemorySigner; + #[cfg(taproot)] + type TaprootSigner = InMemorySigner; fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { self.signer.channel_keys_id() } - fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer { + fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::EcdsaSigner { self.signer.clone() } - fn read_chan_signer(&self, _data: &[u8]) -> Result { panic!(); } + fn read_chan_signer(&self, _data: &[u8]) -> Result { panic!(); } - fn get_destination_script(&self) -> Result { + fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result { let secp_ctx = Secp256k1::signing_only(); let channel_monitor_claim_key = SecretKey::from_slice(&>::from_hex("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); let channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); @@ -8007,6 +8147,7 @@ mod tests { payment_id: PaymentId([42; 32]), }, skimmed_fee_msat: None, + blinding_point: None, }); // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass @@ -8332,6 +8473,96 @@ mod tests { assert!(!node_a_chan.channel_update(&update).unwrap()); } + #[test] + fn blinding_point_ser() { + // Ensure that channel blinding points are (de)serialized properly. + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let secp_ctx = Secp256k1::new(); + let seed = [42; 32]; + let network = Network::Testnet; + let keys_provider = test_utils::TestKeysInterface::new(&seed, network); + + let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let config = UserConfig::default(); + let features = channelmanager::provided_init_features(&config); + let outbound_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &features, 10000000, 100000, 42, &config, 0, 42, None).unwrap(); + let mut chan = Channel { context: outbound_chan.context }; + + let dummy_htlc_source = HTLCSource::OutboundRoute { + path: Path { + hops: vec![RouteHop { + pubkey: test_utils::pubkey(2), channel_features: ChannelFeatures::empty(), + node_features: NodeFeatures::empty(), short_channel_id: 0, fee_msat: 0, + cltv_expiry_delta: 0, maybe_announced_channel: false, + }], + blinded_tail: None + }, + session_priv: test_utils::privkey(42), + first_hop_htlc_msat: 0, + payment_id: PaymentId([42; 32]), + }; + let dummy_outbound_output = OutboundHTLCOutput { + htlc_id: 0, + amount_msat: 0, + payment_hash: PaymentHash([43; 32]), + cltv_expiry: 0, + state: OutboundHTLCState::Committed, + source: dummy_htlc_source.clone(), + skimmed_fee_msat: None, + blinding_point: None, + }; + let mut pending_outbound_htlcs = vec![dummy_outbound_output.clone(); 10]; + for (idx, htlc) in pending_outbound_htlcs.iter_mut().enumerate() { + if idx % 2 == 0 { + htlc.blinding_point = Some(test_utils::pubkey(42 + idx as u8)); + } + } + chan.context.pending_outbound_htlcs = pending_outbound_htlcs.clone(); + + let dummy_holding_cell_add_htlc = HTLCUpdateAwaitingACK::AddHTLC { + amount_msat: 0, + cltv_expiry: 0, + payment_hash: PaymentHash([43; 32]), + source: dummy_htlc_source.clone(), + onion_routing_packet: msgs::OnionPacket { + version: 0, + public_key: Ok(test_utils::pubkey(1)), + hop_data: [0; 20*65], + hmac: [0; 32] + }, + skimmed_fee_msat: None, + blinding_point: None, + }; + let dummy_holding_cell_claim_htlc = HTLCUpdateAwaitingACK::ClaimHTLC { + payment_preimage: PaymentPreimage([42; 32]), + htlc_id: 0, + }; + let mut holding_cell_htlc_updates = Vec::with_capacity(10); + for i in 0..10 { + if i % 3 == 0 { + holding_cell_htlc_updates.push(dummy_holding_cell_add_htlc.clone()); + } else if i % 3 == 1 { + holding_cell_htlc_updates.push(dummy_holding_cell_claim_htlc.clone()); + } else { + let mut dummy_add = dummy_holding_cell_add_htlc.clone(); + if let HTLCUpdateAwaitingACK::AddHTLC { ref mut blinding_point, .. } = &mut dummy_add { + *blinding_point = Some(test_utils::pubkey(42 + i)); + } else { panic!() } + holding_cell_htlc_updates.push(dummy_add); + } + } + chan.context.holding_cell_htlc_updates = holding_cell_htlc_updates.clone(); + + // Encode and decode the channel and ensure that the HTLCs within are the same. + let encoded_chan = chan.encode(); + let mut s = crate::io::Cursor::new(&encoded_chan); + let mut reader = crate::util::ser::FixedLengthReader::new(&mut s, encoded_chan.len() as u64); + let features = channelmanager::provided_channel_type_features(&config); + let decoded_chan = Channel::read(&mut reader, (&&keys_provider, &&keys_provider, 0, &features)).unwrap(); + assert_eq!(decoded_chan.context.pending_outbound_htlcs, pending_outbound_htlcs); + assert_eq!(decoded_chan.context.holding_cell_htlc_updates, holding_cell_htlc_updates); + } + #[cfg(feature = "_test_vectors")] #[test] fn outbound_commitment_test() { @@ -8341,9 +8572,10 @@ mod tests { use bitcoin::hashes::hex::FromHex; use bitcoin::hash_types::Txid; use bitcoin::secp256k1::Message; - use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, EcdsaChannelSigner}; + use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ecdsa::EcdsaChannelSigner}; use crate::ln::PaymentPreimage; use crate::ln::channel::{HTLCOutputInCommitment ,TxCreationKeys}; + use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint}; use crate::ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; use crate::util::logger::Logger; use crate::sync::Arc; @@ -8385,10 +8617,10 @@ mod tests { let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"), - revocation_basepoint: PublicKey::from_slice(&>::from_hex("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap(), + revocation_basepoint: RevocationBasepoint::from(PublicKey::from_slice(&>::from_hex("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap()), payment_point: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444"), - delayed_payment_basepoint: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"), - htlc_basepoint: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444") + delayed_payment_basepoint: DelayedPaymentBasepoint::from(public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13")), + htlc_basepoint: HtlcBasepoint::from(public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444")) }; chan.context.channel_transaction_parameters.counterparty_parameters = Some( CounterpartyChannelTransactionParameters { @@ -8404,7 +8636,7 @@ mod tests { assert_eq!(counterparty_pubkeys.funding_pubkey.serialize()[..], >::from_hex("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]); - assert_eq!(counterparty_pubkeys.htlc_basepoint.serialize()[..], + assert_eq!(counterparty_pubkeys.htlc_basepoint.to_public_key().serialize()[..], >::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]); // We can't just use build_holder_transaction_keys here as the per_commitment_secret is not @@ -8489,7 +8721,7 @@ mod tests { let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, $opt_anchors, &keys); let htlc_sighashtype = if $opt_anchors.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; let htlc_sighash = Message::from_slice(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]).unwrap(); - assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key).is_ok(), "verify counterparty htlc sig"); + assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key.to_public_key()).is_ok(), "verify counterparty htlc sig"); let mut preimage: Option = None; if !htlc.offered { @@ -8580,6 +8812,7 @@ mod tests { state: OutboundHTLCState::Committed, source: HTLCSource::dummy(), skimmed_fee_msat: None, + blinding_point: None, }; out.payment_hash.0 = Sha256::hash(&>::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap()).to_byte_array(); out @@ -8593,6 +8826,7 @@ mod tests { state: OutboundHTLCState::Committed, source: HTLCSource::dummy(), skimmed_fee_msat: None, + blinding_point: None, }; out.payment_hash.0 = Sha256::hash(&>::from_hex("0303030303030303030303030303030303030303030303030303030303030303").unwrap()).to_byte_array(); out @@ -9004,6 +9238,7 @@ mod tests { state: OutboundHTLCState::Committed, source: HTLCSource::dummy(), skimmed_fee_msat: None, + blinding_point: None, }; out.payment_hash.0 = Sha256::hash(&>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array(); out @@ -9017,6 +9252,7 @@ mod tests { state: OutboundHTLCState::Committed, source: HTLCSource::dummy(), skimmed_fee_msat: None, + blinding_point: None, }; out.payment_hash.0 = Sha256::hash(&>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array(); out @@ -9098,13 +9334,10 @@ mod tests { let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); assert_eq!(per_commitment_point.serialize()[..], >::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]); - assert_eq!(chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..], - >::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]); - assert_eq!(chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &base_secret), SecretKey::from_slice(&>::from_hex("cbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f").unwrap()[..]).unwrap()); - assert_eq!(chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..], + assert_eq!(RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(base_point), &per_commitment_point).to_public_key().serialize()[..], >::from_hex("02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0").unwrap()[..]); assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret),