Skip to content

Commit dd1d57d

Browse files
ziggie1984guggero
authored andcommitted
routing: make sure attempts are always resolved after a timeout
We check the context of the payment lifecycle at the beginning of the `resumepayment` loop. This will make sure we have always the latest state of the payment before deciding on the next steps in the function `decideNextStep`.
1 parent 985d29f commit dd1d57d

File tree

2 files changed

+21
-25
lines changed

2 files changed

+21
-25
lines changed

routing/payment_lifecycle.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,19 @@ func (p *paymentLifecycle) resumePayment(ctx context.Context) ([32]byte,
226226
// critical error during path finding.
227227
lifecycle:
228228
for {
229+
// Before we attempt any new shard, we'll check to see if we've
230+
// gone past the payment attempt timeout or if the context was
231+
// canceled. If the context is done, the payment is marked as
232+
// failed and we reload the latest payment state to reflect
233+
// this.
234+
//
235+
// NOTE: This can be called several times if there are more
236+
// attempts to be resolved after the timeout or context is
237+
// cancelled.
238+
if err := p.checkContext(ctx); err != nil {
239+
return exitWithErr(err)
240+
}
241+
229242
// We update the payment state on every iteration.
230243
currentPayment, ps, err := p.reloadPayment()
231244
if err != nil {
@@ -241,19 +254,11 @@ lifecycle:
241254

242255
// We now proceed our lifecycle with the following tasks in
243256
// order,
244-
// 1. check context.
245-
// 2. request route.
246-
// 3. create HTLC attempt.
247-
// 4. send HTLC attempt.
248-
// 5. collect HTLC attempt result.
257+
// 1. request route.
258+
// 2. create HTLC attempt.
259+
// 3. send HTLC attempt.
260+
// 4. collect HTLC attempt result.
249261
//
250-
// Before we attempt any new shard, we'll check to see if we've
251-
// gone past the payment attempt timeout, or if the context was
252-
// cancelled, or the router is exiting. In any of these cases,
253-
// we'll stop this payment attempt short.
254-
if err := p.checkContext(ctx); err != nil {
255-
return exitWithErr(err)
256-
}
257262

258263
// Now decide the next step of the current lifecycle.
259264
step, err := p.decideNextStep(payment)

routing/payment_lifecycle_test.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -868,25 +868,16 @@ func TestResumePaymentFailOnTimeoutErr(t *testing.T) {
868868
// Create a test paymentLifecycle with the initial two calls mocked.
869869
p, m := setupTestPaymentLifecycle(t)
870870

871-
paymentAmt := lnwire.MilliSatoshi(10000)
872-
873-
// We now enter the payment lifecycle loop.
874-
//
875-
// 1. calls `FetchPayment` and return the payment.
876-
m.control.On("FetchPayment", p.identifier).Return(m.payment, nil).Once()
877-
878-
// 2. calls `GetState` and return the state.
879-
ps := &channeldb.MPPaymentState{
880-
RemainingAmt: paymentAmt,
881-
}
882-
m.payment.On("GetState").Return(ps).Once()
871+
// We now enter the payment lifecycle loop, we will check the router
872+
// quit channel in the beginning and quit immediately without reloading
873+
// the payment.
883874

884875
// NOTE: GetStatus is only used to populate the logs which is
885876
// not critical so we loosen the checks on how many times it's
886877
// been called.
887878
m.payment.On("GetStatus").Return(channeldb.StatusInFlight)
888879

889-
// 3. quit the router to return an error.
880+
// Quit the router to return an error.
890881
close(p.router.quit)
891882

892883
// Send the payment and assert it failed when router is shutting down.

0 commit comments

Comments
 (0)