if route.paths.len() < 1 {
return Err(PaymentSendFailure::ParameterError(APIError::InvalidRoute{err: "There must be at least one path to send over".to_owned()}));
}
- if recipient_onion.payment_secret.is_none() && route.paths.len() > 1 {
+ if recipient_onion.payment_secret.is_none() && route.paths.len() > 1
+ && !route.paths.iter().any(|p| p.blinded_tail.is_some())
+ {
return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError{err: "Payment secret is required for multi-path payments".to_owned()}));
}
let mut total_value = 0;
path_errs.push(Err(APIError::InvalidRoute{err: "Path didn't go anywhere/had bogus size".to_owned()}));
continue 'path_check;
}
- if path.blinded_tail.is_some() {
- path_errs.push(Err(APIError::InvalidRoute{err: "Sending to blinded paths isn't supported yet".to_owned()}));
- continue 'path_check;
- }
let dest_hop_idx = if path.blinded_tail.is_some() && path.blinded_tail.as_ref().unwrap().hops.len() > 1 {
usize::max_value() } else { path.hops.len() - 1 };
for (idx, hop) in path.hops.iter().enumerate() {
) -> bool where L::Target: Logger {
#[cfg(test)]
let DecodedOnionFailure {
- network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data
+ network_update, short_channel_id, payment_failed_permanently, onion_error_code,
+ onion_error_data
} = onion_error.decode_onion_failure(secp_ctx, logger, &source);
#[cfg(not(test))]
- let DecodedOnionFailure { network_update, short_channel_id, payment_retryable } =
+ let DecodedOnionFailure { network_update, short_channel_id, payment_failed_permanently } =
onion_error.decode_onion_failure(secp_ctx, logger, &source);
let payment_is_probe = payment_is_probe(payment_hash, &payment_id, probing_cookie_secret);
payment.get_mut().insert_previously_failed_scid(scid);
}
- if payment_is_probe || !is_retryable_now || !payment_retryable {
- let reason = if !payment_retryable {
+ if payment_is_probe || !is_retryable_now || payment_failed_permanently {
+ let reason = if payment_failed_permanently {
PaymentFailureReason::RecipientRejected
} else {
PaymentFailureReason::RetriesExhausted
let path_failure = {
if payment_is_probe {
- if !payment_retryable {
+ if payment_failed_permanently {
events::Event::ProbeSuccessful {
payment_id: *payment_id,
payment_hash: payment_hash.clone(),
events::Event::PaymentPathFailed {
payment_id: Some(*payment_id),
payment_hash: payment_hash.clone(),
- payment_failed_permanently: !payment_retryable,
+ payment_failed_permanently,
failure: events::PathFailure::OnPath { network_update },
path: path.clone(),
short_channel_id,