diff --git a/lightning-dns-resolver/src/lib.rs b/lightning-dns-resolver/src/lib.rs index fc591c8c153..3d8e1b3cd9b 100644 --- a/lightning-dns-resolver/src/lib.rs +++ b/lightning-dns-resolver/src/lib.rs @@ -239,8 +239,7 @@ mod test { context, &keys, secp_ctx, - ) - .unwrap()]) + )]) } } impl Deref for DirectlyConnectedRouter { @@ -349,8 +348,7 @@ mod test { query_context, &*payer_keys, &secp_ctx, - ) - .unwrap(); + ); payer.pending_messages.lock().unwrap().push(( DNSResolverMessage::DNSSECQuery(msg), MessageSendInstructions::WithSpecifiedReplyPath { diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index 8105bb206ee..7d721cd1fdc 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -57,23 +57,19 @@ impl BlindedMessagePath { pub fn one_hop( recipient_node_id: PublicKey, local_node_receive_key: ReceiveAuthKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1, - ) -> Result + ) -> Self where ES::Target: EntropySource, { Self::new(&[], recipient_node_id, local_node_receive_key, context, entropy_source, secp_ctx) } - /// Create a path for an onion message, to be forwarded along `node_pks`. The last node - /// pubkey in `node_pks` will be the destination node. - /// - /// Errors if no hops are provided or if `node_pk`(s) are invalid. - // TODO: make all payloads the same size with padding + add dummy hops + /// Create a path for an onion message, to be forwarded along `node_pks`. pub fn new( intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey, local_node_receive_key: ReceiveAuthKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1, - ) -> Result + ) -> Self where ES::Target: EntropySource, { @@ -96,7 +92,7 @@ impl BlindedMessagePath { intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey, dummy_hop_count: usize, local_node_receive_key: ReceiveAuthKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1, - ) -> Result + ) -> Self where ES::Target: EntropySource, { @@ -107,7 +103,7 @@ impl BlindedMessagePath { let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); - Ok(Self(BlindedPath { + Self(BlindedPath { introduction_node, blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), blinded_hops: blinded_hops( @@ -118,9 +114,8 @@ impl BlindedMessagePath { context, &blinding_secret, local_node_receive_key, - ) - .map_err(|_| ())?, - })) + ), + }) } /// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed @@ -669,7 +664,7 @@ pub(super) fn blinded_hops( secp_ctx: &Secp256k1, intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey, dummy_hop_count: usize, context: MessageContext, session_priv: &SecretKey, local_node_receive_key: ReceiveAuthKey, -) -> Result, secp256k1::Error> { +) -> Vec { let dummy_count = cmp::min(dummy_hop_count, MAX_DUMMY_HOPS_COUNT); let pks = intermediate_nodes .iter() diff --git a/lightning/src/blinded_path/payment.rs b/lightning/src/blinded_path/payment.rs index 96913ef3c62..4ae10f75961 100644 --- a/lightning/src/blinded_path/payment.rs +++ b/lightning/src/blinded_path/payment.rs @@ -116,7 +116,6 @@ impl BlindedPaymentPath { /// Create a blinded path for a payment, to be forwarded along `intermediate_nodes`. /// /// Errors if: - /// * a provided node id is invalid /// * [`BlindedPayInfo`] calculation results in an integer overflow /// * any unknown features are required in the provided [`ForwardTlvs`] // TODO: make all payloads the same size with padding + add dummy hops @@ -151,8 +150,7 @@ impl BlindedPaymentPath { payee_node_id, payee_tlvs, &blinding_secret, - ) - .map_err(|_| ())?, + ), }, payinfo: blinded_payinfo, }) @@ -663,7 +661,7 @@ pub(crate) const PAYMENT_PADDING_ROUND_OFF: usize = 30; pub(super) fn blinded_hops( secp_ctx: &Secp256k1, intermediate_nodes: &[PaymentForwardNode], payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs, session_priv: &SecretKey, -) -> Result, secp256k1::Error> { +) -> Vec { let pks = intermediate_nodes .iter() .map(|node| (node.node_id, None)) diff --git a/lightning/src/blinded_path/utils.rs b/lightning/src/blinded_path/utils.rs index 3956fd9bcdf..5fc359a47d9 100644 --- a/lightning/src/blinded_path/utils.rs +++ b/lightning/src/blinded_path/utils.rs @@ -51,10 +51,8 @@ macro_rules! build_keys_helper { hmac.input(encrypted_data_ss.as_ref()); Hmac::from_engine(hmac).to_byte_array() }; - pk.mul_tweak( - $secp_ctx, - &Scalar::from_be_bytes(hop_pk_blinding_factor).unwrap(), - )? + pk.mul_tweak($secp_ctx, &Scalar::from_be_bytes(hop_pk_blinding_factor).unwrap()) + .expect("RNG is busted") }; let onion_packet_ss = SharedSecret::new(&blinded_hop_pk, &onion_packet_pubkey_priv); @@ -84,9 +82,9 @@ macro_rules! build_keys_helper { Sha256::from_engine(sha).to_byte_array() }; - msg_blinding_point_priv = msg_blinding_point_priv.mul_tweak( - &Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap(), - )?; + msg_blinding_point_priv = msg_blinding_point_priv + .mul_tweak(&Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap()) + .expect("RNG is busted"); msg_blinding_point = PublicKey::from_secret_key($secp_ctx, &msg_blinding_point_priv); @@ -96,9 +94,9 @@ macro_rules! build_keys_helper { sha.input(onion_packet_ss.as_ref()); Sha256::from_engine(sha).to_byte_array() }; - onion_packet_pubkey_priv = onion_packet_pubkey_priv.mul_tweak( - &Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap(), - )?; + onion_packet_pubkey_priv = onion_packet_pubkey_priv + .mul_tweak(&Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap()) + .expect("RNG is busted"); onion_packet_pubkey = PublicKey::from_secret_key($secp_ctx, &onion_packet_pubkey_priv); }; @@ -109,8 +107,7 @@ macro_rules! build_keys_helper { pub(crate) fn construct_keys_for_onion_message<'a, T, I, F>( secp_ctx: &Secp256k1, unblinded_path: I, destination: Destination, session_priv: &SecretKey, mut callback: F, -) -> Result<(), secp256k1::Error> -where +) where T: secp256k1::Signing + secp256k1::Verification, I: Iterator, F: FnMut(SharedSecret, PublicKey, [u8; 32], Option, Option>), @@ -134,13 +131,11 @@ where } }, } - Ok(()) } fn construct_keys_for_blinded_path<'a, T, I, F, H>( secp_ctx: &Secp256k1, unblinded_path: I, session_priv: &SecretKey, mut callback: F, -) -> Result<(), secp256k1::Error> -where +) where T: secp256k1::Signing + secp256k1::Verification, H: Borrow, I: Iterator, @@ -151,7 +146,6 @@ where for pk in unblinded_path { build_keys_in_loop!(pk, false, None); } - Ok(()) } struct PublicKeyWithTlvs { @@ -168,7 +162,7 @@ impl Borrow for PublicKeyWithTlvs { pub(crate) fn construct_blinded_hops<'a, T, I, W>( secp_ctx: &Secp256k1, unblinded_path: I, session_priv: &SecretKey, -) -> Result, secp256k1::Error> +) -> Vec where T: secp256k1::Signing + secp256k1::Verification, I: Iterator), W)>, @@ -194,8 +188,8 @@ where ), }); }, - )?; - Ok(blinded_hops) + ); + blinded_hops } /// Encrypt TLV payload to be used as a [`crate::blinded_path::BlindedHop::encrypted_payload`]. diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index 8db793054dc..a8e7af23984 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -1552,7 +1552,7 @@ fn route_blinding_spec_test_vector() { ]; let mut dave_eve_blinded_hops = blinded_path::utils::construct_blinded_hops( &secp_ctx, path.into_iter(), &dave_eve_session_priv, - ).unwrap(); + ); // Concatenate an additional Bob -> Carol blinded path to the Eve -> Dave blinded path. let bob_carol_session_priv = secret_from_hex("0202020202020202020202020202020202020202020202020202020202020202"); @@ -1563,7 +1563,7 @@ fn route_blinding_spec_test_vector() { ]; let bob_carol_blinded_hops = blinded_path::utils::construct_blinded_hops( &secp_ctx, path.into_iter(), &bob_carol_session_priv, - ).unwrap(); + ); let mut blinded_hops = bob_carol_blinded_hops; blinded_hops.append(&mut dave_eve_blinded_hops); @@ -2030,7 +2030,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) { let path = [((carol_node_id, None), WithoutLength(&carol_unblinded_tlvs))]; blinded_path::utils::construct_blinded_hops( &secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv, - ).unwrap() + ) } else { let payee_tlvs = blinded_path::payment::TrampolineForwardTlvs { next_trampoline: alice_node_id, @@ -2051,7 +2051,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) { let path = [((carol_node_id, None), WithoutLength(&carol_unblinded_tlvs))]; blinded_path::utils::construct_blinded_hops( &secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv, - ).unwrap() + ) }; let route = Route { @@ -2255,7 +2255,7 @@ fn test_trampoline_unblinded_receive() { let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv); let carol_blinded_hops = blinded_path::utils::construct_blinded_hops( &secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv, - ).unwrap(); + ); let route = Route { paths: vec![Path { diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 3d25934d18d..587ee9408b6 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -8958,12 +8958,19 @@ where } } - #[rustfmt::skip] - fn get_last_revoke_and_ack(&mut self, logger: &L) -> Option where L::Target: Logger { - debug_assert!(self.holder_commitment_point.next_transaction_number() <= INITIAL_COMMITMENT_NUMBER - 2); - self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger); - let per_commitment_secret = self.context.holder_signer.as_ref() - .release_commitment_secret(self.holder_commitment_point.next_transaction_number() + 2).ok(); + fn get_last_revoke_and_ack(&mut self, logger: &L) -> Option + where + L::Target: Logger, + { + debug_assert!( + self.holder_commitment_point.next_transaction_number() <= INITIAL_COMMITMENT_NUMBER - 2 + ); + let signer = &self.context.holder_signer; + self.holder_commitment_point.try_resolve_pending(signer, &self.context.secp_ctx, logger); + let per_commitment_secret = signer + .as_ref() + .release_commitment_secret(self.holder_commitment_point.next_transaction_number() + 2) + .ok(); if let Some(per_commitment_secret) = per_commitment_secret { if self.holder_commitment_point.can_advance() { self.context.signer_pending_revoke_and_ack = false; @@ -8973,7 +8980,7 @@ where next_per_commitment_point: self.holder_commitment_point.next_point(), #[cfg(taproot)] next_local_nonce: None, - }) + }); } } if !self.holder_commitment_point.can_advance() { diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index cfef0540a97..19852395a62 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -449,6 +449,27 @@ pub(super) struct PendingAddHTLCInfo { prev_user_channel_id: u128, } +impl PendingAddHTLCInfo { + fn htlc_previous_hop_data(&self) -> HTLCPreviousHopData { + let phantom_shared_secret = match self.forward_info.routing { + PendingHTLCRouting::Receive { phantom_shared_secret, .. } => phantom_shared_secret, + _ => None, + }; + HTLCPreviousHopData { + short_channel_id: self.prev_short_channel_id, + user_channel_id: Some(self.prev_user_channel_id), + outpoint: self.prev_funding_outpoint, + channel_id: self.prev_channel_id, + counterparty_node_id: Some(self.prev_counterparty_node_id), + htlc_id: self.prev_htlc_id, + incoming_packet_shared_secret: self.forward_info.incoming_shared_secret, + phantom_shared_secret, + blinded_failure: self.forward_info.routing.blinded_failure(), + cltv_expiry: self.forward_info.routing.incoming_cltv_expiry(), + } + } +} + #[cfg_attr(test, derive(Clone, Debug, PartialEq))] pub(super) enum HTLCForwardInfo { AddHTLC(PendingAddHTLCInfo), @@ -6294,20 +6315,8 @@ where err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) })?; - if let PendingHTLCRouting::Forward { short_channel_id, incoming_cltv_expiry, .. } = payment.forward_info.routing { - let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: payment.prev_short_channel_id, - user_channel_id: Some(payment.prev_user_channel_id), - outpoint: payment.prev_funding_outpoint, - channel_id: payment.prev_channel_id, - counterparty_node_id: Some(payment.prev_counterparty_node_id), - htlc_id: payment.prev_htlc_id, - incoming_packet_shared_secret: payment.forward_info.incoming_shared_secret, - phantom_shared_secret: None, - blinded_failure: payment.forward_info.routing.blinded_failure(), - cltv_expiry: incoming_cltv_expiry, - }); - + if let PendingHTLCRouting::Forward { short_channel_id, .. } = payment.forward_info.routing { + let htlc_source = HTLCSource::PreviousHopData(payment.htlc_previous_hop_data()); let reason = HTLCFailReason::from_failure_code(LocalHTLCFailureReason::UnknownNextPeer); let destination = HTLCHandlingFailureType::InvalidForward { requested_forward_scid: short_channel_id }; self.fail_htlc_backwards_internal(&htlc_source, &payment.forward_info.payment_hash, &reason, destination); @@ -6629,24 +6638,24 @@ where ) { for forward_info in forward_infos { match forward_info { - HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, - prev_htlc_id, - prev_channel_id, - prev_funding_outpoint, - prev_user_channel_id, - prev_counterparty_node_id, - forward_info: - PendingHTLCInfo { - routing, - incoming_shared_secret, - payment_hash, - outgoing_amt_msat, - outgoing_cltv_value, - .. - }, - }) => { - let cltv_expiry = routing.incoming_cltv_expiry(); + HTLCForwardInfo::AddHTLC(payment) => { + let PendingAddHTLCInfo { + prev_short_channel_id, + prev_htlc_id, + prev_channel_id, + prev_funding_outpoint, + prev_user_channel_id, + prev_counterparty_node_id, + forward_info: + PendingHTLCInfo { + ref routing, + incoming_shared_secret, + payment_hash, + outgoing_amt_msat, + outgoing_cltv_value, + .. + }, + } = payment; let logger = WithContext::from( &self.logger, forwarding_counterparty, @@ -6657,19 +6666,11 @@ where |msg, reason, err_data, phantom_ss, next_hop_unknown| { log_info!(logger, "Failed to accept/forward incoming HTLC: {}", msg); - let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: prev_short_channel_id, - user_channel_id: Some(prev_user_channel_id), - channel_id: prev_channel_id, - outpoint: prev_funding_outpoint, - counterparty_node_id: Some(prev_counterparty_node_id), - htlc_id: prev_htlc_id, - incoming_packet_shared_secret: incoming_shared_secret, - phantom_shared_secret: phantom_ss, - blinded_failure: routing.blinded_failure(), - cltv_expiry, - }); - + let mut prev_hop = payment.htlc_previous_hop_data(); + // Override the phantom shared secret because it wasn't set in the originating + // `PendingAddHTLCInfo` above, it was calculated below after detecting this as a + // phantom payment. + prev_hop.phantom_shared_secret = phantom_ss; let failure_type = if next_hop_unknown { HTLCHandlingFailureType::InvalidForward { requested_forward_scid: short_chan_id, @@ -6679,7 +6680,7 @@ where }; failed_forwards.push(( - htlc_source, + HTLCSource::PreviousHopData(prev_hop), payment_hash, HTLCFailReason::reason(reason, err_data), failure_type, @@ -6848,43 +6849,29 @@ where let mut draining_pending_forwards = pending_forwards.drain(..); while let Some(forward_info) = draining_pending_forwards.next() { let queue_fail_htlc_res = match forward_info { - HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, - prev_htlc_id, - prev_channel_id, - prev_funding_outpoint, - prev_user_channel_id, - prev_counterparty_node_id, - forward_info: - PendingHTLCInfo { - incoming_shared_secret, - payment_hash, - outgoing_amt_msat, - outgoing_cltv_value, - routing: - PendingHTLCRouting::Forward { - ref onion_packet, - blinded, - incoming_cltv_expiry, - .. - }, - skimmed_fee_msat, - .. + HTLCForwardInfo::AddHTLC(ref payment) => { + let htlc_source = HTLCSource::PreviousHopData(payment.htlc_previous_hop_data()); + let PendingAddHTLCInfo { + prev_short_channel_id, + forward_info: + PendingHTLCInfo { + payment_hash, + outgoing_amt_msat, + outgoing_cltv_value, + routing, + skimmed_fee_msat, + .. + }, + .. + } = payment; + let (onion_packet, blinded) = match routing { + PendingHTLCRouting::Forward { ref onion_packet, blinded, .. } => { + (onion_packet, blinded) }, - }) => { - let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: prev_short_channel_id, - user_channel_id: Some(prev_user_channel_id), - counterparty_node_id: Some(prev_counterparty_node_id), - channel_id: prev_channel_id, - outpoint: prev_funding_outpoint, - htlc_id: prev_htlc_id, - incoming_packet_shared_secret: incoming_shared_secret, - // Phantom payments are only PendingHTLCRouting::Receive. - phantom_shared_secret: None, - blinded_failure: blinded.map(|b| b.failure), - cltv_expiry: incoming_cltv_expiry, - }); + _ => { + panic!("short_channel_id != 0 should imply any pending_forward entries are of type Forward"); + }, + }; let next_blinding_point = blinded.and_then(|b| { b.next_blinding_override.or_else(|| { let encrypted_tlvs_ss = self @@ -6950,7 +6937,7 @@ where let logger = WithChannelContext::from( &self.logger, &optimal_channel.context, - Some(payment_hash), + Some(*payment_hash), ); let channel_description = if optimal_channel.funding.get_short_channel_id() == Some(short_chan_id) { @@ -6961,12 +6948,12 @@ where log_trace!(logger, "Forwarding HTLC from SCID {} with payment_hash {} and next hop SCID {} over {} channel {} with corresponding peer {}", prev_short_channel_id, &payment_hash, short_chan_id, channel_description, optimal_channel.context.channel_id(), &counterparty_node_id); if let Err((reason, msg)) = optimal_channel.queue_add_htlc( - outgoing_amt_msat, - payment_hash, - outgoing_cltv_value, + *outgoing_amt_msat, + *payment_hash, + *outgoing_cltv_value, htlc_source.clone(), onion_packet.clone(), - skimmed_fee_msat, + *skimmed_fee_msat, next_blinding_point, &self.fee_estimator, &&logger, @@ -6991,7 +6978,7 @@ where }; failed_forwards.push(( htlc_source, - payment_hash, + *payment_hash, HTLCFailReason::reason(reason, data), failure_type, )); @@ -7008,9 +6995,6 @@ where } None }, - HTLCForwardInfo::AddHTLC { .. } => { - panic!("short_channel_id != 0 should imply any pending_forward entries are of type Forward"); - }, HTLCForwardInfo::FailHTLC { htlc_id, ref err_packet } => { if let Some(chan) = peer_state .channel_by_id @@ -7094,24 +7078,22 @@ where ) { 'next_forwardable_htlc: for forward_info in pending_forwards.drain(..) { match forward_info { - HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, - prev_htlc_id, - prev_channel_id, - prev_funding_outpoint, - prev_user_channel_id, - prev_counterparty_node_id, - forward_info: - PendingHTLCInfo { - routing, - incoming_shared_secret, - payment_hash, - incoming_amt_msat, - outgoing_amt_msat, - skimmed_fee_msat, - .. - }, - }) => { + HTLCForwardInfo::AddHTLC(payment) => { + let prev_hop = payment.htlc_previous_hop_data(); + let PendingAddHTLCInfo { + prev_channel_id, + prev_funding_outpoint, + forward_info: + PendingHTLCInfo { + routing, + payment_hash, + incoming_amt_msat, + outgoing_amt_msat, + skimmed_fee_msat, + .. + }, + .. + } = payment; let blinded_failure = routing.blinded_failure(); let ( cltv_expiry, @@ -7183,18 +7165,7 @@ where }, }; let claimable_htlc = ClaimableHTLC { - prev_hop: HTLCPreviousHopData { - short_channel_id: prev_short_channel_id, - user_channel_id: Some(prev_user_channel_id), - counterparty_node_id: Some(prev_counterparty_node_id), - channel_id: prev_channel_id, - outpoint: prev_funding_outpoint, - htlc_id: prev_htlc_id, - incoming_packet_shared_secret: incoming_shared_secret, - phantom_shared_secret, - blinded_failure, - cltv_expiry: Some(cltv_expiry), - }, + prev_hop, // We differentiate the received value from the sender intended value // if possible so that we don't prematurely mark MPP payments complete // if routing nodes overpay @@ -10657,28 +10628,30 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let is_our_scid = self.short_to_chan_info.read().unwrap().contains_key(&scid); let mut forward_htlcs = self.forward_htlcs.lock().unwrap(); + let payment_hash = forward_info.payment_hash; + let pending_add = PendingAddHTLCInfo { + prev_short_channel_id, + prev_counterparty_node_id, + prev_funding_outpoint, + prev_channel_id, + prev_htlc_id, + prev_user_channel_id, + forward_info, + }; match forward_htlcs.entry(scid) { hash_map::Entry::Occupied(mut entry) => { - entry.get_mut().push(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, - prev_counterparty_node_id, - prev_funding_outpoint, - prev_channel_id, - prev_htlc_id, - prev_user_channel_id, - forward_info, - })); + entry.get_mut().push(HTLCForwardInfo::AddHTLC(pending_add)); }, hash_map::Entry::Vacant(entry) => { if !is_our_scid - && forward_info.incoming_amt_msat.is_some() + && pending_add.forward_info.incoming_amt_msat.is_some() && fake_scid::is_valid_intercept( &self.fake_scid_rand_bytes, scid, &self.chain_hash, ) { let intercept_id = InterceptId( - Sha256::hash(&forward_info.incoming_shared_secret) + Sha256::hash(&pending_add.forward_info.incoming_shared_secret) .to_byte_array(), ); let mut pending_intercepts = @@ -10688,57 +10661,35 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ new_intercept_events.push_back(( events::Event::HTLCIntercepted { requested_next_hop_scid: scid, - payment_hash: forward_info.payment_hash, - inbound_amount_msat: forward_info + payment_hash, + inbound_amount_msat: pending_add + .forward_info .incoming_amt_msat .unwrap(), - expected_outbound_amount_msat: forward_info + expected_outbound_amount_msat: pending_add + .forward_info .outgoing_amt_msat, intercept_id, }, None, )); - entry.insert(PendingAddHTLCInfo { - prev_short_channel_id, - prev_counterparty_node_id, - prev_funding_outpoint, - prev_channel_id, - prev_htlc_id, - prev_user_channel_id, - forward_info, - }); + entry.insert(pending_add); }, hash_map::Entry::Occupied(_) => { let logger = WithContext::from( &self.logger, None, Some(prev_channel_id), - Some(forward_info.payment_hash), + Some(payment_hash), ); log_info!( logger, "Failed to forward incoming HTLC: detected duplicate intercepted payment over short channel id {}", scid ); - let routing = &forward_info.routing; - let htlc_source = - HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: prev_short_channel_id, - user_channel_id: Some(prev_user_channel_id), - counterparty_node_id: Some( - prev_counterparty_node_id, - ), - outpoint: prev_funding_outpoint, - channel_id: prev_channel_id, - htlc_id: prev_htlc_id, - incoming_packet_shared_secret: forward_info - .incoming_shared_secret, - phantom_shared_secret: None, - blinded_failure: routing.blinded_failure(), - cltv_expiry: routing.incoming_cltv_expiry(), - }); - - let payment_hash = forward_info.payment_hash; + let htlc_source = HTLCSource::PreviousHopData( + pending_add.htlc_previous_hop_data(), + ); let reason = HTLCFailReason::from_failure_code( LocalHTLCFailureReason::UnknownNextPeer, ); @@ -10755,15 +10706,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ }, } } else { - entry.insert(vec![HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, - prev_counterparty_node_id, - prev_funding_outpoint, - prev_channel_id, - prev_htlc_id, - prev_user_channel_id, - forward_info, - })]); + entry.insert(vec![HTLCForwardInfo::AddHTLC(pending_add)]); } }, } @@ -13701,19 +13644,7 @@ where let mut intercepted_htlcs = self.pending_intercepted_htlcs.lock().unwrap(); intercepted_htlcs.retain(|_, htlc| { if height >= htlc.forward_info.outgoing_cltv_value - HTLC_FAIL_BACK_BUFFER { - let prev_hop_data = HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: htlc.prev_short_channel_id, - user_channel_id: Some(htlc.prev_user_channel_id), - htlc_id: htlc.prev_htlc_id, - incoming_packet_shared_secret: htlc.forward_info.incoming_shared_secret, - phantom_shared_secret: None, - counterparty_node_id: Some(htlc.prev_counterparty_node_id), - outpoint: htlc.prev_funding_outpoint, - channel_id: htlc.prev_channel_id, - blinded_failure: htlc.forward_info.routing.blinded_failure(), - cltv_expiry: htlc.forward_info.routing.incoming_cltv_expiry(), - }); - + let prev_hop_data = HTLCSource::PreviousHopData(htlc.htlc_previous_hop_data()); let requested_forward_scid /* intercept scid */ = match htlc.forward_info.routing { PendingHTLCRouting::Forward { short_channel_id, .. } => short_channel_id, _ => unreachable!(), diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 476964db889..a66c21ac4ef 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -1106,12 +1106,14 @@ impl OutboundPayments { Ok(()) } - #[rustfmt::skip] pub(super) fn static_invoice_received( &self, invoice: &StaticInvoice, payment_id: PaymentId, features: Bolt12InvoiceFeatures, best_block_height: u32, duration_since_epoch: Duration, entropy_source: ES, - pending_events: &Mutex)>> - ) -> Result<(), Bolt12PaymentError> where ES::Target: EntropySource { + pending_events: &Mutex)>>, + ) -> Result<(), Bolt12PaymentError> + where + ES::Target: EntropySource, + { macro_rules! abandon_with_entry { ($payment: expr, $reason: expr) => { assert!( @@ -1130,64 +1132,82 @@ impl OutboundPayments { match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(mut entry) => match entry.get_mut() { PendingOutboundPayment::AwaitingInvoice { - retry_strategy, retryable_invoice_request, route_params_config, .. + retry_strategy, + retryable_invoice_request, + route_params_config, + .. } => { let invreq = &retryable_invoice_request .as_ref() .ok_or(Bolt12PaymentError::UnexpectedInvoice)? .invoice_request; if !invoice.is_from_same_offer(invreq) { - return Err(Bolt12PaymentError::UnexpectedInvoice) + return Err(Bolt12PaymentError::UnexpectedInvoice); } if invoice.invoice_features().requires_unknown_bits_from(&features) { abandon_with_entry!(entry, PaymentFailureReason::UnknownRequiredFeatures); - return Err(Bolt12PaymentError::UnknownRequiredFeatures) + return Err(Bolt12PaymentError::UnknownRequiredFeatures); } - if duration_since_epoch > invoice.created_at().saturating_add(invoice.relative_expiry()) { + if duration_since_epoch + > invoice.created_at().saturating_add(invoice.relative_expiry()) + { abandon_with_entry!(entry, PaymentFailureReason::PaymentExpired); - return Err(Bolt12PaymentError::SendingFailed(RetryableSendFailure::PaymentExpired)) + return Err(Bolt12PaymentError::SendingFailed( + RetryableSendFailure::PaymentExpired, + )); } - let amount_msat = match InvoiceBuilder::::amount_msats(invreq) { + let amount_msat = match InvoiceBuilder::::amount_msats( + invreq, + ) { Ok(amt) => amt, Err(_) => { // We check this during invoice request parsing, when constructing the invreq's // contents from its TLV stream. debug_assert!(false, "LDK requires an msat amount in either the invreq or the invreq's underlying offer"); abandon_with_entry!(entry, PaymentFailureReason::UnexpectedError); - return Err(Bolt12PaymentError::UnknownRequiredFeatures) - } + return Err(Bolt12PaymentError::UnknownRequiredFeatures); + }, }; - let keysend_preimage = PaymentPreimage(entropy_source.get_secure_random_bytes()); - let payment_hash = PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array()); + let keysend_preimage = + PaymentPreimage(entropy_source.get_secure_random_bytes()); + let payment_hash = + PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array()); let pay_params = PaymentParameters::from_static_invoice(invoice) .with_user_config_ignoring_fee_limit(*route_params_config); - let mut route_params = RouteParameters::from_payment_params_and_value(pay_params, amount_msat); - route_params.max_total_routing_fee_msat = route_params_config.max_total_routing_fee_msat; + let mut route_params = + RouteParameters::from_payment_params_and_value(pay_params, amount_msat); + route_params.max_total_routing_fee_msat = + route_params_config.max_total_routing_fee_msat; if let Err(()) = onion_utils::set_max_path_length( - &mut route_params, &RecipientOnionFields::spontaneous_empty(), Some(keysend_preimage), - Some(invreq), best_block_height + &mut route_params, + &RecipientOnionFields::spontaneous_empty(), + Some(keysend_preimage), + Some(invreq), + best_block_height, ) { abandon_with_entry!(entry, PaymentFailureReason::RouteNotFound); - return Err(Bolt12PaymentError::SendingFailed(RetryableSendFailure::OnionPacketSizeExceeded)) + return Err(Bolt12PaymentError::SendingFailed( + RetryableSendFailure::OnionPacketSizeExceeded, + )); } - let absolute_expiry = duration_since_epoch.saturating_add(ASYNC_PAYMENT_TIMEOUT_RELATIVE_EXPIRY); + let absolute_expiry = + duration_since_epoch.saturating_add(ASYNC_PAYMENT_TIMEOUT_RELATIVE_EXPIRY); *entry.into_mut() = PendingOutboundPayment::StaticInvoiceReceived { payment_hash, keysend_preimage, retry_strategy: *retry_strategy, route_params, - invoice_request: - retryable_invoice_request + invoice_request: retryable_invoice_request .take() .ok_or(Bolt12PaymentError::UnexpectedInvoice)? .invoice_request, static_invoice: invoice.clone(), expiry_time: absolute_expiry, }; - return Ok(()) + return Ok(()); }, _ => return Err(Bolt12PaymentError::DuplicateInvoice), }, @@ -1195,12 +1215,17 @@ impl OutboundPayments { }; } - #[rustfmt::skip] pub(super) fn send_payment_for_static_invoice< - R: Deref, ES: Deref, NS: Deref, NL: Deref, IH, SP, L: Deref + R: Deref, + ES: Deref, + NS: Deref, + NL: Deref, + IH, + SP, + L: Deref, >( - &self, payment_id: PaymentId, router: &R, first_hops: Vec, inflight_htlcs: IH, - entropy_source: &ES, node_signer: &NS, node_id_lookup: &NL, + &self, payment_id: PaymentId, router: &R, first_hops: Vec, + inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1, best_block_height: u32, logger: &L, pending_events: &Mutex)>>, send_payment_along_path: SP, @@ -1214,24 +1239,55 @@ impl OutboundPayments { IH: Fn() -> InFlightHtlcs, SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - let (payment_hash, keysend_preimage, route_params, retry_strategy, invoice_request, invoice) = - match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { - hash_map::Entry::Occupied(entry) => match entry.get() { - PendingOutboundPayment::StaticInvoiceReceived { - payment_hash, route_params, retry_strategy, keysend_preimage, invoice_request, static_invoice, .. - } => { - (*payment_hash, *keysend_preimage, route_params.clone(), *retry_strategy, - invoice_request.clone(), static_invoice.clone()) - }, - _ => return Err(Bolt12PaymentError::DuplicateInvoice), - }, - hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice), - }; + let ( + payment_hash, + keysend_preimage, + route_params, + retry_strategy, + invoice_request, + invoice, + ) = match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { + hash_map::Entry::Occupied(entry) => match entry.get() { + PendingOutboundPayment::StaticInvoiceReceived { + payment_hash, + route_params, + retry_strategy, + keysend_preimage, + invoice_request, + static_invoice, + .. + } => ( + *payment_hash, + *keysend_preimage, + route_params.clone(), + *retry_strategy, + invoice_request.clone(), + static_invoice.clone(), + ), + _ => return Err(Bolt12PaymentError::DuplicateInvoice), + }, + hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice), + }; let invoice = PaidBolt12Invoice::StaticInvoice(invoice); self.send_payment_for_bolt12_invoice_internal( - payment_id, payment_hash, Some(keysend_preimage), Some(&invoice_request), invoice, route_params, - retry_strategy, router, first_hops, inflight_htlcs, entropy_source, node_signer, - node_id_lookup, secp_ctx, best_block_height, logger, pending_events, send_payment_along_path + payment_id, + payment_hash, + Some(keysend_preimage), + Some(&invoice_request), + invoice, + route_params, + retry_strategy, + router, + first_hops, + inflight_htlcs, + entropy_source, + node_signer, + node_id_lookup, + secp_ctx, + best_block_height, + logger, + pending_events, + send_payment_along_path, ) } diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index 4bec3dc31b3..1cbea9fef8d 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -437,8 +437,7 @@ fn one_blinded_hop() { let entropy = &*nodes[1].entropy_source; let receive_key = nodes[1].messenger.node_signer.get_receive_auth_key(); let blinded_path = - BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx) - .unwrap(); + BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap(); @@ -463,8 +462,7 @@ fn blinded_path_with_dummy_hops() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); // Ensure that dummy hops are added to the blinded path. assert_eq!(blinded_path.blinded_hops().len(), 6); let destination = Destination::BlindedPath(blinded_path); @@ -492,8 +490,7 @@ fn two_unblinded_two_blinded() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let path = OnionMessagePath { intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id], destination: Destination::BlindedPath(blinded_path), @@ -525,8 +522,7 @@ fn three_blinded_hops() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -553,8 +549,7 @@ fn async_response_over_one_blinded_hop() { let entropy = &*nodes[1].entropy_source; let receive_key = nodes[1].messenger.node_signer.get_receive_auth_key(); let reply_path = - BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx) - .unwrap(); + BlindedMessagePath::new(&[], nodes[1].node_id, receive_key, context, entropy, &secp_ctx); // 4. Create a responder using the reply path for Alice. let responder = Some(Responder::new(reply_path)); @@ -595,8 +590,7 @@ fn async_response_with_reply_path_succeeds() { let entropy = &*bob.entropy_source; let receive_key = bob.messenger.node_signer.get_receive_auth_key(); let reply_path = - BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx) - .unwrap(); + BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx); // Alice asynchronously responds to Bob, expecting a response back from him. let responder = Responder::new(reply_path); @@ -638,8 +632,7 @@ fn async_response_with_reply_path_fails() { let entropy = &*bob.entropy_source; let receive_key = bob.messenger.node_signer.get_receive_auth_key(); let reply_path = - BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx) - .unwrap(); + BlindedMessagePath::new(&[], bob.node_id, receive_key, context, entropy, &secp_ctx); // Alice tries to asynchronously respond to Bob, but fails because the nodes are unannounced and // disconnected. Thus, a reply path could no be created for the response. @@ -697,8 +690,7 @@ fn test_blinded_path_padding_for_full_length_path() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); assert!(is_padded(&blinded_path.blinded_hops(), MESSAGE_PADDING_ROUND_OFF)); @@ -734,8 +726,7 @@ fn test_blinded_path_no_padding_for_compact_path() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); assert!(!is_padded(&blinded_path.blinded_hops(), MESSAGE_PADDING_ROUND_OFF)); } @@ -762,8 +753,7 @@ fn we_are_intro_node() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -784,8 +774,7 @@ fn we_are_intro_node() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -814,8 +803,7 @@ fn invalid_blinded_path_error() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); blinded_path.clear_blinded_hops(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -850,8 +838,7 @@ fn reply_path() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); nodes[0] .messenger .send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)) @@ -878,8 +865,7 @@ fn reply_path() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let destination = Destination::BlindedPath(blinded_path); let intermediate_nodes = [ MessageForwardNode { node_id: nodes[2].node_id, short_channel_id: None }, @@ -895,8 +881,7 @@ fn reply_path() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let instructions = MessageSendInstructions::WithSpecifiedReplyPath { destination, reply_path }; nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap(); @@ -1000,8 +985,7 @@ fn requests_peer_connection_for_buffered_messages() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -1049,8 +1033,7 @@ fn drops_buffered_messages_waiting_for_peer_connection() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -1114,8 +1097,7 @@ fn intercept_offline_peer_oms() { context, entropy, &secp_ctx, - ) - .unwrap(); + ); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index ede82b41aa8..4fe2a63ae16 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -272,7 +272,7 @@ where /// ]; /// let context = MessageContext::Custom(Vec::new()); /// let receive_key = keys_manager.get_receive_auth_key(); -/// let blinded_path = BlindedMessagePath::new(&hops, your_node_id, receive_key, context, &keys_manager, &secp_ctx).unwrap(); +/// let blinded_path = BlindedMessagePath::new(&hops, your_node_id, receive_key, context, &keys_manager, &secp_ctx); /// /// // Send a custom onion message to a blinded path. /// let destination = Destination::BlindedPath(blinded_path); @@ -627,16 +627,14 @@ where .into_iter() .map(|(peer, _, _)| build_path(&[peer])) .take(MAX_PATHS) - .collect::, _>>() - .ok() - .filter(|paths| !paths.is_empty()) - .or_else(|| { - is_recipient_announced - .then(|| build_path(&[])) - .and_then(|result| result.ok()) - .map(|path| vec![path]) - }) - .ok_or(())?; + .collect::>(); + if paths.is_empty() { + if is_recipient_announced { + paths = vec![build_path(&[])]; + } else { + return Err(()); + } + } // Sanity check: Ones the paths are created for the non-compact case, ensure // each of them are of the length `PADDED_PATH_LENGTH`. @@ -2464,8 +2462,7 @@ fn packet_payloads_and_keys< mu, }); }, - ) - .map_err(|e| SendError::Secp256k1(e))?; + ); if let Some(control_tlvs) = final_control_tlvs { payloads.push((