routing+routerrpc+channeldb: return route on invalid payment details
This commit is contained in:
4 files changed
+55
-15
No files matched your search
@@ -246,9 +246,12 @@ func (p *PaymentControl) Success(paymentHash lntypes.Hash,
|
|||||||
// its next call for this payment hash, allowing the switch to make a
|
// its next call for this payment hash, allowing the switch to make a
|
||||||
// subsequent payment.
|
// subsequent payment.
|
||||||
func (p *PaymentControl) Fail(paymentHash lntypes.Hash,
|
func (p *PaymentControl) Fail(paymentHash lntypes.Hash,
|
||||||
reason FailureReason) error {
|
reason FailureReason) (*route.Route, error) {
|
||||||
|
|
||||||
var updateErr error
|
var (
|
||||||
|
updateErr error
|
||||||
|
route *route.Route
|
||||||
|
)
|
||||||
err := p.db.Batch(func(tx *bbolt.Tx) error {
|
err := p.db.Batch(func(tx *bbolt.Tx) error {
|
||||||
// Reset the update error, to avoid carrying over an error
|
// Reset the update error, to avoid carrying over an error
|
||||||
// from a previous execution of the batched db transaction.
|
// from a previous execution of the batched db transaction.
|
||||||
@@ -270,13 +273,27 @@ func (p *PaymentControl) Fail(paymentHash lntypes.Hash,
|
|||||||
|
|
||||||
// Put the failure reason in the bucket for record keeping.
|
// Put the failure reason in the bucket for record keeping.
|
||||||
v := []byte{byte(reason)}
|
v := []byte{byte(reason)}
|
||||||
return bucket.Put(paymentFailInfoKey, v)
|
err = bucket.Put(paymentFailInfoKey, v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve attempt info for the notification, if available.
|
||||||
|
attempt, err := fetchPaymentAttempt(bucket)
|
||||||
|
if err != nil && err != errNoAttemptInfo {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err != errNoAttemptInfo {
|
||||||
|
route = &attempt.Route
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateErr
|
return route, updateErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchPayment returns information about a payment from the database.
|
// FetchPayment returns information about a payment from the database.
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ func TestPaymentControlSwitchFail(t *testing.T) {
|
|||||||
|
|
||||||
// Fail the payment, which should moved it to Failed.
|
// Fail the payment, which should moved it to Failed.
|
||||||
failReason := FailureReasonNoRoute
|
failReason := FailureReasonNoRoute
|
||||||
err = pControl.Fail(info.PaymentHash, failReason)
|
_, err = pControl.Fail(info.PaymentHash, failReason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fail payment hash: %v", err)
|
t.Fatalf("unable to fail payment hash: %v", err)
|
||||||
}
|
}
|
||||||
@@ -270,7 +270,7 @@ func TestPaymentControlFailsWithoutInFlight(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calling Fail should return an error.
|
// Calling Fail should return an error.
|
||||||
err = pControl.Fail(info.PaymentHash, FailureReasonNoRoute)
|
_, err = pControl.Fail(info.PaymentHash, FailureReasonNoRoute)
|
||||||
if err != ErrPaymentNotInitiated {
|
if err != ErrPaymentNotInitiated {
|
||||||
t.Fatalf("expected ErrPaymentNotInitiated, got %v", err)
|
t.Fatalf("expected ErrPaymentNotInitiated, got %v", err)
|
||||||
}
|
}
|
||||||
@@ -330,7 +330,7 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) {
|
|||||||
if p.failed {
|
if p.failed {
|
||||||
// Fail the payment, which should moved it to Failed.
|
// Fail the payment, which should moved it to Failed.
|
||||||
failReason := FailureReasonNoRoute
|
failReason := FailureReasonNoRoute
|
||||||
err = pControl.Fail(info.PaymentHash, failReason)
|
_, err = pControl.Fail(info.PaymentHash, failReason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fail payment hash: %v", err)
|
t.Fatalf("unable to fail payment hash: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -499,8 +499,10 @@ func (s *Server) TrackPayment(request *TrackPaymentRequest,
|
|||||||
func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
||||||
stream Router_TrackPaymentServer) error {
|
stream Router_TrackPaymentServer) error {
|
||||||
|
|
||||||
|
router := s.cfg.RouterBackend
|
||||||
|
|
||||||
// Subscribe to the outcome of this payment.
|
// Subscribe to the outcome of this payment.
|
||||||
inFlight, resultChan, err := s.cfg.RouterBackend.Tower.SubscribePayment(
|
inFlight, resultChan, err := router.Tower.SubscribePayment(
|
||||||
paymentHash,
|
paymentHash,
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
@@ -535,7 +537,7 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
|||||||
|
|
||||||
status.State = PaymentState_SUCCEEDED
|
status.State = PaymentState_SUCCEEDED
|
||||||
status.Preimage = result.Preimage[:]
|
status.Preimage = result.Preimage[:]
|
||||||
status.Route = s.cfg.RouterBackend.MarshallRoute(
|
status.Route = router.MarshallRoute(
|
||||||
result.Route,
|
result.Route,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -546,6 +548,11 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
status.State = state
|
status.State = state
|
||||||
|
if result.Route != nil {
|
||||||
|
status.Route = router.MarshallRoute(
|
||||||
|
result.Route,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send event to the client.
|
// Send event to the client.
|
||||||
|
|||||||
@@ -132,11 +132,21 @@ func createSuccessResult(rt *route.Route,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createFailResult creates a failed result to send to subscribers.
|
// createFailResult creates a failed result to send to subscribers.
|
||||||
func createFailedResult(reason channeldb.FailureReason) *PaymentResult {
|
func createFailedResult(rt *route.Route,
|
||||||
return &PaymentResult{
|
reason channeldb.FailureReason) *PaymentResult {
|
||||||
|
|
||||||
|
result := &PaymentResult{
|
||||||
Success: false,
|
Success: false,
|
||||||
FailureReason: reason,
|
FailureReason: reason,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case of incorrect payment details, set the route. This can be used
|
||||||
|
// for probing and to extract a fee estimate from the route.
|
||||||
|
if reason == channeldb.FailureReasonIncorrectPaymentDetails {
|
||||||
|
result.Route = rt
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fail transitions a payment into the Failed state, and records the reason the
|
// Fail transitions a payment into the Failed state, and records the reason the
|
||||||
@@ -146,14 +156,14 @@ func createFailedResult(reason channeldb.FailureReason) *PaymentResult {
|
|||||||
func (p *controlTower) Fail(paymentHash lntypes.Hash,
|
func (p *controlTower) Fail(paymentHash lntypes.Hash,
|
||||||
reason channeldb.FailureReason) error {
|
reason channeldb.FailureReason) error {
|
||||||
|
|
||||||
err := p.db.Fail(paymentHash, reason)
|
route, err := p.db.Fail(paymentHash, reason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify subscribers of fail event.
|
// Notify subscribers of fail event.
|
||||||
p.notifyFinalEvent(
|
p.notifyFinalEvent(
|
||||||
paymentHash, createFailedResult(reason),
|
paymentHash, createFailedResult(route, reason),
|
||||||
)
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -211,7 +221,13 @@ func (p *controlTower) SubscribePayment(paymentHash lntypes.Hash) (
|
|||||||
// subscriber, because we can send the result on the channel
|
// subscriber, because we can send the result on the channel
|
||||||
// immediately.
|
// immediately.
|
||||||
case channeldb.StatusFailed:
|
case channeldb.StatusFailed:
|
||||||
event = *createFailedResult(*payment.Failure)
|
var route *route.Route
|
||||||
|
if payment.Attempt != nil {
|
||||||
|
route = &payment.Attempt.Route
|
||||||
|
}
|
||||||
|
event = *createFailedResult(
|
||||||
|
route, *payment.Failure,
|
||||||
|
)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false, nil, errors.New("unknown payment status")
|
return false, nil, errors.New("unknown payment status")
|
||||||
|
|||||||
Reference in new issue
Block a user