diff --git a/common/onion_decode.c b/common/onion_decode.c index 7711790f29f9..d1bc9b0bdea6 100644 --- a/common/onion_decode.c +++ b/common/onion_decode.c @@ -3,10 +3,12 @@ #include #include #include +#include #include #include #include #include +#include #include /* BOLT #4: @@ -62,17 +64,22 @@ static u64 ceil_div(u64 a, u64 b) return (a + b - 1) / b; } -static bool handle_blinded_forward(struct onion_payload *p, +static bool handle_blinded_forward(const tal_t *ctx, + struct onion_payload *p, struct amount_msat amount_in, u32 cltv_expiry, const struct tlv_payload *tlv, const struct tlv_encrypted_data_tlv *enc, - u64 *failtlvtype) + u64 *failtlvtype, + const char **explanation) { u64 amt = amount_in.millisatoshis; /* Raw: allowed to wrap */ - if (!check_nonfinal_tlv(tlv, failtlvtype)) + if (!check_nonfinal_tlv(tlv, failtlvtype)) { + if (explanation) + *explanation = tal_fmt(ctx, "unexpected tlv type %"PRIu64, *failtlvtype); return false; + } /* BOLT #4: * - If it is not the final node: @@ -81,6 +88,8 @@ static bool handle_blinded_forward(struct onion_payload *p, * contain either `short_channel_id` or `next_node_id`. */ if (!enc->short_channel_id && !enc->next_node_id) { + if (explanation) + *explanation = tal_fmt(ctx, "neither short_channel_id nor next_node_id present"); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; return false; } @@ -104,6 +113,8 @@ static bool handle_blinded_forward(struct onion_payload *p, * contain `payment_relay`. */ if (!enc->payment_relay) { + if (explanation) + *explanation = tal_fmt(ctx, "missing payment_relay"); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; return false; } @@ -117,13 +128,18 @@ static bool handle_blinded_forward(struct onion_payload *p, return true; } -static bool handle_blinded_terminal(struct onion_payload *p, +static bool handle_blinded_terminal(const tal_t *ctx, + struct onion_payload *p, const struct tlv_payload *tlv, const struct tlv_encrypted_data_tlv *enc, - u64 *failtlvtype) + u64 *failtlvtype, + const char **explanation) { - if (!check_final_tlv(tlv, failtlvtype)) + if (!check_final_tlv(tlv, failtlvtype)) { + if (explanation) + *explanation = tal_fmt(ctx, "unexpected tlv type %"PRIu64, *failtlvtype); return false; + } /* BOLT #4: * - MUST return an error if `amt_to_forward`, `outgoing_cltv_value` @@ -132,16 +148,22 @@ static bool handle_blinded_terminal(struct onion_payload *p, * for the payment. */ if (!tlv->amt_to_forward) { + if (explanation) + *explanation = tal_fmt(ctx, "missing amt_to_forward"); *failtlvtype = TLV_PAYLOAD_AMT_TO_FORWARD; return false; } if (!tlv->outgoing_cltv_value) { + if (explanation) + *explanation = tal_fmt(ctx, "missing outgoing_cltv_value"); *failtlvtype = TLV_PAYLOAD_OUTGOING_CLTV_VALUE; return false; } if (!tlv->total_amount_msat) { + if (explanation) + *explanation = tal_fmt(ctx, "missing total_amount_msat"); *failtlvtype = TLV_PAYLOAD_TOTAL_AMOUNT_MSAT; return false; } @@ -173,7 +195,8 @@ struct onion_payload *onion_decode(const tal_t *ctx, struct amount_msat amount_in, u32 cltv_expiry, u64 *failtlvtype, - size_t *failtlvpos) + size_t *failtlvpos, + const char **explanation) { struct onion_payload *p = tal(ctx, struct onion_payload); const u8 *cursor = rs->raw_payload; @@ -191,6 +214,8 @@ struct onion_payload *onion_decode(const tal_t *ctx, if (!cursor || len > max) { *failtlvtype = 0; *failtlvpos = tal_bytelen(rs->raw_payload); + if (explanation) + *explanation = tal_fmt(ctx, "Too short for initial length"); return tal_free(p); } @@ -201,6 +226,8 @@ struct onion_payload *onion_decode(const tal_t *ctx, TLVS_ARRAY_SIZE_tlv_payload, p->tlv, &p->tlv->fields, accepted_extra_tlvs, failtlvpos, failtlvtype)) { + if (explanation) + *explanation = tal_fmt(ctx, "Unparseable TLV"); return tal_free(p); } @@ -225,12 +252,16 @@ struct onion_payload *onion_decode(const tal_t *ctx, if (path_key) { if (p->tlv->current_path_key) { *failtlvtype = TLV_PAYLOAD_CURRENT_PATH_KEY; + if (explanation) + *explanation = tal_fmt(ctx, "current_path_key was present"); goto field_bad; } p->path_key = tal_dup(p, struct pubkey, path_key); } else { if (!p->tlv->current_path_key) { *failtlvtype = TLV_PAYLOAD_CURRENT_PATH_KEY; + if (explanation) + *explanation = tal_fmt(ctx, "current_path_key was not present"); goto field_bad; } p->path_key = tal_dup(p, struct pubkey, @@ -248,6 +279,8 @@ struct onion_payload *onion_decode(const tal_t *ctx, enc = decrypt_encrypted_data(tmpctx, &p->blinding_ss, p->tlv->encrypted_recipient_data); if (!enc) { + if (explanation) + *explanation = tal_fmt(ctx, "encrypted_recipient_data decryption failed"); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; goto field_bad; } @@ -259,6 +292,10 @@ struct onion_payload *onion_decode(const tal_t *ctx, * `encrypted_recipient_data.payment_constraints.max_cltv_expiry`. */ if (cltv_expiry > enc->payment_constraints->max_cltv_expiry) { + if (explanation) + *explanation = tal_fmt(ctx, "cltv_expiry %u > payment_constraint %u", + cltv_expiry, + enc->payment_constraints->max_cltv_expiry); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; goto field_bad; } @@ -271,6 +308,10 @@ struct onion_payload *onion_decode(const tal_t *ctx, */ if (amount_msat_less(amount_in, amount_msat(enc->payment_constraints->htlc_minimum_msat))) { + if (explanation) + *explanation = tal_fmt(ctx, "amount_in %s < payment_constraint min %"PRIu64, + fmt_amount_msat(tmpctx, amount_in), + enc->payment_constraints->htlc_minimum_msat); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; goto field_bad; } @@ -299,21 +340,26 @@ struct onion_payload *onion_decode(const tal_t *ctx, /* No features, this is easy */ if (!memeqzero(enc->allowed_features, tal_bytelen(enc->allowed_features))) { + if (explanation) + *explanation = tal_fmt(ctx, "non-zero allowed_features (%s)", + tal_hex(tmpctx, enc->allowed_features)); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; goto field_bad; } if (enc->short_channel_id && enc->next_node_id) { + if (explanation) + *explanation = tal_fmt(ctx, "both scid and next_node_id present"); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; goto field_bad; } if (!p->final) { - if (!handle_blinded_forward(p, amount_in, cltv_expiry, - p->tlv, enc, failtlvtype)) + if (!handle_blinded_forward(ctx, p, amount_in, cltv_expiry, + p->tlv, enc, failtlvtype, explanation)) goto field_bad; } else { - if (!handle_blinded_terminal(p, p->tlv, enc, failtlvtype)) + if (!handle_blinded_terminal(ctx, p, p->tlv, enc, failtlvtype, explanation)) goto field_bad; } @@ -336,6 +382,9 @@ struct onion_payload *onion_decode(const tal_t *ctx, * is present. */ if (path_key || p->tlv->current_path_key) { + if (explanation) + *explanation = tal_fmt(ctx, "%s set outside blinded route", + path_key ? "update_add_htlc->path_key" : "current_path_key"); *failtlvtype = TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; goto field_bad; } @@ -348,10 +397,14 @@ struct onion_payload *onion_decode(const tal_t *ctx, * `outgoing_cltv_value` are not present. */ if (!p->tlv->amt_to_forward) { + if (explanation) + *explanation = tal_fmt(ctx, "missing amt_to_forward"); *failtlvtype = TLV_PAYLOAD_AMT_TO_FORWARD; goto field_bad; } if (!p->tlv->outgoing_cltv_value) { + if (explanation) + *explanation = tal_fmt(ctx, "missing outgoing_cltv_value"); *failtlvtype = TLV_PAYLOAD_OUTGOING_CLTV_VALUE; goto field_bad; } @@ -367,6 +420,8 @@ struct onion_payload *onion_decode(const tal_t *ctx, */ if (!p->final) { if (!p->tlv->short_channel_id) { + if (explanation) + *explanation = tal_fmt(ctx, "missing short_channel_id"); *failtlvtype = TLV_PAYLOAD_SHORT_CHANNEL_ID; goto field_bad; } diff --git a/common/onion_decode.h b/common/onion_decode.h index 3e09f03cd4e9..c1149972b78f 100644 --- a/common/onion_decode.h +++ b/common/onion_decode.h @@ -16,6 +16,7 @@ * @cltv_expiry: Incoming HTLC cltv_expiry * @failtlvtype: (out) the tlv type which failed to parse. * @failtlvpos: (out) the offset in the tlv which failed to parse. + * @explanation: (out) if non-NULL, a string describing the problem on failure. * * If the payload is not valid, returns NULL. */ @@ -26,5 +27,6 @@ struct onion_payload *onion_decode(const tal_t *ctx, struct amount_msat amount_in, u32 cltv_expiry, u64 *failtlvtype, - size_t *failtlvpos); + size_t *failtlvpos, + const char **explanation); #endif /* LIGHTNING_COMMON_ONION_DECODE_H */ diff --git a/common/test/run-blindedpath_onion.c b/common/test/run-blindedpath_onion.c index a58ccae9f852..fc6d015cc4d2 100644 --- a/common/test/run-blindedpath_onion.c +++ b/common/test/run-blindedpath_onion.c @@ -55,6 +55,9 @@ struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } +/* Generated stub for fmt_amount_msat */ +char *fmt_amount_msat(const tal_t *ctx UNNEEDED, struct amount_msat msat UNNEEDED) +{ fprintf(stderr, "fmt_amount_msat called!\n"); abort(); } /* Generated stub for fromwire_amount_msat */ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); } diff --git a/common/test/run-onion-test-vector.c b/common/test/run-onion-test-vector.c index d29637fec966..130de79bb01d 100644 --- a/common/test/run-onion-test-vector.c +++ b/common/test/run-onion-test-vector.c @@ -66,6 +66,9 @@ struct tlv_encrypted_data_tlv *decrypt_encrypted_data(const tal_t *ctx UNNEEDED, /* Generated stub for ecdh */ void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED) { fprintf(stderr, "ecdh called!\n"); abort(); } +/* Generated stub for fmt_amount_msat */ +char *fmt_amount_msat(const tal_t *ctx UNNEEDED, struct amount_msat msat UNNEEDED) +{ fprintf(stderr, "fmt_amount_msat called!\n"); abort(); } /* Generated stub for fromwire_amount_msat */ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); } diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c index 2bca7edf4253..b44101f69e1e 100644 --- a/common/test/run-sphinx.c +++ b/common/test/run-sphinx.c @@ -67,6 +67,9 @@ struct tlv_encrypted_data_tlv *decrypt_encrypted_data(const tal_t *ctx UNNEEDED, /* Generated stub for ecdh */ void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED) { fprintf(stderr, "ecdh called!\n"); abort(); } +/* Generated stub for fmt_amount_msat */ +char *fmt_amount_msat(const tal_t *ctx UNNEEDED, struct amount_msat msat UNNEEDED) +{ fprintf(stderr, "fmt_amount_msat called!\n"); abort(); } /* Generated stub for fromwire_amount_msat */ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); } diff --git a/lightningd/pay.c b/lightningd/pay.c index a827d1e61222..d3c4141684bf 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -1844,6 +1844,7 @@ static struct command_result *json_injectpaymentonion(struct command *cmd, const u8 *failmsg; struct htlc_out *hout; const struct wallet_payment *prev_payment; + const char *explanation; if (!param_check(cmd, buffer, params, p_req("onion", param_bin_from_hex, &onion), @@ -1915,12 +1916,13 @@ static struct command_result *json_injectpaymentonion(struct command *cmd, cmd->ld->accept_extra_tlv_types, *msat, *cltv, &failtlvtype, - &failtlvpos); + &failtlvpos, + &explanation); if (!payload) { return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Onion decode for %s failed at type %"PRIu64" offset %zu", + "Onion decode for %s failed at type %"PRIu64" offset %zu (%s)", tal_hex(tmpctx, rs->raw_payload), - failtlvtype, failtlvpos); + failtlvtype, failtlvpos, explanation); } if (payload->final) { diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 1d53707c4e17..8bfb9afa42f1 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -155,38 +155,14 @@ static bool blind_error_return(const struct htlc_in *hin) return false; } -static struct failed_htlc *mk_failed_htlc_badonion(const tal_t *ctx, - const struct htlc_in *hin, - enum onion_wire badonion) -{ - struct failed_htlc *f = tal(ctx, struct failed_htlc); - - if (blind_error_return(hin)) - badonion = WIRE_INVALID_ONION_BLINDING; - - f->id = hin->key.id; - f->onion = NULL; - f->badonion = badonion; - f->sha256_of_onion = tal(f, struct sha256); - sha256(f->sha256_of_onion, hin->onion_routing_packet, - sizeof(hin->onion_routing_packet)); - return f; -} - static struct failed_htlc *mk_failed_htlc(const tal_t *ctx, const struct htlc_in *hin, const struct onionreply *failonion) { struct failed_htlc *f = tal(ctx, struct failed_htlc); + /* Inside a blinded path, override return */ if (blind_error_return(hin)) { - return mk_failed_htlc_badonion(ctx, hin, - WIRE_INVALID_ONION_BLINDING); - } - - /* Also, at head of the blinded path, return "normal" invalid - * onion blinding. */ - if (hin->payload && hin->payload->path_key) { struct sha256 sha; sha256(&sha, hin->onion_routing_packet, sizeof(hin->onion_routing_packet)); @@ -203,6 +179,25 @@ static struct failed_htlc *mk_failed_htlc(const tal_t *ctx, return f; } +static struct failed_htlc *mk_failed_htlc_badonion(const tal_t *ctx, + const struct htlc_in *hin, + enum onion_wire badonion) +{ + struct failed_htlc *f = tal(ctx, struct failed_htlc); + + /* Inside a blinded path, override return */ + if (blind_error_return(hin)) + return mk_failed_htlc(ctx, hin, NULL); + + f->id = hin->key.id; + f->onion = NULL; + f->badonion = badonion; + f->sha256_of_onion = tal(f, struct sha256); + sha256(f->sha256_of_onion, hin->onion_routing_packet, + sizeof(hin->onion_routing_packet)); + return f; +} + static void tell_channeld_htlc_failed(const struct htlc_in *hin, const struct failed_htlc *failed_htlc) { @@ -927,6 +922,7 @@ struct htlc_accepted_hook_payload { u8 *next_onion; u64 failtlvtype; size_t failtlvpos; + const char *failexplanation; }; static void @@ -1017,7 +1013,8 @@ static bool htlc_accepted_hook_deserialize(struct htlc_accepted_hook_payload *re hin->msat, hin->cltv_expiry, &request->failtlvtype, - &request->failtlvpos); + &request->failtlvpos, + &request->failexplanation); } fwdtok = json_get_member(buffer, toks, "forward_to"); @@ -1176,8 +1173,9 @@ htlc_accepted_hook_final(struct htlc_accepted_hook_payload *request STEALS) /* *Now* we barf if it failed to decode */ if (!request->payload) { log_debug(channel->log, - "Failing HTLC because of an invalid payload (TLV %"PRIu64" pos %zu)", - request->failtlvtype, request->failtlvpos); + "Failing HTLC because of an invalid payload (TLV %"PRIu64" pos %zu): %s", + request->failtlvtype, request->failtlvpos, + request->failexplanation); local_fail_in_htlc(hin, take(towire_invalid_onion_payload( NULL, request->failtlvtype, @@ -1438,7 +1436,8 @@ static bool peer_accepted_htlc(const tal_t *ctx, hin->msat, hin->cltv_expiry, &hook_payload->failtlvtype, - &hook_payload->failtlvpos); + &hook_payload->failtlvpos, + &hook_payload->failexplanation); hook_payload->ld = ld; hook_payload->hin = hin; hook_payload->channel = channel; @@ -1474,8 +1473,14 @@ static bool peer_accepted_htlc(const tal_t *ctx, fail: /* In a blinded path, *all* failures are "invalid_onion_blinding" */ if (hin->path_key) { - *failmsg = tal_free(*failmsg); - *badonion = WIRE_INVALID_ONION_BLINDING; + struct sha256 hash; + + *badonion = 0; + tal_free(*failmsg); + + sha256(&hash, hin->onion_routing_packet, + sizeof(hin->onion_routing_packet)); + *failmsg = towire_invalid_onion_blinding(ctx, &hash); } return false; } diff --git a/plugins/offers.c b/plugins/offers.c index 3d2e54282e39..03620a6fd302 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -351,8 +351,13 @@ static struct command_result *block_added_notify(struct command *cmd, const char *buf, const jsmntok_t *params) { - json_scan(cmd, buf, params, "{block:{height:%}}", - JSON_SCAN(json_to_u32, &blockheight)); + const char *err = json_scan(cmd, buf, params, "{block_added:{height:%}}", + JSON_SCAN(json_to_u32, &blockheight)); + if (err) + plugin_err(cmd->plugin, "Failed to parse block_added (%.*s): %s", + json_tok_full_len(params), + json_tok_full(buf, params), + err); return notification_handled(cmd); } diff --git a/tests/plugins/channeld_fakenet.c b/tests/plugins/channeld_fakenet.c index ac0609cf46c2..100f3e00cd37 100644 --- a/tests/plugins/channeld_fakenet.c +++ b/tests/plugins/channeld_fakenet.c @@ -292,6 +292,7 @@ static struct onion_payload *decode_onion(const tal_t *ctx, struct privkey pk; struct pubkey current_pubkey; struct node_id current_node_id; + const char *explanation; op = parse_onionpacket(tmpctx, onion_routing_packet, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), @@ -335,11 +336,11 @@ static struct onion_payload *decode_onion(const tal_t *ctx, rs, path_key, NULL, amount, - cltv, &failtlvtype, &failtlvpos); + cltv, &failtlvtype, &failtlvpos, &explanation); if (!payload) { status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed tlvtype %"PRIu64" at %zu", - failtlvtype, failtlvpos); + "Failed tlvtype %"PRIu64" at %zu: %s", + failtlvtype, failtlvpos, explanation); } /* Find ourselves in the gossmap, so we know our channels */ diff --git a/tests/test_pay.py b/tests/test_pay.py index 1c649e8c09dd..02b43ec30536 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -4509,8 +4509,7 @@ def test_fetchinvoice(node_factory, bitcoind): l1.rpc.pay(inv1['invoice']) # We can't pay the other one now. - # FIXME: Even dummy blinded paths always return WIRE_INVALID_ONION_BLINDING! - with pytest.raises(RpcError, match="INVALID_ONION_BLINDING.*'erring_node': '{}'".format(l3.info['id'])): + with pytest.raises(RpcError, match="INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS.*'erring_node': '{}'".format(l3.info['id'])): l1.rpc.pay(inv2['invoice']) # We can't reuse the offer, either. @@ -5993,6 +5992,21 @@ def test_enableoffer(node_factory): l1.rpc.enableoffer(offer_id=offer1['offer_id']) +def test_offer_with_private_channels_multyhop2(node_factory): + """We should be able to fetch an invoice through a private path and pay the invoice""" + l1, l2, l3, l4, l5 = node_factory.line_graph(5, fundchannel=False) + + node_factory.join_nodes([l1, l2], wait_for_announce=True) + node_factory.join_nodes([l2, l3], wait_for_announce=True) + node_factory.join_nodes([l3, l4], wait_for_announce=True) + node_factory.join_nodes([l3, l5], announce_channels=False) + wait_for(lambda: ['alias' in n for n in l4.rpc.listnodes()['nodes']] == [True, True, True, True]) + + offer = l5.rpc.offer(amount='2msat', description='test_offer_with_private_channels_multyhop2')['bolt12'] + invoice = l1.rpc.fetchinvoice(offer=offer)["invoice"] + l1.rpc.pay(invoice) + + def diamond_network(node_factory): """Build a diamond, with a cheap route, that is exhausted. The first payment should try that route first, learn it's exhausted, diff --git a/tests/test_xpay.py b/tests/test_xpay.py index f3a4bdccaa55..62450ec5c440 100644 --- a/tests/test_xpay.py +++ b/tests/test_xpay.py @@ -188,8 +188,7 @@ def test_xpay_simple(node_factory): l1.rpc.xpay(b11) # Failure from l3 (with blinded path) - # FIXME: We return wrong error here! - with pytest.raises(RpcError, match=r"Failed after 1 attempts\. Unexpected error \(invalid_onion_payload\) from intermediate node: disabling the invoice's blinded path \(0x0x0/[01]\) for this payment\. Then routing failed: We could not find a usable set of paths\. The destination has disabled 1 of 1 channels, leaving capacity only 0msat of 10605000msat\."): + with pytest.raises(RpcError, match=r"Failed after 1 attempts. We got an error from inside the blinded path 0x0x0/1: we assume it means insufficient capacity. Then routing failed: We could not find a usable set of paths. The shortest path is [0-9x]*->[0-9x]*->0x0x0, but 0x0x0/1 layer xpay-7 says max is 99999msat"): l1.rpc.xpay(b12) # Restart, try pay already paid one again. diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 03f6d09199a1..a534bc3f6289 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -742,7 +742,8 @@ struct onion_payload *onion_decode(const tal_t *ctx UNNEEDED, struct amount_msat amount_in UNNEEDED, u32 cltv_expiry UNNEEDED, u64 *failtlvtype UNNEEDED, - size_t *failtlvpos UNNEEDED) + size_t *failtlvpos UNNEEDED, + const char **explanation UNNEEDED) { fprintf(stderr, "onion_decode called!\n"); abort(); } /* Generated stub for onion_final_hop */ u8 *onion_final_hop(const tal_t *ctx UNNEEDED,