+ Err(e) => {
+ Err(APIError::ChannelUnavailable { err: e.err })
+ },
+ }
+ }
+
+ /// Sends a payment along a given route.
+ ///
+ /// Value parameters are provided via the last hop in route, see documentation for RouteHop
+ /// fields for more info.
+ ///
+ /// Note that if the payment_hash already exists elsewhere (eg you're sending a duplicative
+ /// payment), we don't do anything to stop you! We always try to ensure that if the provided
+ /// next hop knows the preimage to payment_hash they can claim an additional amount as
+ /// specified in the last hop in the route! Thus, you should probably do your own
+ /// payment_preimage tracking (which you should already be doing as they represent "proof of
+ /// payment") and prevent double-sends yourself.
+ ///
+ /// May generate SendHTLCs message(s) event on success, which should be relayed.
+ ///
+ /// Each path may have a different return value, and PaymentSendValue may return a Vec with
+ /// each entry matching the corresponding-index entry in the route paths, see
+ /// PaymentSendFailure for more info.
+ ///
+ /// In general, a path may raise:
+ /// * APIError::RouteError when an invalid route or forwarding parameter (cltv_delta, fee,
+ /// node public key) is specified.
+ /// * APIError::ChannelUnavailable if the next-hop channel is not available for updates
+ /// (including due to previous monitor update failure or new permanent monitor update
+ /// failure).
+ /// * APIError::MonitorUpdateFailed if a new monitor update failure prevented sending the
+ /// relevant updates.
+ ///
+ /// Note that depending on the type of the PaymentSendFailure the HTLC may have been
+ /// irrevocably committed to on our end. In such a case, do NOT retry the payment with a
+ /// different route unless you intend to pay twice!
+ ///
+ /// payment_secret is unrelated to payment_hash (or PaymentPreimage) and exists to authenticate
+ /// the sender to the recipient and prevent payment-probing (deanonymization) attacks. For
+ /// newer nodes, it will be provided to you in the invoice. If you do not have one, the Route
+ /// must not contain multiple paths as multi-path payments require a recipient-provided
+ /// payment_secret.
+ /// If a payment_secret *is* provided, we assume that the invoice had the payment_secret feature
+ /// bit set (either as required or as available). If multiple paths are present in the Route,
+ /// we assume the invoice had the basic_mpp feature set.
+ pub fn send_payment(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>) -> Result<(), PaymentSendFailure> {
+ if route.paths.len() < 1 {
+ return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "There must be at least one path to send over"}));
+ }
+ if route.paths.len() > 10 {
+ // This limit is completely arbitrary - there aren't any real fundamental path-count
+ // limits. After we support retrying individual paths we should likely bump this, but
+ // for now more than 10 paths likely carries too much one-path failure.
+ return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "Sending over more than 10 paths is not currently supported"}));
+ }
+ let mut total_value = 0;
+ let our_node_id = self.get_our_node_id();
+ let mut path_errs = Vec::with_capacity(route.paths.len());
+ 'path_check: for path in route.paths.iter() {
+ if path.len() < 1 || path.len() > 20 {
+ path_errs.push(Err(APIError::RouteError{err: "Path didn't go anywhere/had bogus size"}));
+ continue 'path_check;
+ }
+ for (idx, hop) in path.iter().enumerate() {
+ if idx != path.len() - 1 && hop.pubkey == our_node_id {
+ path_errs.push(Err(APIError::RouteError{err: "Path went through us but wasn't a simple rebalance loop to us"}));
+ continue 'path_check;
+ }
+ }
+ total_value += path.last().unwrap().fee_msat;
+ path_errs.push(Ok(()));
+ }
+ if path_errs.iter().any(|e| e.is_err()) {
+ return Err(PaymentSendFailure::PathParameterError(path_errs));
+ }
+
+ let cur_height = self.latest_block_height.load(Ordering::Acquire) as u32 + 1;
+ let mut results = Vec::new();
+ for path in route.paths.iter() {
+ results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height));
+ }
+ let mut has_ok = false;
+ let mut has_err = false;
+ for res in results.iter() {
+ if res.is_ok() { has_ok = true; }
+ if res.is_err() { has_err = true; }
+ if let &Err(APIError::MonitorUpdateFailed) = res {
+ // MonitorUpdateFailed is inherently unsafe to retry, so we call it a
+ // PartialFailure.
+ has_err = true;
+ has_ok = true;
+ break;
+ }
+ }
+ if has_err && has_ok {
+ Err(PaymentSendFailure::PartialFailure(results))
+ } else if has_err {
+ Err(PaymentSendFailure::AllFailedRetrySafe(results.drain(..).map(|r| r.unwrap_err()).collect()))
+ } else {
+ Ok(())