session_privs: HashSet<[u8; 32]>,
payment_hash: PaymentHash,
payment_secret: Option<PaymentSecret>,
+ keysend_preimage: Option<PaymentPreimage>,
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<u64>,
F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
u32, PaymentId, &Option<PaymentPreimage>, [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 })
F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
u32, PaymentId, &Option<PaymentPreimage>, [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<ES: Deref, NS: Deref, F>(
+ pub(super) fn send_spontaneous_payment<R: Deref, ES: Deref, NS: Deref, F, L: Deref>(
+ &self, payment_preimage: Option<PaymentPreimage>, payment_id: PaymentId,
+ retry_strategy: Retry, route_params: RouteParameters, router: &R,
+ first_hops: Vec<ChannelDetails>, inflight_htlcs: InFlightHtlcs, entropy_source: &ES,
+ node_signer: &NS, best_block_height: u32, logger: &L, send_payment_along_path: F
+ ) -> Result<PaymentHash, PaymentSendFailure>
+ where
+ R::Target: Router,
+ ES::Target: EntropySource,
+ NS::Target: NodeSigner,
+ L::Target: Logger,
+ F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
+ u32, PaymentId, &Option<PaymentPreimage>, [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<ES: Deref, NS: Deref, F>(
&self, route: &Route, payment_preimage: Option<PaymentPreimage>, payment_id: PaymentId,
entropy_source: &ES, node_signer: &NS, best_block_height: u32, send_payment_along_path: F
) -> Result<PaymentHash, PaymentSendFailure>
F: Fn(&Vec<RouteHop>, &Option<PaymentParameters>, &PaymentHash, &Option<PaymentSecret>, u64,
u32, PaymentId, &Option<PaymentPreimage>, [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),
fn pay_internal<R: Deref, NS: Deref, ES: Deref, F, L: Deref>(
&self, payment_id: PaymentId,
- initial_send_info: Option<(PaymentHash, &Option<PaymentSecret>, Retry)>,
+ initial_send_info: Option<(PaymentHash, &Option<PaymentSecret>, Option<PaymentPreimage>, Retry)>,
route_params: RouteParameters, router: &R, first_hops: Vec<ChannelDetails>,
inflight_htlcs: InFlightHtlcs, entropy_source: &ES, node_signer: &NS, best_block_height: u32,
logger: &L, send_payment_along_path: &F,
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)
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 {
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 {
})),
}
};
- 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<ES: Deref, NS: Deref, F>(
}
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)),
&self, payment_hash: PaymentHash, payment_secret: Option<PaymentSecret>, payment_id: PaymentId,
route: &Route, retry_strategy: Option<Retry>, entropy_source: &ES, best_block_height: u32
) -> Result<Vec<[u8; 32]>, 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<ES: Deref>(
&self, payment_hash: PaymentHash, payment_secret: Option<PaymentSecret>, payment_id: PaymentId,
- route: &Route, retry_strategy: Option<Retry>, payment_params: Option<PaymentParameters>,
- entropy_source: &ES, best_block_height: u32
+ keysend_preimage: Option<PaymentPreimage>, route: &Route, retry_strategy: Option<Retry>,
+ payment_params: Option<PaymentParameters>, entropy_source: &ES, best_block_height: u32
) -> Result<Vec<[u8; 32]>, PaymentSendFailure> where ES::Target: EntropySource {
let mut onion_session_privs = Vec::with_capacity(route.paths.len());
for _ in 0..route.paths.len() {
pending_fee_msat: Some(0),
payment_hash,
payment_secret,
+ keysend_preimage,
starting_block_height: best_block_height,
total_msat: route.get_total_amount(),
});
(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),
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()