routing/payment_lifecycle: move attempt DB checkpointing into payment

loop

To prepare for multiple in flight payment attempts, we move
checkpointing the payment attempt out of createNewPaymentAttempt and
into the main payment lifecycle loop.

We'll attempt to move all calls to the DB via the ControlTower into this
loop, so we can more easily handle them in sequence.
This commit is contained in:
Johan T. Halseth 2020-04-01 00:13:23 +02:00
parent e61fcda6a9
commit 3620721391
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

@ -114,12 +114,24 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) {
// Using the route received from the payment session, // Using the route received from the payment session,
// create a new shard to send. // create a new shard to send.
firstHop, htlcAdd, err := p.createNewPaymentAttempt( firstHop, htlcAdd, attempt, err := p.createNewPaymentAttempt(
rt, rt,
) )
if err != nil { if err != nil {
return [32]byte{}, nil, err return [32]byte{}, nil, err
} }
p.attempt = attempt
// Before sending this HTLC to the switch, we checkpoint the
// fresh paymentID and route to the DB. This lets us know on
// startup the ID of the payment that we attempted to send,
// such that we can query the Switch for its whereabouts. The
// route is needed to handle the result when it eventually
// comes back.
err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, attempt)
if err != nil {
return [32]byte{}, nil, err
}
// Now that the attempt is created and checkpointed to // Now that the attempt is created and checkpointed to
// the DB, we send it. // the DB, we send it.
@ -297,15 +309,15 @@ func errorToPaymentFailure(err error) channeldb.FailureReason {
return channeldb.FailureReasonError return channeldb.FailureReasonError
} }
// createNewPaymentAttempt creates and stores a new payment attempt to the // createNewPaymentAttempt creates a new payment attempt from the given route.
// database. func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (
func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (lnwire.ShortChannelID, lnwire.ShortChannelID, *lnwire.UpdateAddHTLC,
*lnwire.UpdateAddHTLC, error) { *channeldb.HTLCAttemptInfo, error) {
// 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 lnwire.ShortChannelID{}, nil, err return lnwire.ShortChannelID{}, nil, nil, err
} }
// Generate the raw encoded sphinx packet to be included along // Generate the raw encoded sphinx packet to be included along
@ -327,13 +339,13 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (lnwire.Shor
p.paymentHash, channeldb.FailureReasonError, p.paymentHash, channeldb.FailureReasonError,
) )
if controlErr != nil { if controlErr != nil {
return lnwire.ShortChannelID{}, nil, controlErr return lnwire.ShortChannelID{}, nil, nil, controlErr
} }
} }
// In any case, don't continue if there is an error. // In any case, don't continue if there is an error.
if err != nil { if err != nil {
return lnwire.ShortChannelID{}, nil, err return lnwire.ShortChannelID{}, nil, nil, err
} }
// Update our cached circuit with the newly generated // Update our cached circuit with the newly generated
@ -361,30 +373,19 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (lnwire.Shor
// this HTLC. // this HTLC.
attemptID, err := p.router.cfg.NextPaymentID() attemptID, err := p.router.cfg.NextPaymentID()
if err != nil { if err != nil {
return lnwire.ShortChannelID{}, nil, err return lnwire.ShortChannelID{}, nil, nil, err
} }
// We now have all the information needed to populate // We now have all the information needed to populate
// the current attempt information. // the current attempt information.
p.attempt = &channeldb.HTLCAttemptInfo{ attempt := &channeldb.HTLCAttemptInfo{
AttemptID: attemptID, AttemptID: attemptID,
AttemptTime: p.router.cfg.Clock.Now(), AttemptTime: p.router.cfg.Clock.Now(),
SessionKey: sessionKey, SessionKey: sessionKey,
Route: *rt, Route: *rt,
} }
// Before sending this HTLC to the switch, we checkpoint the return firstHop, htlcAdd, attempt, nil
// fresh attemptID and route to the DB. This lets us know on
// startup the ID of the payment that we attempted to send,
// such that we can query the Switch for its whereabouts. The
// route is needed to handle the result when it eventually
// comes back.
err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, p.attempt)
if err != nil {
return lnwire.ShortChannelID{}, nil, err
}
return firstHop, htlcAdd, nil
} }
// sendPaymentAttempt attempts to send the current attempt to the switch. // sendPaymentAttempt attempts to send the current attempt to the switch.