1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-02-24 06:47:46 +01:00

PaymentLifecycle should tell the router to ignore route prefix (#1217)

When paying a multi-part payment, we tell the PaymentLifecycle to use a route prefix that contains the first hop (for example a -> b via channel 1).

We need to also tell the router to ignore the nodes that are in the route prefix, otherwise when retrying it may try some completely dumb routes that have no chance of succeeding.
This commit is contained in:
Bastien Teinturier 2019-11-18 15:25:38 +01:00 committed by GitHub
parent f45dc1c0fd
commit c76cc5bfe6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 8 additions and 6 deletions

View file

@ -59,11 +59,13 @@ class PaymentLifecycle(nodeParams: NodeParams, cfg: SendPaymentConfig, router: A
case Event(c: SendPayment, WaitingForRequest) =>
log.debug("sending {} to {}{}", c.finalPayload.amount, c.targetNodeId, c.routePrefix.mkString(" with route prefix ", "->", ""))
// We don't want the router to try cycling back to nodes that are at the beginning of the route.
val ignoredNodes = c.routePrefix.map(_.nodeId).toSet
if (c.routePrefix.lastOption.exists(_.nextNodeId == c.targetNodeId)) {
// If the sender already provided a route to the target, no need to involve the router.
self ! RouteResponse(Nil, Set.empty, Set.empty, allowEmpty = true)
self ! RouteResponse(Nil, ignoredNodes, Set.empty, allowEmpty = true)
} else {
router ! RouteRequest(c.getRouteRequestStart(nodeParams), c.targetNodeId, c.finalPayload.amount, c.assistedRoutes, routeParams = c.routeParams)
router ! RouteRequest(c.getRouteRequestStart(nodeParams), c.targetNodeId, c.finalPayload.amount, c.assistedRoutes, routeParams = c.routeParams, ignoreNodes = ignoredNodes)
}
if (cfg.storeInDb) {
paymentsDb.addOutgoingPayment(OutgoingPayment(id, cfg.parentId, cfg.externalId, cfg.paymentHash, c.finalPayload.amount, cfg.targetNodeId, Platform.currentTime, cfg.paymentRequest, OutgoingPaymentStatus.Pending))

View file

@ -120,7 +120,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec {
val request = SendPayment(defaultPaymentHash, d, FinalLegacyPayload(defaultAmountMsat, defaultExpiry), 3, routePrefix = Seq(ChannelHop(a, b, channelUpdate_ab), ChannelHop(b, c, channelUpdate_bc)))
sender.send(paymentFSM, request)
routerForwarder.expectMsg(RouteRequest(c, d, defaultAmountMsat))
routerForwarder.expectMsg(RouteRequest(c, d, defaultAmountMsat, ignoreNodes = Set(a, b)))
val Transition(_, WAITING_FOR_REQUEST, WAITING_FOR_ROUTE) = monitor.expectMsgClass(classOf[Transition[_]])
awaitCond(nodeParams.db.payments.getOutgoingPayment(id).exists(_.status == OutgoingPaymentStatus.Pending))
@ -146,15 +146,15 @@ class PaymentLifecycleSpec extends BaseRouterSpec {
val request = SendPayment(defaultPaymentHash, d, FinalLegacyPayload(defaultAmountMsat, defaultExpiry), 3, routePrefix = Seq(ChannelHop(a, b, channelUpdate_ab), ChannelHop(b, c, channelUpdate_bc)))
sender.send(paymentFSM, request)
routerForwarder.expectMsg(RouteRequest(c, d, defaultAmountMsat))
routerForwarder.expectMsg(RouteRequest(c, d, defaultAmountMsat, ignoreNodes = Set(a, b)))
val Transition(_, WAITING_FOR_REQUEST, WAITING_FOR_ROUTE) = monitor.expectMsgClass(classOf[Transition[_]])
awaitCond(nodeParams.db.payments.getOutgoingPayment(id).exists(_.status == OutgoingPaymentStatus.Pending))
routerForwarder.send(paymentFSM, RouteResponse(Seq(ChannelHop(c, d, channelUpdate_cd)), Set.empty, Set.empty))
routerForwarder.send(paymentFSM, RouteResponse(Seq(ChannelHop(c, d, channelUpdate_cd)), Set(a, b), Set.empty))
val Transition(_, WAITING_FOR_ROUTE, WAITING_FOR_PAYMENT_COMPLETE) = monitor.expectMsgClass(classOf[Transition[_]])
sender.send(paymentFSM, UpdateFailMalformedHtlc(randomBytes32, 0, randomBytes32, 0))
routerForwarder.expectMsg(RouteRequest(c, d, defaultAmountMsat, ignoreChannels = Set(ChannelDesc(channelUpdate_ab.shortChannelId, a, b))))
routerForwarder.expectMsg(RouteRequest(c, d, defaultAmountMsat, ignoreNodes = Set(a, b), ignoreChannels = Set(ChannelDesc(channelUpdate_ab.shortChannelId, a, b))))
val Transition(_, WAITING_FOR_PAYMENT_COMPLETE, WAITING_FOR_ROUTE) = monitor.expectMsgClass(classOf[Transition[_]])
assert(nodeParams.db.payments.getOutgoingPayment(id).exists(_.status == OutgoingPaymentStatus.Pending))
}