diff --git a/common/onion.c b/common/onion.c index a29327e7a..368f543da 100644 --- a/common/onion.c +++ b/common/onion.c @@ -159,14 +159,16 @@ static bool handle_blinded_forward(struct onion_payload *p, return false; } - /* FIXME: handle fwd-by-node-id */ - if (!enc->short_channel_id) { - *failtlvtype = TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; - return false; + if (enc->short_channel_id) { + p->forward_channel = tal_dup(p, struct short_channel_id, + enc->short_channel_id); + p->forward_node_id = NULL; + } else { + p->forward_channel = NULL; + p->forward_node_id = tal_dup(p, struct pubkey, + enc->next_node_id); } - p->forward_channel = tal_dup(p, struct short_channel_id, - enc->short_channel_id); p->total_msat = NULL; /* BOLT-route-blinding #4: @@ -231,6 +233,8 @@ static bool handle_blinded_terminal(struct onion_payload *p, p->outgoing_cltv = *tlv->outgoing_cltv_value; p->forward_channel = NULL; + p->forward_node_id = NULL; + if (tlv->total_amount_msat) { p->total_msat = tal(p, struct amount_msat); *p->total_msat = amount_msat(*tlv->total_amount_msat); @@ -454,6 +458,9 @@ struct onion_payload *onion_decode(const tal_t *ctx, &p->amt_to_forward); } + /* Non-blinded is (currently) always by scid */ + p->forward_node_id = NULL; + p->payment_secret = NULL; if (p->tlv->payment_data) { p->payment_secret = tal_dup(p, struct secret, diff --git a/common/onion.h b/common/onion.h index 6bd4bf234..37587038c 100644 --- a/common/onion.h +++ b/common/onion.h @@ -11,7 +11,11 @@ struct onion_payload { struct amount_msat amt_to_forward; u32 outgoing_cltv; struct amount_msat *total_msat; + + /* One of these is set */ struct short_channel_id *forward_channel; + struct pubkey *forward_node_id; + struct secret *payment_secret; u8 *payment_metadata; diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 20db3bce4..fd1d3262f 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -714,7 +714,7 @@ static void forward_htlc(struct htlc_in *hin, /* Update this to where we're actually trying to send. */ if (next) forward_scid = channel_scid_or_local_alias(next); - }else + } else next = NULL; /* Unknown peer, or peer not ready. */ @@ -1077,6 +1077,9 @@ static void htlc_accepted_hook_serialize(struct htlc_accepted_hook_payload *p, if (p->payload->forward_channel) json_add_short_channel_id(s, "short_channel_id", p->payload->forward_channel); + if (p->payload->forward_node_id) + json_add_pubkey(s, "next_node_id", + p->payload->forward_node_id); if (deprecated_apis) json_add_string(s, "forward_amount", fmt_amount_msat(tmpctx, @@ -1202,20 +1205,42 @@ static struct channel_id *calc_forwarding_channel(struct lightningd *ld, const struct route_step *rs) { const struct onion_payload *p = hp->payload; + struct peer *peer; struct channel *c, *best; if (rs->nextcase != ONION_FORWARD) return NULL; - if (!p || !p->forward_channel) + if (!p) return NULL; - c = any_channel_by_scid(ld, p->forward_channel, false); - if (!c) - return NULL; + if (p->forward_channel) { + c = any_channel_by_scid(ld, p->forward_channel, false); + if (!c) + return NULL; + peer = c->peer; + } else { + struct node_id id; + if (!p->forward_node_id) + return NULL; + node_id_from_pubkey(&id, p->forward_node_id); + peer = peer_by_id(ld, &id); + if (!peer) + return NULL; + c = NULL; + } - best = best_channel(ld, c->peer, p->amt_to_forward, c); - if (best != c) { + best = best_channel(ld, peer, p->amt_to_forward, c); + if (!c) { + if (!best) + return NULL; + log_debug(hp->channel->log, + "Chose channel %s for peer %s", + type_to_string(tmpctx, struct short_channel_id, + channel_scid_or_local_alias(best)), + type_to_string(tmpctx, struct node_id, + &peer->id)); + } else if (best != c) { log_debug(hp->channel->log, "Chose a better channel than %s: %s", type_to_string(tmpctx, struct short_channel_id, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 9836974e5..9b7a5bf9c 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -347,6 +347,11 @@ void json_add_node_id(struct json_stream *response UNNEEDED, void json_add_num(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED, unsigned int value UNNEEDED) { fprintf(stderr, "json_add_num called!\n"); abort(); } +/* Generated stub for json_add_pubkey */ +void json_add_pubkey(struct json_stream *response UNNEEDED, + const char *fieldname UNNEEDED, + const struct pubkey *key UNNEEDED) +{ fprintf(stderr, "json_add_pubkey called!\n"); abort(); } /* Generated stub for json_add_s32 */ void json_add_s32(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED, int32_t value UNNEEDED)