X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Foutbound_payment.rs;h=47193bea3f197b2fcd41d261202c612c5f06526a;hb=6b45237f46590eda6412402fb40c1fb0831ed828;hp=0fbb0f5eaf4ccdeffd32d2a7c9d2aea20888273c;hpb=8f308f98dda28f54e1c7603be5a440a8c0c101c8;p=rust-lightning diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 0fbb0f5e..47193bea 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -19,7 +19,7 @@ use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::ln::channelmanager::{ChannelDetails, EventCompletionAction, HTLCSource, PaymentId}; use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason}; use crate::offers::invoice::Bolt12Invoice; -use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router}; +use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router}; use crate::util::errors::APIError; use crate::util::logger::Logger; use crate::util::time::Time; @@ -129,6 +129,11 @@ impl PendingOutboundPayment { params.previously_failed_channels.push(scid); } } + pub fn insert_previously_failed_blinded_path(&mut self, blinded_tail: &BlindedTail) { + if let PendingOutboundPayment::Retryable { payment_params: Some(params), .. } = self { + params.insert_previously_failed_blinded_path(blinded_tail); + } + } fn is_awaiting_invoice(&self) -> bool { match self { PendingOutboundPayment::AwaitingInvoice { .. } => true, @@ -243,7 +248,7 @@ impl PendingOutboundPayment { if insert_res { if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, - ref mut remaining_max_total_routing_fee_msat, .. + ref mut remaining_max_total_routing_fee_msat, .. } = self { *pending_amt_msat += path.final_value_msat(); let path_fee_msat = path.fee_msat(); @@ -728,7 +733,7 @@ impl OutboundPayments { { let preimage = payment_preimage .unwrap_or_else(|| PaymentPreimage(entropy_source.get_secure_random_bytes())); - let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner()); + let payment_hash = PaymentHash(Sha256::hash(&preimage.0).to_byte_array()); self.send_payment_internal(payment_id, payment_hash, recipient_onion, Some(preimage), retry_strategy, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path) @@ -747,7 +752,7 @@ impl OutboundPayments { { let preimage = payment_preimage .unwrap_or_else(|| PaymentPreimage(entropy_source.get_secure_random_bytes())); - let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner()); + let payment_hash = PaymentHash(Sha256::hash(&preimage.0).to_byte_array()); let onion_session_privs = self.add_new_pending_payment(payment_hash, recipient_onion.clone(), payment_id, Some(preimage), &route, None, None, entropy_source, best_block_height)?; @@ -1337,6 +1342,13 @@ impl OutboundPayments { continue 'path_check; } } + for (i, hop) in path.hops.iter().enumerate() { + // Check for duplicate channel_id in the remaining hops of the path + if path.hops.iter().skip(i + 1).any(|other_hop| other_hop.short_channel_id == hop.short_channel_id) { + path_errs.push(Err(APIError::InvalidRoute{err: "Path went through the same channel twice".to_owned()})); + continue 'path_check; + } + } total_value += path.final_value_msat(); path_errs.push(Ok(())); } @@ -1463,7 +1475,7 @@ impl OutboundPayments { let mut pending_events = pending_events.lock().unwrap(); if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { if !payment.get().is_fulfilled() { - let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner()); + let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array()); log_info!(logger, "Payment with id {} and hash {} sent!", payment_id, payment_hash); let fee_paid_msat = payment.get().get_pending_fee_msat(); pending_events.push_back((events::Event::PaymentSent { @@ -1483,7 +1495,7 @@ impl OutboundPayments { // TODO: We should have a second monitor event that informs us of payments // irrevocably fulfilled. if payment.get_mut().remove(&session_priv_bytes, Some(&path)) { - let payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0).into_inner())); + let payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array())); pending_events.push_back((events::Event::PaymentPathSuccessful { payment_id, payment_hash, @@ -1597,11 +1609,12 @@ impl OutboundPayments { #[cfg(test)] let DecodedOnionFailure { network_update, short_channel_id, payment_failed_permanently, onion_error_code, - onion_error_data + onion_error_data, failed_within_blinded_path } = onion_error.decode_onion_failure(secp_ctx, logger, &source); #[cfg(not(test))] - let DecodedOnionFailure { network_update, short_channel_id, payment_failed_permanently } = - onion_error.decode_onion_failure(secp_ctx, logger, &source); + let DecodedOnionFailure { + network_update, short_channel_id, payment_failed_permanently, failed_within_blinded_path + } = onion_error.decode_onion_failure(secp_ctx, logger, &source); let payment_is_probe = payment_is_probe(payment_hash, &payment_id, probing_cookie_secret); let mut session_priv_bytes = [0; 32]; @@ -1640,6 +1653,12 @@ impl OutboundPayments { // next-hop is needlessly blaming us! payment.get_mut().insert_previously_failed_scid(scid); } + if failed_within_blinded_path { + debug_assert!(short_channel_id.is_none()); + if let Some(bt) = &path.blinded_tail { + payment.get_mut().insert_previously_failed_blinded_path(&bt); + } else { debug_assert!(false); } + } if payment_is_probe || !is_retryable_now || payment_failed_permanently { let reason = if payment_failed_permanently { @@ -1763,7 +1782,7 @@ fn probing_cookie_from_id(payment_id: &PaymentId, probing_cookie_secret: [u8; 32 let mut preimage = [0u8; 64]; preimage[..32].copy_from_slice(&probing_cookie_secret); preimage[32..].copy_from_slice(&payment_id.0); - PaymentHash(Sha256::hash(&preimage).into_inner()) + PaymentHash(Sha256::hash(&preimage).to_byte_array()) } impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,