From c00a544db862b078e2a9eeb9fd7892433ea4e251 Mon Sep 17 00:00:00 2001 From: Jesse de Wit Date: Fri, 1 Dec 2023 16:26:05 +0100 Subject: [PATCH] use failure messages instead of failure codes --- cln/cln_interceptor.go | 32 ++++++---------------------- common/intercept_handler.go | 16 +++++++------- interceptor/intercept_handler.go | 36 ++++++++++++++++---------------- lnd/interceptor.go | 23 +++++--------------- lsps2/intercept_handler.go | 12 +++++------ lsps2/intercept_test.go | 24 ++++++++++----------- 6 files changed, 55 insertions(+), 88 deletions(-) diff --git a/cln/cln_interceptor.go b/cln/cln_interceptor.go index f58ad239..267222e8 100644 --- a/cln/cln_interceptor.go +++ b/cln/cln_interceptor.go @@ -161,7 +161,7 @@ func (i *ClnHtlcInterceptor) intercept() error { interceptorClient.Send(i.resumeWithOnion(request, interceptResult)) case common.INTERCEPT_FAIL_HTLC_WITH_CODE: interceptorClient.Send( - i.failWithCode(request, interceptResult.FailureCode), + i.failWithMessage(request, interceptResult.FailureMessage), ) case common.INTERCEPT_IGNORE: // Do nothing @@ -202,12 +202,12 @@ func (i *ClnHtlcInterceptor) resumeWithOnion(request *proto.HtlcAccepted, interc payload, err := hex.DecodeString(request.Onion.Payload) if err != nil { log.Printf("paymenthash: %s, resumeWithOnion: hex.DecodeString(%v) error: %v", request.Htlc.PaymentHash, request.Onion.Payload, err) - return i.failWithCode(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE) + return i.failWithMessage(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE) } newPayload, err := encodePayloadWithNextHop(payload, interceptResult.Scid, interceptResult.AmountMsat, interceptResult.FeeMsat) if err != nil { log.Printf("paymenthash: %s, encodePayloadWithNextHop error: %v", request.Htlc.PaymentHash, err) - return i.failWithCode(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE) + return i.failWithMessage(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE) } newPayloadStr := hex.EncodeToString(newPayload) @@ -234,14 +234,14 @@ func (i *ClnHtlcInterceptor) defaultResolution(request *proto.HtlcAccepted) *pro } } -func (i *ClnHtlcInterceptor) failWithCode(request *proto.HtlcAccepted, code common.InterceptFailureCode) *proto.HtlcResolution { - log.Printf("paymenthash: %s, failing htlc with code: '%x'", request.Htlc.PaymentHash, code) +func (i *ClnHtlcInterceptor) failWithMessage(request *proto.HtlcAccepted, message []byte) *proto.HtlcResolution { + log.Printf("paymenthash: %s, failing htlc with message '%x'", request.Htlc.PaymentHash, message) return &proto.HtlcResolution{ Correlationid: request.Correlationid, Outcome: &proto.HtlcResolution_Fail{ Fail: &proto.HtlcFail{ Failure: &proto.HtlcFail_FailureMessage{ - FailureMessage: i.mapFailureCode(code), + FailureMessage: hex.EncodeToString(message), }, }, }, @@ -305,23 +305,3 @@ func encodePayloadWithNextHop(payload []byte, scid lightning.ShortChannelID, amo } return newPayloadBuf.Bytes(), nil } - -func (i *ClnHtlcInterceptor) mapFailureCode(original common.InterceptFailureCode) string { - switch original { - case common.FAILURE_TEMPORARY_CHANNEL_FAILURE: - return "1007" - case common.FAILURE_AMOUNT_BELOW_MINIMUM: - return "100B" - case common.FAILURE_INCORRECT_CLTV_EXPIRY: - return "100D" - case common.FAILURE_TEMPORARY_NODE_FAILURE: - return "2002" - case common.FAILURE_UNKNOWN_NEXT_PEER: - return "400A" - case common.FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS: - return "400F" - default: - log.Printf("Unknown failure code %v, default to temporary channel failure.", original) - return "1007" // temporary channel failure - } -} diff --git a/common/intercept_handler.go b/common/intercept_handler.go index 96ea2a3f..9a2eea74 100644 --- a/common/intercept_handler.go +++ b/common/intercept_handler.go @@ -16,15 +16,15 @@ const ( INTERCEPT_IGNORE InterceptAction = 3 ) -type InterceptFailureCode uint16 +type InterceptFailureCode []byte var ( - FAILURE_TEMPORARY_CHANNEL_FAILURE InterceptFailureCode = 0x1007 - FAILURE_AMOUNT_BELOW_MINIMUM InterceptFailureCode = 0x100B - FAILURE_INCORRECT_CLTV_EXPIRY InterceptFailureCode = 0x100D - FAILURE_TEMPORARY_NODE_FAILURE InterceptFailureCode = 0x2002 - FAILURE_UNKNOWN_NEXT_PEER InterceptFailureCode = 0x400A - FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS InterceptFailureCode = 0x400F + FAILURE_TEMPORARY_CHANNEL_FAILURE InterceptFailureCode = []byte{0x10, 0x07} + FAILURE_AMOUNT_BELOW_MINIMUM InterceptFailureCode = []byte{0x10, 0x0B} + FAILURE_INCORRECT_CLTV_EXPIRY InterceptFailureCode = []byte{0x10, 0x0D} + FAILURE_TEMPORARY_NODE_FAILURE InterceptFailureCode = []byte{0x20, 0x02} + FAILURE_UNKNOWN_NEXT_PEER InterceptFailureCode = []byte{0x40, 0x0A} + FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS InterceptFailureCode = []byte{0x40, 0x0F} ) type InterceptRequest struct { @@ -49,7 +49,7 @@ func (r *InterceptRequest) HtlcId() string { type InterceptResult struct { Action InterceptAction - FailureCode InterceptFailureCode + FailureMessage []byte Destination []byte AmountMsat uint64 FeeMsat *uint64 diff --git a/interceptor/intercept_handler.go b/interceptor/intercept_handler.go index 06794aaa..0b03db82 100644 --- a/interceptor/intercept_handler.go +++ b/interceptor/intercept_handler.go @@ -58,8 +58,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if err != nil { log.Printf("paymentInfo(%x) error: %v", req.PaymentHash, err) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_NODE_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_NODE_FAILURE, }, nil } @@ -110,8 +110,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if err != nil { log.Printf("IsConnected(%x) error: %v", nextHop, err) return &common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, }, nil } @@ -132,8 +132,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if channelPoint == nil { log.Printf("paymentHash: %s, probe and channelPoint == nil", reqPaymentHashStr) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, }, nil } } @@ -178,8 +178,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if int64(req.IncomingExpiry)-int64(req.OutgoingExpiry) < int64(i.node.NodeConfig.TimeLockDelta) { log.Printf("paymentHash: %s, outgoingExpiry: %v, incomingExpiry: %v, i.node.NodeConfig.TimeLockDelta: %v", reqPaymentHashStr, req.OutgoingExpiry, req.IncomingExpiry, i.node.NodeConfig.TimeLockDelta) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, }, nil } @@ -187,8 +187,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if err != nil { log.Printf("paymentHash: %s, time.Parse(%s, %s) failed. Failing channel open: %v", reqPaymentHashStr, lsps0.TIME_FORMAT, params.ValidUntil, err) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, }, nil } @@ -198,8 +198,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if !i.openingService.IsCurrentChainFeeCheaper(token, params) { log.Printf("Intercepted expired payment registration. Failing payment. payment hash: %s, valid until: %s", reqPaymentHashStr, params.ValidUntil) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, }, nil } @@ -210,8 +210,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if err != nil { log.Printf("paymentHash: %s, openChannel(%x, %v) err: %v", reqPaymentHashStr, destination, incomingAmountMsat, err) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, }, nil } } @@ -237,8 +237,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes if err != nil { log.Printf("paymentHash: %s, insertChannel error: %v", reqPaymentHashStr, err) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, }, nil } @@ -270,8 +270,8 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes log.Printf("paymentHash: %s, Error: Channel failed to open... timed out. ", reqPaymentHashStr) return common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: common.FAILURE_TEMPORARY_CHANNEL_FAILURE, }, nil }) diff --git a/lnd/interceptor.go b/lnd/interceptor.go index c3eef64b..fae2083f 100644 --- a/lnd/interceptor.go +++ b/lnd/interceptor.go @@ -150,11 +150,12 @@ func (i *LndHtlcInterceptor) intercept() error { case common.INTERCEPT_RESUME_WITH_ONION: interceptorClient.Send(i.createOnionResponse(interceptResult, request)) case common.INTERCEPT_FAIL_HTLC_WITH_CODE: - log.Printf("paymenthash %x, failing htlc with code '%x'", request.PaymentHash, interceptResult.FailureCode) + log.Printf("paymenthash %x, failing htlc with message '%x'", request.PaymentHash, interceptResult.FailureMessage) interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{ - IncomingCircuitKey: request.IncomingCircuitKey, - Action: routerrpc.ResolveHoldForwardAction_FAIL, - FailureCode: i.mapFailureCode(interceptResult.FailureCode), + IncomingCircuitKey: request.IncomingCircuitKey, + Action: routerrpc.ResolveHoldForwardAction_FAIL, + FailureMessage: interceptResult.FailureMessage, + FailureMessageUnencrypted: true, }) case common.INTERCEPT_RESUME: fallthrough @@ -176,20 +177,6 @@ func (i *LndHtlcInterceptor) intercept() error { } } -func (i *LndHtlcInterceptor) mapFailureCode(original common.InterceptFailureCode) lnrpc.Failure_FailureCode { - switch original { - case common.FAILURE_TEMPORARY_CHANNEL_FAILURE: - return lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE - case common.FAILURE_TEMPORARY_NODE_FAILURE: - return lnrpc.Failure_TEMPORARY_NODE_FAILURE - case common.FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS: - return lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS - default: - log.Printf("Unknown failure code %v, default to temporary channel failure.", original) - return lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE - } -} - func (i *LndHtlcInterceptor) constructOnion( interceptResult common.InterceptResult, reqOutgoingExpiry uint32, diff --git a/lsps2/intercept_handler.go b/lsps2/intercept_handler.go index 2eb83b37..92ff53c8 100644 --- a/lsps2/intercept_handler.go +++ b/lsps2/intercept_handler.go @@ -623,11 +623,11 @@ func (i *Interceptor) handlePaymentChanOpened(event *paymentChanOpenedEvent) { func (i *Interceptor) handlePaymentFailure( paymentId string, - code common.InterceptFailureCode, + message []byte, ) { i.finalizeAllParts(paymentId, &common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: code, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: message, }) } @@ -663,11 +663,11 @@ func (i *Interceptor) Intercept(req common.InterceptRequest) common.InterceptRes func (i *Interceptor) failPart( payment *paymentState, part *partState, - code common.InterceptFailureCode, + message []byte, ) { part.resolution <- &common.InterceptResult{ - Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, - FailureCode: code, + Action: common.INTERCEPT_FAIL_HTLC_WITH_CODE, + FailureMessage: message, } delete(payment.parts, part.req.HtlcId()) if len(payment.parts) == 0 { diff --git a/lsps2/intercept_test.go b/lsps2/intercept_test.go index 4f136193..d55b2e67 100644 --- a/lsps2/intercept_test.go +++ b/lsps2/intercept_test.go @@ -284,7 +284,7 @@ func Test_NoMpp_AmtBelowMinimum(t *testing.T) { res := i.Intercept(createPart(&part{amt: defaultMinViableAmount - 1})) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureMessage) assertEmpty(t, i) } @@ -309,7 +309,7 @@ func Test_NoMpp_AmtAboveMaximum(t *testing.T) { res := i.Intercept(createPart(&part{amt: defaultConfig().MaxPaymentSizeMsat + 1})) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureMessage) assertEmpty(t, i) } @@ -322,7 +322,7 @@ func Test_NoMpp_CltvDeltaBelowMinimum(t *testing.T) { res := i.Intercept(createPart(&part{cltvDelta: 145})) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_INCORRECT_CLTV_EXPIRY, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_INCORRECT_CLTV_EXPIRY, res.FailureMessage) assertEmpty(t, i) } @@ -350,7 +350,7 @@ func Test_NoMpp_ParamsExpired(t *testing.T) { res := i.Intercept(createPart(nil)) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureMessage) assertEmpty(t, i) } @@ -376,7 +376,7 @@ func Test_NoMpp_ChannelAlreadyOpened_Complete_Fails(t *testing.T) { res := i.Intercept(createPart(nil)) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureMessage) assertEmpty(t, i) } @@ -408,7 +408,7 @@ func Test_Mpp_SinglePart_AmtTooSmall(t *testing.T) { res := i.Intercept(createPart(&part{amt: defaultPaymentSizeMsat - 1})) end := time.Now() assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_TEMPORARY_CHANNEL_FAILURE, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_TEMPORARY_CHANNEL_FAILURE, res.FailureMessage) assert.GreaterOrEqual(t, end.Sub(start).Milliseconds(), config.MppTimeout.Milliseconds()) assertEmpty(t, i) } @@ -519,7 +519,7 @@ func Test_Mpp_BadSecondPart_ThirdPartCompletes(t *testing.T) { assert.Equal(t, defaultFee, *res1.FeeMsat) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res2.Action) - assert.Equal(t, common.FAILURE_AMOUNT_BELOW_MINIMUM, res2.FailureCode) + assert.ElementsMatch(t, common.FAILURE_AMOUNT_BELOW_MINIMUM, res2.FailureMessage) assert.Equal(t, common.INTERCEPT_RESUME_WITH_ONION, res3.Action) assert.Equal(t, defaultConfig().HtlcMinimumMsat, res3.AmountMsat) @@ -541,7 +541,7 @@ func Test_Mpp_CltvDeltaBelowMinimum(t *testing.T) { res := i.Intercept(createPart(&part{cltvDelta: 145})) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_INCORRECT_CLTV_EXPIRY, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_INCORRECT_CLTV_EXPIRY, res.FailureMessage) assertEmpty(t, i) } @@ -569,7 +569,7 @@ func Test_Mpp_ParamsExpired(t *testing.T) { res := i.Intercept(createPart(nil)) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureMessage) assertEmpty(t, i) } @@ -605,9 +605,9 @@ func Test_Mpp_ParamsExpireInFlight(t *testing.T) { wg.Wait() assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res1.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res1.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res1.FailureMessage) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res2.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res2.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res2.FailureMessage) assertEmpty(t, i) } @@ -698,7 +698,7 @@ func Test_Mpp_ChannelAlreadyOpened_Complete_Fails(t *testing.T) { res := i.Intercept(createPart(nil)) assert.Equal(t, common.INTERCEPT_FAIL_HTLC_WITH_CODE, res.Action) - assert.Equal(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureCode) + assert.ElementsMatch(t, common.FAILURE_UNKNOWN_NEXT_PEER, res.FailureMessage) assertEmpty(t, i) }