From 3323800e02fe378144876b53a2e02ad3180cd524 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 23 May 2019 20:05:29 +0200 Subject: [PATCH] routing/router: resume payment state machine at startup On startup the router will fetch the in-flight payments from the control tower, and resume their execution. --- routing/missioncontrol.go | 13 +++++++++++++ routing/router.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index 0a8a48a1..0e45bb49 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -242,6 +242,19 @@ func (m *missionControl) NewPaymentSessionForRoute(preBuiltRoute *route.Route) * } } +// NewPaymentSessionEmpty creates a new paymentSession instance that is empty, +// and will be exhausted immediately. Used for failure reporting to +// missioncontrol for resumed payment we don't want to make more attempts for. +func (m *missionControl) NewPaymentSessionEmpty() *paymentSession { + return &paymentSession{ + pruneViewSnapshot: m.GraphPruneView(), + errFailedPolicyChans: make(map[EdgeLocator]struct{}), + mc: m, + preBuiltRoute: &route.Route{}, + preBuiltRouteTried: true, + } +} + // generateBandwidthHints is a helper function that's utilized the main // findPath function in order to obtain hints from the lower layer w.r.t to the // available bandwidth of edges on the network. Currently, we'll only obtain diff --git a/routing/router.go b/routing/router.go index f2d9e9ba..3d9918d7 100644 --- a/routing/router.go +++ b/routing/router.go @@ -492,6 +492,40 @@ func (r *ChannelRouter) Start() error { } } + // If any payments are still in flight, we resume, to make sure their + // results are properly handled. + payments, err := r.cfg.Control.FetchInFlightPayments() + if err != nil { + return err + } + + for _, payment := range payments { + log.Infof("Resuming payment with hash %v", payment.Info.PaymentHash) + r.wg.Add(1) + go func(payment *channeldb.InFlightPayment) { + defer r.wg.Done() + + // We create a dummy, empty payment session such that + // we won't make another payment attempt when the + // result for the in-flight attempt is received. + paySession := r.missionControl.NewPaymentSessionEmpty() + + lPayment := &LightningPayment{ + PaymentHash: payment.Info.PaymentHash, + } + + _, _, err = r.sendPayment(payment.Attempt, lPayment, paySession) + if err != nil { + log.Errorf("Resuming payment with hash %v "+ + "failed: %v.", payment.Info.PaymentHash, err) + return + } + + log.Infof("Resumed payment with hash %v completed.", + payment.Info.PaymentHash) + }(payment) + } + r.wg.Add(1) go r.networkHandler()