@@ -168,15 +168,15 @@ class PaymentLifecycle(nodeParams: NodeParams, cfg: SendPaymentConfig, router: A
168
168
169
169
private def handleRemoteFail (d : WaitingForComplete , fail : UpdateFailHtlc ) = {
170
170
import d ._
171
- ((Sphinx .FailurePacket .decrypt(fail.reason, sharedSecrets) match {
172
- case success@ Success (e) =>
171
+ val result = Sphinx .FatErrorPacket .decrypt(fail.reason, sharedSecrets)
172
+ result match {
173
+ case Right (e) =>
173
174
Metrics .PaymentError .withTag(Tags .Failure , Tags .FailureType (RemoteFailure (d.c.finalPayload.amount, Nil , e))).increment()
174
- success
175
- case failure@ Failure (_) =>
176
- Metrics .PaymentError .withTag(Tags .Failure , Tags .FailureType (UnreadableRemoteFailure (d.c.finalPayload.amount, Nil ))).increment()
177
- failure
178
- }) match {
179
- case res@ Success (Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) =>
175
+ case Left (e) =>
176
+ Metrics .PaymentError .withTag(Tags .Failure , Tags .FailureType (UnreadableRemoteFailure (d.c.finalPayload.amount, Nil , e))).increment()
177
+ }
178
+ result match {
179
+ case Right (Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) =>
180
180
// We have discovered some liquidity information with this payment: we update the router accordingly.
181
181
val stoppedRoute = d.route.stopAt(nodeId)
182
182
if (stoppedRoute.hops.length > 1 ) {
@@ -191,38 +191,43 @@ class PaymentLifecycle(nodeParams: NodeParams, cfg: SendPaymentConfig, router: A
191
191
}
192
192
case _ => // other errors should not be used for liquidity issues
193
193
}
194
- res
195
- case res => res
196
- }) match {
197
- case Success (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) if nodeId == c.targetNodeId =>
194
+ case Left (Sphinx .InvalidFatErrorPacket (reachedNodes, _)) =>
195
+ if (reachedNodes.length > 1 ) {
196
+ val lastReachedNode = reachedNodes.last._1
197
+ val stoppedRoute = d.route.stopAt(lastReachedNode)
198
+ router ! Router .RouteCouldRelay (stoppedRoute)
199
+ }
200
+ }
201
+ result match {
202
+ case Right (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) if nodeId == c.targetNodeId =>
198
203
// if destination node returns an error, we fail the payment immediately
199
204
log.warning(s " received an error message from target nodeId= $nodeId, failing the payment (failure= $failureMessage) " )
200
205
myStop(c, Left (PaymentFailed (id, paymentHash, failures :+ RemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route), e))))
201
206
case res if failures.size + 1 >= c.maxAttempts =>
202
207
// otherwise we never try more than maxAttempts, no matter the kind of error returned
203
208
val failure = res match {
204
- case Success (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) =>
209
+ case Right (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) =>
205
210
log.info(s " received an error message from nodeId= $nodeId (failure= $failureMessage) " )
206
211
failureMessage match {
207
212
case failureMessage : Update => handleUpdate(nodeId, failureMessage, d)
208
213
case _ =>
209
214
}
210
215
RemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route), e)
211
- case Failure (t ) =>
212
- log.warning(s " cannot parse returned error ${fail.reason.toHex} with sharedSecrets= $sharedSecrets : ${t.getMessage} " )
213
- UnreadableRemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route))
216
+ case Left (e ) =>
217
+ log.warning(s " cannot parse returned error: $e " )
218
+ UnreadableRemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route), e )
214
219
}
215
220
log.warning(s " too many failed attempts, failing the payment " )
216
221
myStop(c, Left (PaymentFailed (id, paymentHash, failures :+ failure)))
217
- case Failure (t ) =>
218
- log.warning(s " cannot parse returned error: ${t.getMessage} , route= ${route.printNodes()}" )
219
- val failure = UnreadableRemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route))
222
+ case Left (e ) =>
223
+ log.warning(s " cannot parse returned error: $e , route= ${route.printNodes()}" )
224
+ val failure = UnreadableRemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route), e )
220
225
retry(failure, d)
221
- case Success (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage : Node )) =>
226
+ case Right (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage : Node )) =>
222
227
log.info(s " received 'Node' type error message from nodeId= $nodeId, trying to route around it (failure= $failureMessage) " )
223
228
val failure = RemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route), e)
224
229
retry(failure, d)
225
- case Success (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage : Update )) =>
230
+ case Right (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage : Update )) =>
226
231
log.info(s " received 'Update' type error message from nodeId= $nodeId, retrying payment (failure= $failureMessage) " )
227
232
val failure = RemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route), e)
228
233
if (Announcements .checkSig(failureMessage.update, nodeId)) {
@@ -249,7 +254,7 @@ class PaymentLifecycle(nodeParams: NodeParams, cfg: SendPaymentConfig, router: A
249
254
goto(WAITING_FOR_ROUTE ) using WaitingForRoute (c, failures :+ failure, ignore + nodeId)
250
255
}
251
256
}
252
- case Success (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) =>
257
+ case Right (e@ Sphinx .DecryptedFailurePacket (nodeId, failureMessage)) =>
253
258
log.info(s " received an error message from nodeId= $nodeId, trying to use a different channel (failure= $failureMessage) " )
254
259
val failure = RemoteFailure (d.c.finalPayload.amount, cfg.fullRoute(route), e)
255
260
retry(failure, d)
0 commit comments