mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-12 10:30:29 +01:00
connectd: forward onion messages by scid as well as node_id.
This is now permitted in the offers PR, so we should support it. But we can't just look up in the gossmap, since the "short_channel_id" could be an alias. So we get lightningd to tell us all scid->peer mappings, and look up in that. Changelog-Added: Protocol: onion messages can now be forwarded by short_channel_id. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
19af516dcb
commit
621bfe370e
4 changed files with 56 additions and 32 deletions
|
@ -40,7 +40,7 @@ static bool decrypt_final_onionmsg(const tal_t *ctx,
|
|||
static bool decrypt_forwarding_onionmsg(const struct pubkey *blinding,
|
||||
const struct secret *ss,
|
||||
const u8 *enctlv,
|
||||
struct pubkey *next_node,
|
||||
struct sciddir_or_pubkey *next_node,
|
||||
struct pubkey *next_blinding)
|
||||
{
|
||||
struct tlv_encrypted_data_tlv *encmsg;
|
||||
|
@ -58,14 +58,27 @@ static bool decrypt_forwarding_onionmsg(const struct pubkey *blinding,
|
|||
if (encmsg->path_id)
|
||||
return false;
|
||||
|
||||
/* BOLT #4:
|
||||
* - SHOULD forward the message using `onion_message` to the next peer
|
||||
* indicated by `next_node_id`.
|
||||
/* BOLT-offers #4:
|
||||
* - if it is not the final node according to the onion encryption:
|
||||
*...
|
||||
* - if `next_node_id` is present:
|
||||
* - the *next peer* is the peer with that node id.
|
||||
* - otherwise, if `short_channel_id` is present and corresponds to an announced short_channel_id or a local alias for a channel:
|
||||
* - the *next peer* is the peer at the other end of that channel.
|
||||
* - otherwise:
|
||||
* - MUST ignore the message.
|
||||
*/
|
||||
if (!encmsg->next_node_id)
|
||||
if (encmsg->next_node_id)
|
||||
sciddir_or_pubkey_from_pubkey(next_node, encmsg->next_node_id);
|
||||
else if (encmsg->short_channel_id) {
|
||||
/* This is actually scid, not sciddir, but the type is convenient! */
|
||||
struct short_channel_id_dir scidd;
|
||||
scidd.scid = *encmsg->short_channel_id;
|
||||
scidd.dir = 0;
|
||||
sciddir_or_pubkey_from_scidd(next_node, &scidd);
|
||||
} else
|
||||
return false;
|
||||
|
||||
*next_node = *encmsg->next_node_id;
|
||||
blindedpath_next_blinding(encmsg, blinding, ss, next_blinding);
|
||||
return true;
|
||||
}
|
||||
|
@ -76,7 +89,7 @@ const char *onion_message_parse(const tal_t *ctx,
|
|||
const struct pubkey *blinding,
|
||||
const struct pubkey *me,
|
||||
u8 **next_onion_msg,
|
||||
struct pubkey *next_node_id,
|
||||
struct sciddir_or_pubkey *next_node,
|
||||
struct tlv_onionmsg_tlv **final_om,
|
||||
struct pubkey *final_alias,
|
||||
struct secret **final_path_id)
|
||||
|
@ -161,7 +174,7 @@ const char *onion_message_parse(const tal_t *ctx,
|
|||
}
|
||||
|
||||
/* This fails as expected if no enctlv. */
|
||||
if (!decrypt_forwarding_onionmsg(blinding, &ss, om->encrypted_recipient_data, next_node_id,
|
||||
if (!decrypt_forwarding_onionmsg(blinding, &ss, om->encrypted_recipient_data, next_node,
|
||||
&next_blinding)) {
|
||||
return tal_fmt(ctx,
|
||||
"onion_message_parse: invalid encrypted_recipient_data %s",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <common/amount.h>
|
||||
|
||||
struct tlv_onionmsg_tlv;
|
||||
struct node_id;
|
||||
struct sciddir_or_pubkey;
|
||||
struct pubkey;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,7 @@ struct pubkey;
|
|||
* @blinding: Blinding we were given for @onion_message_packet
|
||||
* @me: my pubkey
|
||||
* @next_onion_msg (out): set if we should forward, otherwise NULL.
|
||||
* @next_node_id (out): set to node id to fwd to, iff *@next_onion_msg.
|
||||
* @next_node (out): set to node id or scid to fwd to, iff *@next_onion_msg.
|
||||
* @final_om (out): set if we're the final hop, otherwise NULL.
|
||||
* @final_alias (out): our alias (if *@final_om), or our own ID
|
||||
* @final_path_id (out): secret enclosed, if any (iff *@final_om).
|
||||
|
@ -27,7 +27,7 @@ const char *onion_message_parse(const tal_t *ctx,
|
|||
const struct pubkey *blinding,
|
||||
const struct pubkey *me,
|
||||
u8 **next_onion_msg,
|
||||
struct pubkey *next_node_id,
|
||||
struct sciddir_or_pubkey *next_node,
|
||||
struct tlv_onionmsg_tlv **final_om,
|
||||
struct pubkey *final_alias,
|
||||
struct secret **final_path_id);
|
||||
|
|
|
@ -14,6 +14,7 @@ static void maybe_print(const char *fmt, ...);
|
|||
#include "../hmac.c"
|
||||
#include "../onion_encode.c"
|
||||
#include "../onion_message_parse.c"
|
||||
#include "../sciddir_or_pubkey.c"
|
||||
#include "../sphinx.c"
|
||||
#include "../../wire/onion_wiregen.c"
|
||||
#include "../../wire/peer_wiregen.c"
|
||||
|
@ -29,32 +30,18 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
|
|||
/* Generated stub for fromwire_node_id */
|
||||
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_sciddir_or_pubkey */
|
||||
void fromwire_sciddir_or_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
|
||||
struct sciddir_or_pubkey *sciddpk UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_sciddir_or_pubkey called!\n"); abort(); }
|
||||
/* Generated stub for new_onionreply */
|
||||
struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents TAKES UNNEEDED)
|
||||
{ fprintf(stderr, "new_onionreply called!\n"); abort(); }
|
||||
/* Generated stub for pubkey_from_node_id */
|
||||
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)
|
||||
{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); }
|
||||
/* Generated stub for status_fmt */
|
||||
void status_fmt(enum log_level level UNNEEDED,
|
||||
const struct node_id *peer UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
|
||||
{ fprintf(stderr, "status_fmt called!\n"); abort(); }
|
||||
/* Generated stub for towire_channel_id */
|
||||
void towire_channel_id(u8 **pptr UNNEEDED, const struct channel_id *channel_id UNNEEDED)
|
||||
{ fprintf(stderr, "towire_channel_id called!\n"); abort(); }
|
||||
/* Generated stub for towire_node_id */
|
||||
void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED)
|
||||
{ fprintf(stderr, "towire_node_id called!\n"); abort(); }
|
||||
/* Generated stub for towire_sciddir_or_pubkey */
|
||||
void towire_sciddir_or_pubkey(u8 **pptr UNNEEDED,
|
||||
const struct sciddir_or_pubkey *sciddpk UNNEEDED)
|
||||
{ fprintf(stderr, "towire_sciddir_or_pubkey called!\n"); abort(); }
|
||||
/* AUTOGENERATED MOCKS END */
|
||||
|
||||
static bool comma;
|
||||
|
@ -355,7 +342,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
json_start("hops", '[');
|
||||
for (size_t i = 0; i < ARRAY_SIZE(erd); i++) {
|
||||
struct pubkey next_node_id;
|
||||
struct sciddir_or_pubkey next_node;
|
||||
struct tlv_onionmsg_tlv *final_om;
|
||||
struct pubkey final_alias;
|
||||
struct secret *final_path_id;
|
||||
|
@ -373,12 +360,13 @@ int main(int argc, char *argv[])
|
|||
mykey = &privkey[i];
|
||||
assert(onion_message_parse(tmpctx, onion_message_packet, &blinding_pub,
|
||||
&id[i],
|
||||
&onion_message, &next_node_id,
|
||||
&onion_message, &next_node,
|
||||
&final_om,
|
||||
&final_alias,
|
||||
&final_path_id) == NULL);
|
||||
if (onion_message) {
|
||||
json_pubkey("next_node_id", &next_node_id);
|
||||
assert(next_node.is_pubkey);
|
||||
json_pubkey("next_node_id", &next_node.pubkey);
|
||||
} else {
|
||||
const struct tlv_field *hello;
|
||||
json_start("tlvs", '{');
|
||||
|
|
|
@ -42,7 +42,7 @@ static const char *handle_onion(const tal_t *ctx,
|
|||
const u8 *onion)
|
||||
{
|
||||
u8 *next_onion_msg;
|
||||
struct pubkey next_node;
|
||||
struct sciddir_or_pubkey next_node;
|
||||
struct tlv_onionmsg_tlv *final_om;
|
||||
struct pubkey final_alias;
|
||||
struct secret *final_path_id;
|
||||
|
@ -73,12 +73,35 @@ static const char *handle_onion(const tal_t *ctx,
|
|||
|
||||
assert(next_onion_msg);
|
||||
|
||||
/* FIXME: Handle short_channel_id! */
|
||||
node_id_from_pubkey(&next_node_id, &next_node);
|
||||
/* BOLT-offers #4:
|
||||
* - if it is not the final node according to the onion encryption:
|
||||
*...
|
||||
* - if `next_node_id` is present:
|
||||
* - the *next peer* is the peer with that node id.
|
||||
* - otherwise, if `short_channel_id` is present and corresponds to an announced short_channel_id or a local alias for a channel:
|
||||
* - the *next peer* is the peer at the other end of that channel.
|
||||
* - otherwise:
|
||||
* - MUST ignore the message.
|
||||
* - SHOULD forward the message using `onion_message` to the *next peer*.
|
||||
*/
|
||||
/* Since an alias is legal here, we can't simply lookup in gossmap. */
|
||||
if (!next_node.is_pubkey) {
|
||||
struct scid_to_node_id *scid_to_node_id;
|
||||
|
||||
scid_to_node_id = scid_htable_get(daemon->scid_htable, next_node.scidd.scid);
|
||||
if (!scid_to_node_id) {
|
||||
return tal_fmt(ctx, "onion msg: unknown next scid %s",
|
||||
fmt_short_channel_id(tmpctx, next_node.scidd.scid));
|
||||
}
|
||||
next_node_id = scid_to_node_id->node_id;
|
||||
} else {
|
||||
node_id_from_pubkey(&next_node_id, &next_node.pubkey);
|
||||
}
|
||||
|
||||
next_peer = peer_htable_get(daemon->peers, &next_node_id);
|
||||
if (!next_peer) {
|
||||
return tal_fmt(ctx, "onion msg: unknown next peer %s",
|
||||
fmt_pubkey(tmpctx, &next_node));
|
||||
fmt_sciddir_or_pubkey(tmpctx, &next_node));
|
||||
}
|
||||
inject_peer_msg(next_peer, take(next_onion_msg));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue