X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Foutbound_payment.rs;h=a9ced49f647a75e13a1a2a535c38fa86ef29a1c9;hb=1a5482a8bbf56c66adb6a3f889c52ecf15fa8bb1;hp=f745363036b7b2caf4ba72ad8ab8bb01185b46e1;hpb=071297234ac3490bcbdc30caa7f6768ecea9eca7;p=rust-lightning diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index f7453630..a9ced49f 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -48,6 +48,7 @@ pub(crate) enum PendingOutboundPayment { session_privs: HashSet<[u8; 32]>, payment_hash: PaymentHash, payment_secret: Option, + keysend_preimage: Option, pending_amt_msat: u64, /// Used to track the fee paid. Only present if the payment was serialized on 0.0.103+. pending_fee_msat: Option, @@ -415,7 +416,7 @@ impl OutboundPayments { F: Fn(&Vec, &Option, &PaymentHash, &Option, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError>, { - self.pay_internal(payment_id, Some((payment_hash, payment_secret, retry_strategy)), + self.pay_internal(payment_id, Some((payment_hash, payment_secret, None, retry_strategy)), route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, &send_payment_along_path) .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e }) @@ -432,13 +433,37 @@ impl OutboundPayments { F: Fn(&Vec, &Option, &PaymentHash, &Option, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { - let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, route, None, None, entropy_source, best_block_height)?; + let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, None, route, None, None, entropy_source, best_block_height)?; self.pay_route_internal(route, payment_hash, payment_secret, None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e }) } - pub(super) fn send_spontaneous_payment( + pub(super) fn send_spontaneous_payment( + &self, payment_preimage: Option, payment_id: PaymentId, + retry_strategy: Retry, route_params: RouteParameters, router: &R, + first_hops: Vec, inflight_htlcs: InFlightHtlcs, entropy_source: &ES, + node_signer: &NS, best_block_height: u32, logger: &L, send_payment_along_path: F + ) -> Result + where + R::Target: Router, + ES::Target: EntropySource, + NS::Target: NodeSigner, + L::Target: Logger, + F: Fn(&Vec, &Option, &PaymentHash, &Option, u64, + u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError>, + { + let preimage = payment_preimage + .unwrap_or_else(|| PaymentPreimage(entropy_source.get_secure_random_bytes())); + let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner()); + self.pay_internal(payment_id, Some((payment_hash, &None, Some(preimage), retry_strategy)), + route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, + best_block_height, logger, &send_payment_along_path) + .map(|()| payment_hash) + .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e }) + } + + pub(super) fn send_spontaneous_payment_with_route( &self, route: &Route, payment_preimage: Option, payment_id: PaymentId, entropy_source: &ES, node_signer: &NS, best_block_height: u32, send_payment_along_path: F ) -> Result @@ -448,12 +473,10 @@ impl OutboundPayments { F: Fn(&Vec, &Option, &PaymentHash, &Option, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { - let preimage = match payment_preimage { - Some(p) => p, - None => PaymentPreimage(entropy_source.get_secure_random_bytes()), - }; + 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 onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, &route, None, None, entropy_source, best_block_height)?; + let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, Some(preimage), &route, None, None, entropy_source, best_block_height)?; match self.pay_route_internal(route, payment_hash, &None, Some(preimage), payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) { Ok(()) => Ok(payment_hash), @@ -511,7 +534,7 @@ impl OutboundPayments { fn pay_internal( &self, payment_id: PaymentId, - initial_send_info: Option<(PaymentHash, &Option, Retry)>, + initial_send_info: Option<(PaymentHash, &Option, Option, Retry)>, route_params: RouteParameters, router: &R, first_hops: Vec, inflight_htlcs: InFlightHtlcs, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, send_payment_along_path: &F, @@ -539,8 +562,8 @@ impl OutboundPayments { err: format!("Failed to find a route for payment {}: {:?}", log_bytes!(payment_id.0), e), // TODO: add APIError::RouteNotFound }))?; - let res = if let Some((payment_hash, payment_secret, retry_strategy)) = initial_send_info { - let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, &route, Some(retry_strategy), Some(route_params.payment_params.clone()), entropy_source, best_block_height)?; + let res = if let Some((payment_hash, payment_secret, keysend_preimage, retry_strategy)) = initial_send_info { + let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, keysend_preimage, &route, Some(retry_strategy), Some(route_params.payment_params.clone()), entropy_source, best_block_height)?; self.pay_route_internal(&route, payment_hash, payment_secret, None, payment_id, None, onion_session_privs, node_signer, best_block_height, send_payment_along_path) } else { self.retry_payment_with_route(&route, payment_id, entropy_source, node_signer, best_block_height, send_payment_along_path) @@ -596,13 +619,13 @@ impl OutboundPayments { onion_session_privs.push(entropy_source.get_secure_random_bytes()); } - let (total_msat, payment_hash, payment_secret) = { + let (total_msat, payment_hash, payment_secret, keysend_preimage) = { let mut outbounds = self.pending_outbound_payments.lock().unwrap(); match outbounds.get_mut(&payment_id) { Some(payment) => { let res = match payment { PendingOutboundPayment::Retryable { - total_msat, payment_hash, payment_secret, pending_amt_msat, .. + total_msat, payment_hash, keysend_preimage, payment_secret, pending_amt_msat, .. } => { let retry_amt_msat: u64 = route.paths.iter().map(|path| path.last().unwrap().fee_msat).sum(); if retry_amt_msat + *pending_amt_msat > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 { @@ -610,7 +633,7 @@ impl OutboundPayments { err: format!("retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat).to_string() })) } - (*total_msat, *payment_hash, *payment_secret) + (*total_msat, *payment_hash, *payment_secret, *keysend_preimage) }, PendingOutboundPayment::Legacy { .. } => { return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { @@ -645,7 +668,7 @@ impl OutboundPayments { })), } }; - self.pay_route_internal(route, payment_hash, &payment_secret, None, payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height, &send_payment_along_path) + self.pay_route_internal(route, payment_hash, &payment_secret, keysend_preimage, payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height, &send_payment_along_path) } pub(super) fn send_probe( @@ -669,7 +692,7 @@ impl OutboundPayments { } let route = Route { paths: vec![hops], payment_params: None }; - let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, &route, None, None, entropy_source, best_block_height)?; + let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, None, &route, None, None, entropy_source, best_block_height)?; match self.pay_route_internal(&route, payment_hash, &None, None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) { Ok(()) => Ok((payment_hash, payment_id)), @@ -685,13 +708,13 @@ impl OutboundPayments { &self, payment_hash: PaymentHash, payment_secret: Option, payment_id: PaymentId, route: &Route, retry_strategy: Option, entropy_source: &ES, best_block_height: u32 ) -> Result, PaymentSendFailure> where ES::Target: EntropySource { - self.add_new_pending_payment(payment_hash, payment_secret, payment_id, route, retry_strategy, None, entropy_source, best_block_height) + self.add_new_pending_payment(payment_hash, payment_secret, payment_id, None, route, retry_strategy, None, entropy_source, best_block_height) } pub(super) fn add_new_pending_payment( &self, payment_hash: PaymentHash, payment_secret: Option, payment_id: PaymentId, - route: &Route, retry_strategy: Option, payment_params: Option, - entropy_source: &ES, best_block_height: u32 + keysend_preimage: Option, route: &Route, retry_strategy: Option, + payment_params: Option, entropy_source: &ES, best_block_height: u32 ) -> Result, PaymentSendFailure> where ES::Target: EntropySource { let mut onion_session_privs = Vec::with_capacity(route.paths.len()); for _ in 0..route.paths.len() { @@ -711,6 +734,7 @@ impl OutboundPayments { pending_fee_msat: Some(0), payment_hash, payment_secret, + keysend_preimage, starting_block_height: best_block_height, total_msat: route.get_total_amount(), }); @@ -1153,6 +1177,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment, (2, payment_hash, required), (3, payment_params, option), (4, payment_secret, option), + (5, keysend_preimage, option), (6, total_msat, required), (8, pending_amt_msat, required), (10, starting_block_height, required), @@ -1247,9 +1272,9 @@ mod tests { Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError })); let err = if on_retry { - outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]), - &Route { paths: vec![], payment_params: None }, Some(Retry::Attempts(1)), Some(route_params.payment_params.clone()), - &&keys_manager, 0).unwrap(); + outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]), None, + &Route { paths: vec![], payment_params: None }, Some(Retry::Attempts(1)), + Some(route_params.payment_params.clone()), &&keys_manager, 0).unwrap(); outbound_payments.pay_internal( PaymentId([0; 32]), None, route_params, &&router, vec![], InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, &|_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()