routing/router: move sending and receiving payment result into loop

This commit is contained in:
Johan T. Halseth
2019-05-23 20:05:29 +02:00
parent 59c2557cc9
commit ae7bf2cb7b

View File

@@ -1513,6 +1513,7 @@ type LightningPayment struct {
// when we should should abandon the payment attempt after consecutive // when we should should abandon the payment attempt after consecutive
// payment failure. This prevents us from attempting to send a payment // payment failure. This prevents us from attempting to send a payment
// indefinitely. // indefinitely.
// TODO(halseth): make wallclock time to allow resume after startup.
PayAttemptTimeout time.Duration PayAttemptTimeout time.Duration
// RouteHints represents the different routing hints that can be used to // RouteHints represents the different routing hints that can be used to
@@ -1617,6 +1618,8 @@ func (r *ChannelRouter) sendPayment(payment *LightningPayment,
timeoutChan := time.After(payAttemptTimeout) timeoutChan := time.After(payAttemptTimeout)
paymentHash := payment.PaymentHash
// We'll continue until either our payment succeeds, or we encounter a // We'll continue until either our payment succeeds, or we encounter a
// critical error during path finding. // critical error during path finding.
var lastError error var lastError error
@@ -1657,26 +1660,6 @@ func (r *ChannelRouter) sendPayment(payment *LightningPayment,
return [32]byte{}, nil, err return [32]byte{}, nil, err
} }
// Send payment attempt. It will return a final boolean
// indicating if more attempts are needed.
preimage, final, err := r.sendPaymentAttempt(
paySession, route, payment.PaymentHash,
)
if final {
return preimage, route, err
}
lastError = err
}
}
// sendPaymentAttempt tries to send the payment via the specified route. If
// successful, it returns the obtained preimage. If an error occurs, the last
// bool parameter indicates whether this is a final outcome or more attempts
// should be made.
func (r *ChannelRouter) sendPaymentAttempt(paySession *paymentSession,
route *route.Route, paymentHash [32]byte) ([32]byte, bool, error) {
log.Tracef("Attempting to send payment %x, using route: %v", log.Tracef("Attempting to send payment %x, using route: %v",
paymentHash, newLogClosure(func() string { paymentHash, newLogClosure(func() string {
return spew.Sdump(route) return spew.Sdump(route)
@@ -1686,8 +1669,9 @@ func (r *ChannelRouter) sendPaymentAttempt(paySession *paymentSession,
// Generate a new key to be used for this attempt. // Generate a new key to be used for this attempt.
sessionKey, err := generateNewSessionKey() sessionKey, err := generateNewSessionKey()
if err != nil { if err != nil {
return [32]byte{}, true, err return [32]byte{}, nil, err
} }
// Generate the raw encoded sphinx packet to be included along // Generate the raw encoded sphinx packet to be included along
// with the htlcAdd message that we send directly to the // with the htlcAdd message that we send directly to the
// switch. // switch.
@@ -1695,7 +1679,7 @@ func (r *ChannelRouter) sendPaymentAttempt(paySession *paymentSession,
route, paymentHash[:], sessionKey, route, paymentHash[:], sessionKey,
) )
if err != nil { if err != nil {
return [32]byte{}, true, err return [32]byte{}, nil, err
} }
// Craft an HTLC packet to send to the layer 2 switch. The // Craft an HTLC packet to send to the layer 2 switch. The
@@ -1719,23 +1703,28 @@ func (r *ChannelRouter) sendPaymentAttempt(paySession *paymentSession,
// this HTLC. // this HTLC.
paymentID, err := r.cfg.NextPaymentID() paymentID, err := r.cfg.NextPaymentID()
if err != nil { if err != nil {
return [32]byte{}, true, err return [32]byte{}, nil, err
} }
err = r.cfg.Payer.SendHTLC( err = r.cfg.Payer.SendHTLC(
firstHop, paymentID, htlcAdd, firstHop, paymentID, htlcAdd,
) )
if err != nil { if err != nil {
log.Errorf("Failed sending attempt %d for payment %x to "+ log.Errorf("Failed sending attempt %d for payment "+
"switch: %v", paymentID, paymentHash, err) "%x to switch: %v", paymentID, paymentHash, err)
// We must inspect the error to know whether it was critical or // We must inspect the error to know whether it was
// not, to decide whether we should continue trying. // critical or not, to decide whether we should
// continue trying.
finalOutcome := r.processSendError( finalOutcome := r.processSendError(
paySession, route, err, paySession, route, err,
) )
if finalOutcome {
return [32]byte{}, nil, err
}
return [32]byte{}, finalOutcome, err lastError = err
continue
} }
// Using the created circuit, initialize the error decrypter so we can // Using the created circuit, initialize the error decrypter so we can
@@ -1753,7 +1742,7 @@ func (r *ChannelRouter) sendPaymentAttempt(paySession *paymentSession,
if err != nil { if err != nil {
log.Errorf("Failed getting result for paymentID %d "+ log.Errorf("Failed getting result for paymentID %d "+
"from switch: %v", paymentID, err) "from switch: %v", paymentID, err)
return [32]byte{}, true, err return [32]byte{}, nil, err
} }
var ( var (
@@ -1763,11 +1752,11 @@ func (r *ChannelRouter) sendPaymentAttempt(paySession *paymentSession,
select { select {
case result, ok = <-resultChan: case result, ok = <-resultChan:
if !ok { if !ok {
return [32]byte{}, true, htlcswitch.ErrSwitchExiting return [32]byte{}, nil, htlcswitch.ErrSwitchExiting
} }
case <-r.quit: case <-r.quit:
return [32]byte{}, true, ErrRouterShuttingDown return [32]byte{}, nil, ErrRouterShuttingDown
} }
if result.Error != nil { if result.Error != nil {
@@ -1778,10 +1767,17 @@ func (r *ChannelRouter) sendPaymentAttempt(paySession *paymentSession,
paySession, route, result.Error, paySession, route, result.Error,
) )
return [32]byte{}, finalOutcome, result.Error if finalOutcome {
return [32]byte{}, nil, result.Error
}
lastError = result.Error
continue
}
return result.Preimage, route, nil
} }
return result.Preimage, true, nil
} }
// processSendError analyzes the error for the payment attempt received from the // processSendError analyzes the error for the payment attempt received from the