routing: return full htlc attempt from router

This commit is contained in:
Joost Jager 2020-05-06 15:36:51 +02:00
parent cc37485432
commit 674c199047
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
4 changed files with 44 additions and 29 deletions

View File

@ -318,25 +318,30 @@ func (s *Server) SendToRoute(ctx context.Context,
return nil, err
}
preimage, err := s.cfg.Router.SendToRoute(hash, route)
// Pass route to the router. This call returns the full htlc attempt
// information as it is stored in the database. It is possible that both
// the attempt return value and err are non-nil. This can happen when
// the attempt was already initiated before the error happened. In that
// case, we give precedence to the attempt information as stored in the
// db.
attempt, err := s.cfg.Router.SendToRoute(hash, route)
if attempt != nil {
rpcAttempt, err := s.cfg.RouterBackend.MarshalHTLCAttempt(
*attempt,
)
if err != nil {
return nil, err
}
// In the success case, return the preimage.
if err == nil {
return &SendToRouteResponse{
Preimage: preimage[:],
}, nil
resp := &SendToRouteResponse{
Preimage: rpcAttempt.Preimage,
Failure: rpcAttempt.Failure,
}
return resp, nil
}
// In the failure case, marshall the failure message to the rpc format
// before returning it to the caller.
rpcErr, err := marshallError(err)
if err != nil {
return nil, err
}
return &SendToRouteResponse{
Failure: rpcErr,
}, nil
return nil, err
}
// ResetMissionControl clears all mission control state and starts with a clean

View File

@ -1741,10 +1741,12 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) (
}
// SendToRoute attempts to send a payment with the given hash through the
// provided route. This function is blocking and will return the obtained
// preimage if the payment is successful or the full error in case of a failure.
// provided route. This function is blocking and will return the attempt
// information as it is stored in the database. For a successful htlc, this
// information will contain the preimage. If an error occurs after the attempt
// was initiated, both return values will be non-nil.
func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
lntypes.Preimage, error) {
*channeldb.HTLCAttempt, error) {
// Calculate amount paid to receiver.
amt := rt.ReceiverAmt()
@ -1774,7 +1776,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
// Any other error is not tolerated.
case err != nil:
return [32]byte{}, err
return nil, err
}
log.Tracef("Dispatching SendToRoute for hash %v: %v",
@ -1804,34 +1806,37 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
hash, channeldb.FailureReasonError,
)
if controlErr != nil {
return [32]byte{}, controlErr
return nil, controlErr
}
}
// In any case, don't continue if there is an error.
if err != nil {
return lntypes.Preimage{}, err
return nil, err
}
var htlcAttempt *channeldb.HTLCAttempt
switch {
// Failed to launch shard.
case outcome.err != nil:
shardError = outcome.err
htlcAttempt = outcome.attempt
// Shard successfully launched, wait for the result to be available.
default:
result, err := sh.collectResult(attempt)
if err != nil {
return lntypes.Preimage{}, err
return nil, err
}
// We got a successful result.
if result.err == nil {
return result.attempt.Settle.Preimage, nil
return result.attempt, nil
}
// The shard failed, break switch to handle it.
shardError = result.err
htlcAttempt = result.attempt
}
// Since for SendToRoute we won't retry in case the shard fails, we'll
@ -1848,10 +1853,10 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
err = r.cfg.Control.Fail(hash, *reason)
if err != nil {
return lntypes.Preimage{}, err
return nil, err
}
return lntypes.Preimage{}, shardError
return htlcAttempt, shardError
}
// sendPayment attempts to send a payment to the passed payment hash. This

View File

@ -2809,13 +2809,13 @@ func TestSendToRouteMultiShardSend(t *testing.T) {
for i := 0; i < numShards; i++ {
go func() {
preimg, err := ctx.router.SendToRoute(payment, rt)
attempt, err := ctx.router.SendToRoute(payment, rt)
if err != nil {
errChan <- err
return
}
successes <- preimg
successes <- attempt.Settle.Preimage
}()
}

View File

@ -3978,10 +3978,15 @@ func (r *rpcServer) dispatchPaymentIntent(
payment,
)
} else {
preImage, routerErr = r.server.chanRouter.SendToRoute(
var attempt *channeldb.HTLCAttempt
attempt, routerErr = r.server.chanRouter.SendToRoute(
payIntent.rHash, payIntent.route,
)
if routerErr == nil {
preImage = attempt.Settle.Preimage
}
route = payIntent.route
}