routing+routerrpc: notify full payment structures
This commit fixes the inconsistency between the payment state as reported by routerrpc.SendPayment/routerrpc.TrackPayment and the main rpc ListPayments call. In addition to that, payment state changes are now sent out for every state change. This opens the door to user interfaces giving more feedback to the user about the payment process. This is especially interesting for multi-part payments.
This commit is contained in:
8 files changed
+392
-617
No files matched your search
@@ -441,7 +441,7 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
||||
router := s.cfg.RouterBackend
|
||||
|
||||
// Subscribe to the outcome of this payment.
|
||||
inFlight, resultChan, err := router.Tower.SubscribePayment(
|
||||
subscription, err := router.Tower.SubscribePayment(
|
||||
paymentHash,
|
||||
)
|
||||
switch {
|
||||
@@ -450,95 +450,37 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
defer subscription.Close()
|
||||
|
||||
// If it is in flight, send a state update to the client. Payment status
|
||||
// update streams are expected to always send the current payment state
|
||||
// immediately.
|
||||
if inFlight {
|
||||
err = stream.Send(&PaymentStatus{
|
||||
State: PaymentState_IN_FLIGHT,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the outcome of the payment. For payments that have
|
||||
// completed, the result should already be waiting on the channel.
|
||||
select {
|
||||
case result := <-resultChan:
|
||||
// Marshall result to rpc type.
|
||||
var status PaymentStatus
|
||||
if result.Success {
|
||||
log.Debugf("Payment %v successfully completed",
|
||||
paymentHash)
|
||||
|
||||
status.State = PaymentState_SUCCEEDED
|
||||
status.Preimage = result.Preimage[:]
|
||||
} else {
|
||||
state, err := marshallFailureReason(
|
||||
result.FailureReason,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
// Stream updates back to the client. The first update is always the
|
||||
// current state of the payment.
|
||||
for {
|
||||
select {
|
||||
case item, ok := <-subscription.Updates:
|
||||
if !ok {
|
||||
// No more payment updates.
|
||||
return nil
|
||||
}
|
||||
status.State = state
|
||||
}
|
||||
|
||||
// Marshal our list of HTLCs that have been tried for this
|
||||
// payment.
|
||||
htlcs := make([]*lnrpc.HTLCAttempt, 0, len(result.HTLCs))
|
||||
for _, dbHtlc := range result.HTLCs {
|
||||
htlc, err := router.MarshalHTLCAttempt(dbHtlc)
|
||||
result := item.(*channeldb.MPPayment)
|
||||
rpcPayment, err := router.MarshallPayment(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
htlcs = append(htlcs, htlc)
|
||||
// Send event to the client.
|
||||
err = stream.Send(rpcPayment)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case <-s.quit:
|
||||
return errServerShuttingDown
|
||||
|
||||
case <-stream.Context().Done():
|
||||
log.Debugf("Payment status stream %v canceled", paymentHash)
|
||||
return stream.Context().Err()
|
||||
}
|
||||
status.Htlcs = htlcs
|
||||
|
||||
// Send event to the client.
|
||||
err = stream.Send(&status)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case <-s.quit:
|
||||
return errServerShuttingDown
|
||||
|
||||
case <-stream.Context().Done():
|
||||
log.Debugf("Payment status stream %v canceled", paymentHash)
|
||||
return stream.Context().Err()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// marshallFailureReason marshalls the failure reason to the corresponding rpc
|
||||
// type.
|
||||
func marshallFailureReason(reason channeldb.FailureReason) (
|
||||
PaymentState, error) {
|
||||
|
||||
switch reason {
|
||||
|
||||
case channeldb.FailureReasonTimeout:
|
||||
return PaymentState_FAILED_TIMEOUT, nil
|
||||
|
||||
case channeldb.FailureReasonNoRoute:
|
||||
return PaymentState_FAILED_NO_ROUTE, nil
|
||||
|
||||
case channeldb.FailureReasonError:
|
||||
return PaymentState_FAILED_ERROR, nil
|
||||
|
||||
case channeldb.FailureReasonPaymentDetails:
|
||||
return PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS, nil
|
||||
|
||||
case channeldb.FailureReasonInsufficientBalance:
|
||||
return PaymentState_FAILED_INSUFFICIENT_BALANCE, nil
|
||||
}
|
||||
|
||||
return 0, errors.New("unknown failure reason")
|
||||
}
|
||||
|
||||
// BuildRoute builds a route from a list of hop addresses.
|
||||
|
||||
Reference in new issue
Block a user