X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Foutbound_payment.rs;h=b82cc436a114e224c266709c7fb6adfc06013eec;hb=1059ac3c28d0f7bac70bdc9be6d85e936fa6a358;hp=2adabebe7e3eca165ec40a3a9f3302c5cf2b47a9;hpb=34bdf224891dfc42b50e09e29f40e0633b2aba25;p=rust-lightning diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 2adabebe..b82cc436 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -23,7 +23,7 @@ use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, Rout use crate::util::errors::APIError; use crate::util::logger::Logger; use crate::util::time::Time; -#[cfg(all(not(feature = "no-std"), test))] +#[cfg(all(feature = "std", test))] use crate::util::time::tests::SinceEpoch; use crate::util::ser::ReadableArgs; @@ -243,7 +243,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(); @@ -282,7 +282,7 @@ pub enum Retry { /// retry, and may retry multiple failed HTLCs at once if they failed around the same time and /// were retried along a route from a single call to [`Router::find_route_with_id`]. Attempts(u32), - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] /// Time elapsed before abandoning retries for a payment. At least one attempt at payment is made; /// see [`PaymentParameters::expiry_time`] to avoid any attempt at payment after a specific time. /// @@ -290,13 +290,13 @@ pub enum Retry { Timeout(core::time::Duration), } -#[cfg(feature = "no-std")] +#[cfg(not(feature = "std"))] impl_writeable_tlv_based_enum!(Retry, ; (0, Attempts) ); -#[cfg(not(feature = "no-std"))] +#[cfg(feature = "std")] impl_writeable_tlv_based_enum!(Retry, ; (0, Attempts), @@ -309,10 +309,10 @@ impl Retry { (Retry::Attempts(max_retry_count), PaymentAttempts { count, .. }) => { max_retry_count > count }, - #[cfg(all(not(feature = "no-std"), not(test)))] + #[cfg(all(feature = "std", not(test)))] (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => *max_duration >= crate::util::time::MonotonicTime::now().duration_since(*first_attempted_at), - #[cfg(all(not(feature = "no-std"), test))] + #[cfg(all(feature = "std", test))] (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => *max_duration >= SinceEpoch::now().duration_since(*first_attempted_at), } @@ -338,27 +338,27 @@ pub(crate) struct PaymentAttemptsUsingTime { /// it means the result of the first attempt is not known yet. pub(crate) count: u32, /// This field is only used when retry is `Retry::Timeout` which is only build with feature std - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] first_attempted_at: T, - #[cfg(feature = "no-std")] + #[cfg(not(feature = "std"))] phantom: core::marker::PhantomData, } -#[cfg(not(any(feature = "no-std", test)))] -type ConfiguredTime = crate::util::time::MonotonicTime; -#[cfg(feature = "no-std")] +#[cfg(not(feature = "std"))] type ConfiguredTime = crate::util::time::Eternity; -#[cfg(all(not(feature = "no-std"), test))] +#[cfg(all(feature = "std", not(test)))] +type ConfiguredTime = crate::util::time::MonotonicTime; +#[cfg(all(feature = "std", test))] type ConfiguredTime = SinceEpoch; impl PaymentAttemptsUsingTime { pub(crate) fn new() -> Self { PaymentAttemptsUsingTime { count: 0, - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] first_attempted_at: T::now(), - #[cfg(feature = "no-std")] + #[cfg(not(feature = "std"))] phantom: core::marker::PhantomData, } } @@ -366,9 +366,9 @@ impl PaymentAttemptsUsingTime { impl Display for PaymentAttemptsUsingTime { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { - #[cfg(feature = "no-std")] + #[cfg(not(feature = "std"))] return write!(f, "attempts: {}", self.count); - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] return write!( f, "attempts: {}, duration: {}s", @@ -728,7 +728,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 +747,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)?; @@ -762,7 +762,6 @@ impl OutboundPayments { } } - #[allow(unused)] pub(super) fn send_payment_for_bolt12_invoice( &self, invoice: &Bolt12Invoice, payment_id: PaymentId, router: &R, first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, @@ -779,7 +778,7 @@ impl OutboundPayments { SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, { let payment_hash = invoice.payment_hash(); - let mut max_total_routing_fee_msat = None; + let max_total_routing_fee_msat; match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(entry) => match entry.get() { PendingOutboundPayment::AwaitingInvoice { retry_strategy, max_total_routing_fee_msat: max_total_fee, .. } => { @@ -795,11 +794,12 @@ impl OutboundPayments { hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice), }; - let route_params = RouteParameters { - payment_params: PaymentParameters::from_bolt12_invoice(&invoice), - final_value_msat: invoice.amount_msats(), - max_total_routing_fee_msat, - }; + let pay_params = PaymentParameters::from_bolt12_invoice(&invoice); + let amount_msat = invoice.amount_msats(); + let mut route_params = RouteParameters::from_payment_params_and_value(pay_params, amount_msat); + if let Some(max_fee_msat) = max_total_routing_fee_msat { + route_params.max_total_routing_fee_msat = Some(max_fee_msat); + } self.find_route_and_send_payment( payment_hash, payment_id, route_params, router, first_hops, &inflight_htlcs, @@ -1337,6 +1337,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 +1470,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 +1490,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, @@ -1526,9 +1533,6 @@ impl OutboundPayments { pending_events: &Mutex)>>) { let mut pending_outbound_payments = self.pending_outbound_payments.lock().unwrap(); - #[cfg(not(invreqfailed))] - let pending_events = pending_events.lock().unwrap(); - #[cfg(invreqfailed)] let mut pending_events = pending_events.lock().unwrap(); pending_outbound_payments.retain(|payment_id, payment| match payment { // If an outbound payment was completed, and no pending HTLCs remain, we should remove it @@ -1578,7 +1582,6 @@ impl OutboundPayments { }, }; if is_stale { - #[cfg(invreqfailed)] pending_events.push_back( (events::Event::InvoiceRequestFailed { payment_id: *payment_id }, None) ); @@ -1734,7 +1737,6 @@ impl OutboundPayments { payment.remove(); } } else if let PendingOutboundPayment::AwaitingInvoice { .. } = payment.get() { - #[cfg(invreqfailed)] pending_events.lock().unwrap().push_back((events::Event::InvoiceRequestFailed { payment_id, }, None)); @@ -1768,7 +1770,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, @@ -1828,6 +1830,7 @@ mod tests { use crate::ln::features::{ChannelFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError}; use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, Retry, RetryableSendFailure, StaleExpiration}; + #[cfg(feature = "std")] use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY; use crate::offers::offer::OfferBuilder; use crate::offers::test_utils::*; @@ -1873,7 +1876,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); @@ -1917,7 +1920,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); @@ -1956,7 +1959,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); @@ -2032,7 +2035,6 @@ mod tests { } #[test] - #[cfg(invreqfailed)] fn removes_stale_awaiting_invoice_using_absolute_timeout() { let pending_events = Mutex::new(VecDeque::new()); let outbound_payments = OutboundPayments::new(); @@ -2083,7 +2085,6 @@ mod tests { } #[test] - #[cfg(invreqfailed)] fn removes_stale_awaiting_invoice_using_timer_ticks() { let pending_events = Mutex::new(VecDeque::new()); let outbound_payments = OutboundPayments::new(); @@ -2133,7 +2134,6 @@ mod tests { } #[test] - #[cfg(invreqfailed)] fn removes_abandoned_awaiting_invoice() { let pending_events = Mutex::new(VecDeque::new()); let outbound_payments = OutboundPayments::new(); @@ -2166,7 +2166,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2217,7 +2217,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2276,7 +2276,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2335,7 +2335,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new());