routing/router: enable MPP sends for SendToRoute

This commit enables MPP sends for SendToRoute, by allowing launching
another payment attempt if the hash is already registered with the
ControlTower.

We also set the total payment amount of of the payment from mpp record,
to indicate that the shard value might be different from the total
payment value.

We only mark non-MPP payments as failed in the database after
encountering a failure, since we might want to try more shards for MPP.
For now this means that MPP sendToRoute payments will be failed
only after a restart has happened.
This commit is contained in:
Johan T. Halseth 2020-04-01 00:13:27 +02:00
parent 431372c0cf
commit 36a80b4d51
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

@ -1732,6 +1732,14 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
// Calculate amount paid to receiver.
amt := rt.ReceiverAmt()
// If this is meant as a MP payment shard, we set the amount
// for the creating info to the total amount of the payment.
finalHop := rt.Hops[len(rt.Hops)-1]
mpp := finalHop.MPP
if mpp != nil {
amt = mpp.TotalMsat()
}
// Record this payment hash with the ControlTower, ensuring it is not
// already in-flight.
info := &channeldb.PaymentCreationInfo{
@ -1742,7 +1750,13 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
}
err := r.cfg.Control.InitPayment(hash, info)
if err != nil {
switch {
// If this is an MPP attempt and the hash is already registered with
// the database, we can go on to launch the shard.
case err == channeldb.ErrPaymentInFlight && mpp != nil:
// Any other error is not tolerated.
case err != nil:
return [32]byte{}, err
}