routing/payment_lifecycle+channeldb: collect existing outcome first
To move towards how we will handle existing attempt in case of MPP (collecting their outcome will be done in separate goroutines separate from the payment loop), we move to collect their outcome first. To easily fetch HTLCs that are still not resolved, we add the utility method InFlightHTLCs to channeldb.MPPayment.
This commit is contained in:
parent
49efbefb43
commit
7b5c10814b
@ -131,6 +131,21 @@ type MPPayment struct {
|
||||
Status PaymentStatus
|
||||
}
|
||||
|
||||
// InFlightHTLCs returns the HTLCs that are still in-flight, meaning they have
|
||||
// not been settled or failed.
|
||||
func (m *MPPayment) InFlightHTLCs() []HTLCAttempt {
|
||||
var inflights []HTLCAttempt
|
||||
for _, h := range m.HTLCs {
|
||||
if h.Settle != nil || h.Failure != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
inflights = append(inflights, h)
|
||||
}
|
||||
|
||||
return inflights
|
||||
}
|
||||
|
||||
// serializeHTLCSettleInfo serializes the details of a settled htlc.
|
||||
func serializeHTLCSettleInfo(w io.Writer, s *HTLCSettleInfo) error {
|
||||
if _, err := w.Write(s.Preimage[:]); err != nil {
|
||||
|
@ -32,6 +32,23 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) {
|
||||
paymentHash: p.paymentHash,
|
||||
}
|
||||
|
||||
// If we have an existing attempt, we'll start by collecting its result.
|
||||
payment, err := p.router.cfg.Control.FetchPayment(
|
||||
p.paymentHash,
|
||||
)
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, err
|
||||
}
|
||||
|
||||
for _, a := range payment.InFlightHTLCs() {
|
||||
a := a
|
||||
|
||||
_, err := shardHandler.collectResult(&a.HTLCAttemptInfo)
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// We'll continue until either our payment succeeds, or we encounter a
|
||||
// critical error during path finding.
|
||||
for {
|
||||
@ -160,32 +177,34 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) {
|
||||
// make a new attempt.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Whether this was an existing attempt or one we just sent,
|
||||
// we'll now collect its result. We ignore the result for now
|
||||
// if it is a success, as we will look it up in the control
|
||||
// tower on the next loop iteration.
|
||||
// We'll collect the result of the shard just sent. We
|
||||
// ignore the result for now if it is a success, as we
|
||||
// will look it up in the control tower on the next
|
||||
// loop iteration.
|
||||
result, err := shardHandler.collectResult(attempt)
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, err
|
||||
}
|
||||
|
||||
if result.err != nil {
|
||||
// We must inspect the error to know whether it was
|
||||
// critical or not, to decide whether we should
|
||||
// continue trying.
|
||||
err = shardHandler.handleSendError(attempt, result.err)
|
||||
// We must inspect the error to know whether it
|
||||
// was critical or not, to decide whether we
|
||||
// should continue trying.
|
||||
err := shardHandler.handleSendError(
|
||||
attempt, result.err,
|
||||
)
|
||||
if err != nil {
|
||||
return [32]byte{}, nil, err
|
||||
}
|
||||
|
||||
// Error was handled successfully, continue to make a
|
||||
// new attempt.
|
||||
// Error was handled successfully, continue to
|
||||
// make a new attempt.
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shardHandler holds what is necessary to send and collect the result of
|
||||
// shards.
|
||||
|
Loading…
Reference in New Issue
Block a user