diff --git a/channeld/channeld.c b/channeld/channeld.c index e0c304a0a..3e86da27f 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1931,9 +1931,7 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_PING: case WIRE_PONG: case WIRE_ERROR: -#if EXPERIMENTAL_FEATURES case WIRE_ONION_MESSAGE: -#endif abort(); } diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 2d0cfd429..572bd152d 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -757,6 +757,9 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, case WIRE_CHANNEL_REESTABLISH: case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: +#if !EXPERIMENTAL_FEATURES + case WIRE_ONION_MESSAGE: +#endif #if EXPERIMENTAL_FEATURES case WIRE_TX_ADD_INPUT: case WIRE_TX_REMOVE_INPUT: diff --git a/wire/Makefile b/wire/Makefile index 9d14c587e..6d7bbebc2 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -16,7 +16,6 @@ WIRE_HEADERS := wire/onion_defs.h \ # We don't include peer_printgen/onion_printgen here since most don't need it. WIRE_SRC := wire/wire_sync.c \ wire/wire_io.c \ - wire/wire_dummy.c \ wire/fromwire.c \ wire/peer_wire.c \ wire/tlvstream.c \ diff --git a/wire/common_wiregen.c b/wire/common_wiregen.c index 20e49af61..29531a683 100644 --- a/wire/common_wiregen.c +++ b/wire/common_wiregen.c @@ -100,4 +100,4 @@ bool fromwire_custommsg_out(const tal_t *ctx, const void *p, u8 **msg) fromwire_u8_array(&cursor, &plen, *msg, msg_len); return cursor != NULL; } -// SHA256STAMP:4158cef8360d59eb4078b0e19c0903c978ca224f59cb036dbc3276260b529fea +// SHA256STAMP:c32984d62bcfe143788726cdbc7f82290c83a566f0f58f9394f6b2298f819b9f diff --git a/wire/common_wiregen.h b/wire/common_wiregen.h index b4a1dc396..193a85e3d 100644 --- a/wire/common_wiregen.h +++ b/wire/common_wiregen.h @@ -41,4 +41,4 @@ bool fromwire_custommsg_out(const tal_t *ctx, const void *p, u8 **msg); #endif /* LIGHTNING_WIRE_COMMON_WIREGEN_H */ -// SHA256STAMP:4158cef8360d59eb4078b0e19c0903c978ca224f59cb036dbc3276260b529fea +// SHA256STAMP:c32984d62bcfe143788726cdbc7f82290c83a566f0f58f9394f6b2298f819b9f diff --git a/wire/extracted_onion_exp_1b1c9a71038bd72453cabefd3ace17ce8b8dd96e.patch b/wire/extracted_onion_01_offers.patch similarity index 79% rename from wire/extracted_onion_exp_1b1c9a71038bd72453cabefd3ace17ce8b8dd96e.patch rename to wire/extracted_onion_01_offers.patch index 3b8ebbec8..89b85f399 100644 --- a/wire/extracted_onion_exp_1b1c9a71038bd72453cabefd3ace17ce8b8dd96e.patch +++ b/wire/extracted_onion_01_offers.patch @@ -1,6 +1,6 @@ --- wire/extracted_onion_wire_csv 2020-03-25 10:24:12.861645774 +1030 +++ - 2020-03-26 13:47:13.498294435 +1030 -@@ -8,6 +8,25 @@ +@@ -8,6 +8,31 @@ tlvtype,tlv_payload,payment_data,8 tlvdata,tlv_payload,payment_data,payment_secret,byte,32 tlvdata,tlv_payload,payment_data,total_msat,tu64, @@ -15,6 +15,12 @@ +tlvdata,onionmsg_payload,enctlv,enctlv,byte,... +tlvtype,onionmsg_payload,blinding,12 +tlvdata,onionmsg_payload,blinding,blinding,point, ++tlvtype,onionmsg_payload,invoice_request,64 ++tlvdata,onionmsg_payload,invoice_request,invoice_request,byte,... ++tlvtype,onionmsg_payload,invoice,66 ++tlvdata,onionmsg_payload,invoice,invoice,byte,... ++tlvtype,onionmsg_payload,invoice_error,68 ++tlvdata,onionmsg_payload,invoice_error,invoice_error,byte,... +tlvtype,encmsg_tlvs,next_node_id,4 +tlvdata,encmsg_tlvs,next_node_id,node_id,point, +tlvtype,encmsg_tlvs,next_short_channel_id,6 diff --git a/wire/extracted_onion_exp_offers.patch b/wire/extracted_onion_exp_offers.patch deleted file mode 100644 index b0ecfa803..000000000 --- a/wire/extracted_onion_exp_offers.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- wire/onion_exp_wire.csv 2020-11-11 14:14:11.704265950 +1030 -+++ - 2020-11-11 14:14:16.749321565 +1030 -@@ -23,6 +19,12 @@ - tlvdata,onionmsg_payload,enctlv,enctlv,byte,... - tlvtype,onionmsg_payload,blinding,12 - tlvdata,onionmsg_payload,blinding,blinding,point, -+tlvtype,onionmsg_payload,invoice_request,64 -+tlvdata,onionmsg_payload,invoice_request,invoice_request,byte,... -+tlvtype,onionmsg_payload,invoice,66 -+tlvdata,onionmsg_payload,invoice,invoice,byte,... -+tlvtype,onionmsg_payload,invoice_error,68 -+tlvdata,onionmsg_payload,invoice_error,invoice_error,byte,... - tlvtype,encmsg_tlvs,next_node_id,4 - tlvdata,encmsg_tlvs,next_node_id,node_id,point, - tlvtype,encmsg_tlvs,next_short_channel_id,6 diff --git a/wire/extracted_peer_exp_1b1c9a71038bd72453cabefd3ace17ce8b8dd96e.patch b/wire/extracted_peer_01_offers.patch similarity index 83% rename from wire/extracted_peer_exp_1b1c9a71038bd72453cabefd3ace17ce8b8dd96e.patch rename to wire/extracted_peer_01_offers.patch index 2cb91f2f9..b816a2c1e 100644 --- a/wire/extracted_peer_exp_1b1c9a71038bd72453cabefd3ace17ce8b8dd96e.patch +++ b/wire/extracted_peer_01_offers.patch @@ -1,11 +1,12 @@ --- wire/extracted_peer_wire_csv 2020-03-11 10:30:35.744376417 +1030 +++ - 2020-03-26 13:47:13.409755567 +1030 -@@ -211,3 +211,8 @@ +@@ -211,3 +211,9 @@ msgdata,gossip_timestamp_filter,chain_hash,chain_hash, msgdata,gossip_timestamp_filter,first_timestamp,u32, msgdata,gossip_timestamp_filter,timestamp_range,u32, +msgtype,onion_message,385,option_onion_messages -+msgdata,onion_message,onionmsg,byte,1366 ++msgdata,onion_message,len,u16, ++msgdata,onion_message,onionmsg,byte,len +msgdata,onion_message,onion_message_tlvs,onion_message_tlvs, +tlvtype,onion_message_tlvs,blinding,2 +tlvdata,onion_message_tlvs,blinding,blinding,point, diff --git a/wire/extracted_peer_exp_varonionmessage.patch b/wire/extracted_peer_exp_varonionmessage.patch deleted file mode 100644 index fda5f2eae..000000000 --- a/wire/extracted_peer_exp_varonionmessage.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- wire/peer_exp_wire.csv 2020-12-07 14:17:07.322636209 +1030 -+++ - 2020-12-08 11:05:50.990733421 +1030 -@@ -310,7 +211,8 @@ - msgdata,gossip_timestamp_filter,first_timestamp,u32, - msgdata,gossip_timestamp_filter,timestamp_range,u32, - msgtype,onion_message,385,option_onion_messages --msgdata,onion_message,onionmsg,byte,1366 -+msgdata,onion_message,len,u16, -+msgdata,onion_message,onionmsg,byte,len - msgdata,onion_message,onion_message_tlvs,onion_message_tlvs, - tlvtype,onion_message_tlvs,blinding,2 - tlvdata,onion_message_tlvs,blinding,blinding,point, diff --git a/wire/onion_printgen.c b/wire/onion_printgen.c index 403de5f1e..091545315 100644 --- a/wire/onion_printgen.c +++ b/wire/onion_printgen.c @@ -106,6 +106,33 @@ void printonion_wire_message(const u8 *msg) } +void printwire_onionmsg_path(const char *fieldname, const u8 **cursor, size_t *plen) +{ + + printf("node_id="); + struct pubkey node_id; + fromwire_pubkey(cursor, plen, &node_id); + + printwire_pubkey(tal_fmt(NULL, "%s.node_id", fieldname), &node_id); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + u16 enclen = fromwire_u16(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + printf("enctlv="); + printwire_u8_array(tal_fmt(NULL, "%s.enctlv", fieldname), cursor, plen, enclen); + + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} + static void printwire_tlv_tlv_payload_amt_to_forward(const char *fieldname, const u8 **cursor, size_t *plen) { printf("(msg_name=%s)\n", "amt_to_forward"); @@ -179,6 +206,179 @@ static const struct tlv_print_record_type print_tlvs_tlv_payload[] = { { 6, printwire_tlv_tlv_payload_short_channel_id }, { 8, printwire_tlv_tlv_payload_payment_data }, }; + +static void printwire_tlv_onionmsg_payload_next_node_id(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "next_node_id"); + + printf("node_id="); + struct pubkey node_id; + fromwire_pubkey(cursor, plen, &node_id); + + printwire_pubkey(tal_fmt(NULL, "%s.node_id", fieldname), &node_id); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_onionmsg_payload_next_short_channel_id(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "next_short_channel_id"); + + printf("short_channel_id="); + struct short_channel_id short_channel_id; + fromwire_short_channel_id(cursor, plen, &short_channel_id); + + printwire_short_channel_id(tal_fmt(NULL, "%s.short_channel_id", fieldname), &short_channel_id); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_onionmsg_payload_reply_path(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "reply_path"); + + printf("blinding="); + struct pubkey blinding; + fromwire_pubkey(cursor, plen, &blinding); + + printwire_pubkey(tal_fmt(NULL, "%s.blinding", fieldname), &blinding); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + printf("path="); + printf("["); + for (size_t i = 0; i < *plen; i++) { + printf("{\n"); + printwire_onionmsg_path(tal_fmt(NULL, "%s.path", fieldname), cursor, plen); + printf("}\n"); + } + printf("]"); + + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_onionmsg_payload_enctlv(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "enctlv"); + + printf("enctlv="); + printwire_u8_array(tal_fmt(NULL, "%s.enctlv", fieldname), cursor, plen, *plen); + + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_onionmsg_payload_blinding(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "blinding"); + + printf("blinding="); + struct pubkey blinding; + fromwire_pubkey(cursor, plen, &blinding); + + printwire_pubkey(tal_fmt(NULL, "%s.blinding", fieldname), &blinding); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_onionmsg_payload_invoice_request(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "invoice_request"); + + printf("invoice_request="); + printwire_u8_array(tal_fmt(NULL, "%s.invoice_request", fieldname), cursor, plen, *plen); + + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_onionmsg_payload_invoice(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "invoice"); + + printf("invoice="); + printwire_u8_array(tal_fmt(NULL, "%s.invoice", fieldname), cursor, plen, *plen); + + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_onionmsg_payload_invoice_error(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "invoice_error"); + + printf("invoice_error="); + printwire_u8_array(tal_fmt(NULL, "%s.invoice_error", fieldname), cursor, plen, *plen); + + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} + +static const struct tlv_print_record_type print_tlvs_onionmsg_payload[] = { + { 4, printwire_tlv_onionmsg_payload_next_node_id }, + { 6, printwire_tlv_onionmsg_payload_next_short_channel_id }, + { 8, printwire_tlv_onionmsg_payload_reply_path }, + { 10, printwire_tlv_onionmsg_payload_enctlv }, + { 12, printwire_tlv_onionmsg_payload_blinding }, + { 64, printwire_tlv_onionmsg_payload_invoice_request }, + { 66, printwire_tlv_onionmsg_payload_invoice }, + { 68, printwire_tlv_onionmsg_payload_invoice_error }, +}; + +static void printwire_tlv_encmsg_tlvs_next_node_id(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "next_node_id"); + + printf("node_id="); + struct pubkey node_id; + fromwire_pubkey(cursor, plen, &node_id); + + printwire_pubkey(tal_fmt(NULL, "%s.node_id", fieldname), &node_id); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} +static void printwire_tlv_encmsg_tlvs_next_short_channel_id(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "next_short_channel_id"); + + printf("short_channel_id="); + struct short_channel_id short_channel_id; + fromwire_short_channel_id(cursor, plen, &short_channel_id); + + printwire_short_channel_id(tal_fmt(NULL, "%s.short_channel_id", fieldname), &short_channel_id); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} + +static const struct tlv_print_record_type print_tlvs_encmsg_tlvs[] = { + { 4, printwire_tlv_encmsg_tlvs_next_node_id }, + { 6, printwire_tlv_encmsg_tlvs_next_short_channel_id }, +}; void printwire_invalid_realm(const char *fieldname, const u8 *cursor) { @@ -652,5 +852,11 @@ void printonion_wire_tlv_message(const char *tlv_name, const u8 *msg) { if (strcmp(tlv_name, "tlv_payload") == 0) { printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_tlv_payload, ARRAY_SIZE(print_tlvs_tlv_payload)); } + if (strcmp(tlv_name, "onionmsg_payload") == 0) { + printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_onionmsg_payload, ARRAY_SIZE(print_tlvs_onionmsg_payload)); + } + if (strcmp(tlv_name, "encmsg_tlvs") == 0) { + printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_encmsg_tlvs, ARRAY_SIZE(print_tlvs_encmsg_tlvs)); + } } -// SHA256STAMP:00d8601fa1d48cbbe518bd3ca041bccd1d586c82d65db44fc8530d5ce6fa3705 +// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 diff --git a/wire/onion_printgen.h b/wire/onion_printgen.h index 09e5e8287..dc23db5f1 100644 --- a/wire/onion_printgen.h +++ b/wire/onion_printgen.h @@ -56,5 +56,6 @@ void printwire_invalid_onion_payload(const char *fieldname, const u8 *cursor); void printwire_mpp_timeout(const char *fieldname, const u8 *cursor); +void printwire_onionmsg_path(const char *fieldname, const u8 **cursor, size_t *plen); #endif /* LIGHTNING_WIRE_ONION_PRINTGEN_H */ -// SHA256STAMP:00d8601fa1d48cbbe518bd3ca041bccd1d586c82d65db44fc8530d5ce6fa3705 +// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 diff --git a/wire/onion_wire.csv b/wire/onion_wire.csv index e56518c39..31e7607b3 100644 --- a/wire/onion_wire.csv +++ b/wire/onion_wire.csv @@ -8,6 +8,31 @@ tlvdata,tlv_payload,short_channel_id,short_channel_id,short_channel_id, tlvtype,tlv_payload,payment_data,8 tlvdata,tlv_payload,payment_data,payment_secret,byte,32 tlvdata,tlv_payload,payment_data,total_msat,tu64, +tlvtype,onionmsg_payload,next_node_id,4 +tlvdata,onionmsg_payload,next_node_id,node_id,point, +tlvtype,onionmsg_payload,next_short_channel_id,6 +tlvdata,onionmsg_payload,next_short_channel_id,short_channel_id,short_channel_id, +tlvtype,onionmsg_payload,reply_path,8 +tlvdata,onionmsg_payload,reply_path,blinding,point, +tlvdata,onionmsg_payload,reply_path,path,onionmsg_path,... +tlvtype,onionmsg_payload,enctlv,10 +tlvdata,onionmsg_payload,enctlv,enctlv,byte,... +tlvtype,onionmsg_payload,blinding,12 +tlvdata,onionmsg_payload,blinding,blinding,point, +tlvtype,onionmsg_payload,invoice_request,64 +tlvdata,onionmsg_payload,invoice_request,invoice_request,byte,... +tlvtype,onionmsg_payload,invoice,66 +tlvdata,onionmsg_payload,invoice,invoice,byte,... +tlvtype,onionmsg_payload,invoice_error,68 +tlvdata,onionmsg_payload,invoice_error,invoice_error,byte,... +tlvtype,encmsg_tlvs,next_node_id,4 +tlvdata,encmsg_tlvs,next_node_id,node_id,point, +tlvtype,encmsg_tlvs,next_short_channel_id,6 +tlvdata,encmsg_tlvs,next_short_channel_id,short_channel_id,short_channel_id, +subtype,onionmsg_path +subtypedata,onionmsg_path,node_id,point, +subtypedata,onionmsg_path,enclen,u16, +subtypedata,onionmsg_path,enctlv,byte,enclen msgtype,invalid_realm,PERM|1 msgtype,temporary_node_failure,NODE|2 msgtype,permanent_node_failure,PERM|NODE|2 diff --git a/wire/onion_wiregen.c b/wire/onion_wiregen.c index 9d0934110..f0cd9ce09 100644 --- a/wire/onion_wiregen.c +++ b/wire/onion_wiregen.c @@ -81,6 +81,29 @@ bool onion_wire_is_defined(u16 type) +/* SUBTYPE: ONIONMSG_PATH */ +void towire_onionmsg_path(u8 **p, const struct onionmsg_path *onionmsg_path) +{ + u16 enclen = tal_count(onionmsg_path->enctlv); + + towire_pubkey(p, &onionmsg_path->node_id); + towire_u16(p, enclen); + towire_u8_array(p, onionmsg_path->enctlv, enclen); +} +struct onionmsg_path * +fromwire_onionmsg_path(const tal_t *ctx, const u8 **cursor, size_t *plen) +{ + struct onionmsg_path *onionmsg_path = tal(ctx, struct onionmsg_path); + u16 enclen; + + fromwire_pubkey(cursor, plen, &onionmsg_path->node_id); + enclen = fromwire_u16(cursor, plen); + onionmsg_path->enctlv = enclen ? tal_arr(onionmsg_path, u8, enclen) : NULL; +fromwire_u8_array(cursor, plen, onionmsg_path->enctlv, enclen); + + return onionmsg_path; +} + struct tlv_tlv_payload *tlv_tlv_payload_new(const tal_t *ctx) { @@ -211,6 +234,312 @@ bool tlv_payload_is_valid(const struct tlv_tlv_payload *record, size_t *err_inde } +struct tlv_onionmsg_payload *tlv_onionmsg_payload_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_onionmsg_payload *inst = talz(ctx, struct tlv_onionmsg_payload); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* ONIONMSG_PAYLOAD MSG: next_node_id */ +static u8 *towire_tlv_onionmsg_payload_next_node_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->next_node_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey(&ptr, r->next_node_id); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_next_node_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->next_node_id = tal(r, struct pubkey); + +fromwire_pubkey(cursor, plen, &*r->next_node_id); +} +/* ONIONMSG_PAYLOAD MSG: next_short_channel_id */ +static u8 *towire_tlv_onionmsg_payload_next_short_channel_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->next_short_channel_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_short_channel_id(&ptr, r->next_short_channel_id); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_next_short_channel_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->next_short_channel_id = tal(r, struct short_channel_id); + +fromwire_short_channel_id(cursor, plen, &*r->next_short_channel_id); +} +/* ONIONMSG_PAYLOAD MSG: reply_path */ +static u8 *towire_tlv_onionmsg_payload_reply_path(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->reply_path) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey(&ptr, &r->reply_path->blinding); + + for (size_t i = 0; i < tal_count(r->reply_path->path); i++) + towire_onionmsg_path(&ptr, r->reply_path->path[i]); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_reply_path(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->reply_path = tal(r, struct tlv_onionmsg_payload_reply_path); + fromwire_pubkey(cursor, plen, &r->reply_path->blinding); + r->reply_path->path = *plen ? tal_arr(r->reply_path, struct onionmsg_path *, 0) : NULL; + for (size_t i = 0; *plen != 0; i++) { + struct onionmsg_path * tmp; + tmp = fromwire_onionmsg_path(r->reply_path, cursor, plen); + tal_arr_expand(&r->reply_path->path, tmp); + } +} +/* ONIONMSG_PAYLOAD MSG: enctlv */ +static u8 *towire_tlv_onionmsg_payload_enctlv(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->enctlv) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->enctlv, tal_count(r->enctlv)); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_enctlv(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->enctlv = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->enctlv, *plen); +} +/* ONIONMSG_PAYLOAD MSG: blinding */ +static u8 *towire_tlv_onionmsg_payload_blinding(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->blinding) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey(&ptr, r->blinding); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_blinding(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->blinding = tal(r, struct pubkey); + +fromwire_pubkey(cursor, plen, &*r->blinding); +} +/* ONIONMSG_PAYLOAD MSG: invoice_request */ +static u8 *towire_tlv_onionmsg_payload_invoice_request(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->invoice_request) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->invoice_request, tal_count(r->invoice_request)); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_invoice_request(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->invoice_request = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->invoice_request, *plen); +} +/* ONIONMSG_PAYLOAD MSG: invoice */ +static u8 *towire_tlv_onionmsg_payload_invoice(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->invoice) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->invoice, tal_count(r->invoice)); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_invoice(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->invoice = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->invoice, *plen); +} +/* ONIONMSG_PAYLOAD MSG: invoice_error */ +static u8 *towire_tlv_onionmsg_payload_invoice_error(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onionmsg_payload *r = vrecord; + u8 *ptr; + + if (!r->invoice_error) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->invoice_error, tal_count(r->invoice_error)); + return ptr; +} +static void fromwire_tlv_onionmsg_payload_invoice_error(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onionmsg_payload *r = vrecord; + + r->invoice_error = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->invoice_error, *plen); +} + +static const struct tlv_record_type tlvs_onionmsg_payload[] = { + { 4, towire_tlv_onionmsg_payload_next_node_id, fromwire_tlv_onionmsg_payload_next_node_id }, + { 6, towire_tlv_onionmsg_payload_next_short_channel_id, fromwire_tlv_onionmsg_payload_next_short_channel_id }, + { 8, towire_tlv_onionmsg_payload_reply_path, fromwire_tlv_onionmsg_payload_reply_path }, + { 10, towire_tlv_onionmsg_payload_enctlv, fromwire_tlv_onionmsg_payload_enctlv }, + { 12, towire_tlv_onionmsg_payload_blinding, fromwire_tlv_onionmsg_payload_blinding }, + { 64, towire_tlv_onionmsg_payload_invoice_request, fromwire_tlv_onionmsg_payload_invoice_request }, + { 66, towire_tlv_onionmsg_payload_invoice, fromwire_tlv_onionmsg_payload_invoice }, + { 68, towire_tlv_onionmsg_payload_invoice_error, fromwire_tlv_onionmsg_payload_invoice_error }, +}; + +void towire_onionmsg_payload(u8 **pptr, const struct tlv_onionmsg_payload *record) +{ + towire_tlv(pptr, tlvs_onionmsg_payload, 8, record); +} + + +bool fromwire_onionmsg_payload(const u8 **cursor, size_t *max, struct tlv_onionmsg_payload *record) +{ + return fromwire_tlv(cursor, max, tlvs_onionmsg_payload, 8, record, &record->fields); +} + +bool onionmsg_payload_is_valid(const struct tlv_onionmsg_payload *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, err_index); +} + + +struct tlv_encmsg_tlvs *tlv_encmsg_tlvs_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_encmsg_tlvs *inst = talz(ctx, struct tlv_encmsg_tlvs); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* ENCMSG_TLVS MSG: next_node_id */ +static u8 *towire_tlv_encmsg_tlvs_next_node_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_encmsg_tlvs *r = vrecord; + u8 *ptr; + + if (!r->next_node_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey(&ptr, r->next_node_id); + return ptr; +} +static void fromwire_tlv_encmsg_tlvs_next_node_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_encmsg_tlvs *r = vrecord; + + r->next_node_id = tal(r, struct pubkey); + +fromwire_pubkey(cursor, plen, &*r->next_node_id); +} +/* ENCMSG_TLVS MSG: next_short_channel_id */ +static u8 *towire_tlv_encmsg_tlvs_next_short_channel_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_encmsg_tlvs *r = vrecord; + u8 *ptr; + + if (!r->next_short_channel_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_short_channel_id(&ptr, r->next_short_channel_id); + return ptr; +} +static void fromwire_tlv_encmsg_tlvs_next_short_channel_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_encmsg_tlvs *r = vrecord; + + r->next_short_channel_id = tal(r, struct short_channel_id); + +fromwire_short_channel_id(cursor, plen, &*r->next_short_channel_id); +} + +static const struct tlv_record_type tlvs_encmsg_tlvs[] = { + { 4, towire_tlv_encmsg_tlvs_next_node_id, fromwire_tlv_encmsg_tlvs_next_node_id }, + { 6, towire_tlv_encmsg_tlvs_next_short_channel_id, fromwire_tlv_encmsg_tlvs_next_short_channel_id }, +}; + +void towire_encmsg_tlvs(u8 **pptr, const struct tlv_encmsg_tlvs *record) +{ + towire_tlv(pptr, tlvs_encmsg_tlvs, 2, record); +} + + +bool fromwire_encmsg_tlvs(const u8 **cursor, size_t *max, struct tlv_encmsg_tlvs *record) +{ + return fromwire_tlv(cursor, max, tlvs_encmsg_tlvs, 2, record, &record->fields); +} + +bool encmsg_tlvs_is_valid(const struct tlv_encmsg_tlvs *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, err_index); +} + + /* WIRE: INVALID_REALM */ u8 *towire_invalid_realm(const tal_t *ctx) { @@ -697,4 +1026,4 @@ bool fromwire_mpp_timeout(const void *p) return false; return cursor != NULL; } -// SHA256STAMP:00d8601fa1d48cbbe518bd3ca041bccd1d586c82d65db44fc8530d5ce6fa3705 +// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 diff --git a/wire/onion_wiregen.h b/wire/onion_wiregen.h index 9de4e44a8..365997cf8 100644 --- a/wire/onion_wiregen.h +++ b/wire/onion_wiregen.h @@ -51,10 +51,18 @@ const char *onion_wire_name(int e); */ bool onion_wire_is_defined(u16 type); +struct onionmsg_path { + struct pubkey node_id; + u8 *enctlv; +}; struct tlv_tlv_payload_payment_data { struct secret payment_secret; u64 total_msat; }; +struct tlv_onionmsg_payload_reply_path { + struct pubkey blinding; + struct onionmsg_path **path; +}; struct tlv_tlv_payload { /* Raw fields including unknown ones. */ struct tlv_field *fields; @@ -66,6 +74,30 @@ struct tlv_tlv_payload { struct short_channel_id *short_channel_id; struct tlv_tlv_payload_payment_data *payment_data; }; +struct tlv_onionmsg_payload { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + struct pubkey *next_node_id; + struct short_channel_id *next_short_channel_id; + struct tlv_onionmsg_payload_reply_path *reply_path; + u8 *enctlv; + struct pubkey *blinding; + u8 *invoice_request; + u8 *invoice; + u8 *invoice_error; +}; +struct tlv_encmsg_tlvs { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + struct pubkey *next_node_id; + struct short_channel_id *next_short_channel_id; +}; struct tlv_tlv_payload *tlv_tlv_payload_new(const tal_t *ctx); @@ -117,6 +149,84 @@ enum tlv_payload_types { TLV_TLV_PAYLOAD_PAYMENT_DATA = 8, }; +struct tlv_onionmsg_payload *tlv_onionmsg_payload_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the onionmsg_payload namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using onionmsg_payload_is_valid. + */ +bool fromwire_onionmsg_payload(const u8 **cursor, size_t *max, + struct tlv_onionmsg_payload * record); + +/** + * Serialize a TLV stream for the onionmsg_payload namespace. + * + * This function only considers known fields from the onionmsg_payload namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `onionmsg_payload_is_valid`. + */ +void towire_onionmsg_payload(u8 **pptr, const struct tlv_onionmsg_payload *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool onionmsg_payload_is_valid(const struct tlv_onionmsg_payload *record, + size_t *err_index); + +struct tlv_encmsg_tlvs *tlv_encmsg_tlvs_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the encmsg_tlvs namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using encmsg_tlvs_is_valid. + */ +bool fromwire_encmsg_tlvs(const u8 **cursor, size_t *max, + struct tlv_encmsg_tlvs * record); + +/** + * Serialize a TLV stream for the encmsg_tlvs namespace. + * + * This function only considers known fields from the encmsg_tlvs namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `encmsg_tlvs_is_valid`. + */ +void towire_encmsg_tlvs(u8 **pptr, const struct tlv_encmsg_tlvs *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool encmsg_tlvs_is_valid(const struct tlv_encmsg_tlvs *record, + size_t *err_index); + +/* SUBTYPE: ONIONMSG_PATH */ +void towire_onionmsg_path(u8 **p, const struct onionmsg_path *onionmsg_path); +struct onionmsg_path *fromwire_onionmsg_path(const tal_t *ctx, const u8 **cursor, size_t *plen); + /* WIRE: INVALID_REALM */ u8 *towire_invalid_realm(const tal_t *ctx); bool fromwire_invalid_realm(const void *p); @@ -207,4 +317,4 @@ bool fromwire_mpp_timeout(const void *p); #endif /* LIGHTNING_WIRE_ONION_WIREGEN_H */ -// SHA256STAMP:00d8601fa1d48cbbe518bd3ca041bccd1d586c82d65db44fc8530d5ce6fa3705 +// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 diff --git a/wire/peer_printgen.c b/wire/peer_printgen.c index 5c607aa6c..5ab0bf557 100644 --- a/wire/peer_printgen.c +++ b/wire/peer_printgen.c @@ -124,6 +124,10 @@ void printpeer_wire_message(const u8 *msg) printf("WIRE_GOSSIP_TIMESTAMP_FILTER:\n"); printwire_gossip_timestamp_filter("gossip_timestamp_filter", msg); return; + case WIRE_ONION_MESSAGE: + printf("WIRE_ONION_MESSAGE:\n"); + printwire_onion_message("onion_message", msg); + return; } printf("UNKNOWN: %s\\n", tal_hex(msg, msg)); @@ -444,6 +448,26 @@ static const struct tlv_print_record_type print_tlvs_reply_channel_range_tlvs[] { 1, printwire_tlv_reply_channel_range_tlvs_timestamps_tlv }, { 3, printwire_tlv_reply_channel_range_tlvs_checksums_tlv }, }; + +static void printwire_tlv_onion_message_tlvs_blinding(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "blinding"); + + printf("blinding="); + struct pubkey blinding; + fromwire_pubkey(cursor, plen, &blinding); + + printwire_pubkey(tal_fmt(NULL, "%s.blinding", fieldname), &blinding); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} + +static const struct tlv_print_record_type print_tlvs_onion_message_tlvs[] = { + { 2, printwire_tlv_onion_message_tlvs_blinding }, +}; void printwire_init(const char *fieldname, const u8 *cursor) { @@ -2005,6 +2029,34 @@ void printwire_gossip_timestamp_filter(const char *fieldname, const u8 *cursor) } + if (plen != 0) + printf("EXTRA: %s\n", tal_hexstr(NULL, cursor, plen)); +} +void printwire_onion_message(const char *fieldname, const u8 *cursor) +{ + + size_t plen = tal_count(cursor); + if (fromwire_u16(&cursor, &plen) != WIRE_ONION_MESSAGE) { + printf("WRONG TYPE?!\n"); + return; + } + + u16 len = fromwire_u16(&cursor, &plen); + if (!cursor) { + printf("**TRUNCATED**\n"); + return; + } + printf("onionmsg="); + printwire_u8_array(tal_fmt(NULL, "%s.onionmsg", fieldname), &cursor, &plen, len); + + if (!cursor) { + printf("**TRUNCATED**\n"); + return; + } + printf("onion_message_tlvs="); + printwire_tlvs(tal_fmt(NULL, "%s.onion_message_tlvs", fieldname), &cursor, &plen, print_tlvs_onion_message_tlvs, ARRAY_SIZE(print_tlvs_onion_message_tlvs)); + + if (plen != 0) printf("EXTRA: %s\n", tal_hexstr(NULL, cursor, plen)); } @@ -2035,5 +2087,8 @@ void printpeer_wire_tlv_message(const char *tlv_name, const u8 *msg) { if (strcmp(tlv_name, "reply_channel_range_tlvs") == 0) { printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_reply_channel_range_tlvs, ARRAY_SIZE(print_tlvs_reply_channel_range_tlvs)); } + if (strcmp(tlv_name, "onion_message_tlvs") == 0) { + printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_onion_message_tlvs, ARRAY_SIZE(print_tlvs_onion_message_tlvs)); + } } -// SHA256STAMP:efe21d89eef0b58216ab945b85cfbf5fcee08cf783ad4ef4c45501f1a10ac7ef +// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 diff --git a/wire/peer_printgen.h b/wire/peer_printgen.h index f040fd196..a4066325a 100644 --- a/wire/peer_printgen.h +++ b/wire/peer_printgen.h @@ -66,8 +66,10 @@ void printwire_reply_channel_range(const char *fieldname, const u8 *cursor); void printwire_gossip_timestamp_filter(const char *fieldname, const u8 *cursor); +void printwire_onion_message(const char *fieldname, const u8 *cursor); + void printwire_channel_update_checksums(const char *fieldname, const u8 **cursor, size_t *plen); void printwire_channel_update_timestamps(const char *fieldname, const u8 **cursor, size_t *plen); #endif /* LIGHTNING_WIRE_PEER_PRINTGEN_H */ -// SHA256STAMP:efe21d89eef0b58216ab945b85cfbf5fcee08cf783ad4ef4c45501f1a10ac7ef +// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 diff --git a/wire/peer_wire.c b/wire/peer_wire.c index a2602cc78..2581d3ead 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -32,8 +32,8 @@ static bool unknown_type(enum peer_wire t) case WIRE_QUERY_CHANNEL_RANGE: case WIRE_REPLY_CHANNEL_RANGE: case WIRE_GOSSIP_TIMESTAMP_FILTER: -#if EXPERIMENTAL_FEATURES case WIRE_ONION_MESSAGE: +#if EXPERIMENTAL_FEATURES case WIRE_TX_ADD_INPUT: case WIRE_TX_REMOVE_INPUT: case WIRE_TX_ADD_OUTPUT: @@ -62,9 +62,7 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_REPLY_CHANNEL_RANGE: case WIRE_PING: case WIRE_PONG: -#if EXPERIMENTAL_FEATURES case WIRE_ONION_MESSAGE: -#endif return true; case WIRE_INIT: case WIRE_ERROR: diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index cf9d59621..01061d9fc 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -210,3 +210,9 @@ msgtype,gossip_timestamp_filter,265,gossip_queries msgdata,gossip_timestamp_filter,chain_hash,chain_hash, msgdata,gossip_timestamp_filter,first_timestamp,u32, msgdata,gossip_timestamp_filter,timestamp_range,u32, +msgtype,onion_message,385,option_onion_messages +msgdata,onion_message,len,u16, +msgdata,onion_message,onionmsg,byte,len +msgdata,onion_message,onion_message_tlvs,onion_message_tlvs, +tlvtype,onion_message_tlvs,blinding,2 +tlvdata,onion_message_tlvs,blinding,blinding,point, diff --git a/wire/peer_wiregen.c b/wire/peer_wiregen.c index 9ae69aabe..dc50a6878 100644 --- a/wire/peer_wiregen.c +++ b/wire/peer_wiregen.c @@ -48,6 +48,7 @@ const char *peer_wire_name(int e) case WIRE_QUERY_CHANNEL_RANGE: return "WIRE_QUERY_CHANNEL_RANGE"; case WIRE_REPLY_CHANNEL_RANGE: return "WIRE_REPLY_CHANNEL_RANGE"; case WIRE_GOSSIP_TIMESTAMP_FILTER: return "WIRE_GOSSIP_TIMESTAMP_FILTER"; + case WIRE_ONION_MESSAGE: return "WIRE_ONION_MESSAGE"; } snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); @@ -85,6 +86,7 @@ bool peer_wire_is_defined(u16 type) case WIRE_QUERY_CHANNEL_RANGE:; case WIRE_REPLY_CHANNEL_RANGE:; case WIRE_GOSSIP_TIMESTAMP_FILTER:; + case WIRE_ONION_MESSAGE:; return true; } return false; @@ -699,6 +701,61 @@ bool reply_channel_range_tlvs_is_valid(const struct tlv_reply_channel_range_tlvs } +struct tlv_onion_message_tlvs *tlv_onion_message_tlvs_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_onion_message_tlvs *inst = talz(ctx, struct tlv_onion_message_tlvs); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* ONION_MESSAGE_TLVS MSG: blinding */ +static u8 *towire_tlv_onion_message_tlvs_blinding(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_onion_message_tlvs *r = vrecord; + u8 *ptr; + + if (!r->blinding) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey(&ptr, r->blinding); + return ptr; +} +static void fromwire_tlv_onion_message_tlvs_blinding(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_onion_message_tlvs *r = vrecord; + + r->blinding = tal(r, struct pubkey); + +fromwire_pubkey(cursor, plen, &*r->blinding); +} + +static const struct tlv_record_type tlvs_onion_message_tlvs[] = { + { 2, towire_tlv_onion_message_tlvs_blinding, fromwire_tlv_onion_message_tlvs_blinding }, +}; + +void towire_onion_message_tlvs(u8 **pptr, const struct tlv_onion_message_tlvs *record) +{ + towire_tlv(pptr, tlvs_onion_message_tlvs, 1, record); +} + + +bool fromwire_onion_message_tlvs(const u8 **cursor, size_t *max, struct tlv_onion_message_tlvs *record) +{ + return fromwire_tlv(cursor, max, tlvs_onion_message_tlvs, 1, record, &record->fields); +} + +bool onion_message_tlvs_is_valid(const struct tlv_onion_message_tlvs *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, err_index); +} + + /* WIRE: INIT */ u8 *towire_init(const tal_t *ctx, const u8 *globalfeatures, const u8 *features, const struct tlv_init_tlvs *tlvs) { @@ -1590,6 +1647,36 @@ bool fromwire_gossip_timestamp_filter(const void *p, struct bitcoin_blkid *chain return cursor != NULL; } +/* WIRE: ONION_MESSAGE */ +u8 *towire_onion_message(const tal_t *ctx, const u8 *onionmsg, const struct tlv_onion_message_tlvs *onion_message_tlvs) +{ + u16 len = tal_count(onionmsg); + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_ONION_MESSAGE); + towire_u16(&p, len); + towire_u8_array(&p, onionmsg, len); + towire_onion_message_tlvs(&p, onion_message_tlvs); + + return memcheck(p, tal_count(p)); +} +bool fromwire_onion_message(const tal_t *ctx, const void *p, u8 **onionmsg, struct tlv_onion_message_tlvs *onion_message_tlvs) +{ + u16 len; + + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_ONION_MESSAGE) + return false; + len = fromwire_u16(&cursor, &plen); + // 2nd case onionmsg + *onionmsg = len ? tal_arr(ctx, u8, len) : NULL; + fromwire_u8_array(&cursor, &plen, *onionmsg, len); + fromwire_onion_message_tlvs(&cursor, &plen, onion_message_tlvs); + return cursor != NULL; +} + /* WIRE: CHANNEL_UPDATE_OPTION_CHANNEL_HTLC_MAX */ u8 *towire_channel_update_option_channel_htlc_max(const tal_t *ctx, const secp256k1_ecdsa_signature *signature, const struct bitcoin_blkid *chain_hash, const struct short_channel_id *short_channel_id, u32 timestamp, u8 message_flags, u8 channel_flags, u16 cltv_expiry_delta, struct amount_msat htlc_minimum_msat, u32 fee_base_msat, u32 fee_proportional_millionths, struct amount_msat htlc_maximum_msat) { @@ -1630,4 +1717,4 @@ bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ec *htlc_maximum_msat = fromwire_amount_msat(&cursor, &plen); return cursor != NULL; } -// SHA256STAMP:efe21d89eef0b58216ab945b85cfbf5fcee08cf783ad4ef4c45501f1a10ac7ef +// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 diff --git a/wire/peer_wiregen.h b/wire/peer_wiregen.h index 93ddb7e72..1127f9a4c 100644 --- a/wire/peer_wiregen.h +++ b/wire/peer_wiregen.h @@ -45,6 +45,7 @@ enum peer_wire { WIRE_QUERY_CHANNEL_RANGE = 263, WIRE_REPLY_CHANNEL_RANGE = 264, WIRE_GOSSIP_TIMESTAMP_FILTER = 265, + WIRE_ONION_MESSAGE = 385, }; const char *peer_wire_name(int e); @@ -148,6 +149,14 @@ struct tlv_reply_channel_range_tlvs { struct tlv_reply_channel_range_tlvs_timestamps_tlv *timestamps_tlv; struct channel_update_checksums *checksums_tlv; }; +struct tlv_onion_message_tlvs { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + struct pubkey *blinding; +}; struct tlv_init_tlvs *tlv_init_tlvs_new(const tal_t *ctx); @@ -469,6 +478,43 @@ void towire_reply_channel_range_tlvs(u8 **pptr, const struct tlv_reply_channel_r bool reply_channel_range_tlvs_is_valid(const struct tlv_reply_channel_range_tlvs *record, size_t *err_index); +struct tlv_onion_message_tlvs *tlv_onion_message_tlvs_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the onion_message_tlvs namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using onion_message_tlvs_is_valid. + */ +bool fromwire_onion_message_tlvs(const u8 **cursor, size_t *max, + struct tlv_onion_message_tlvs * record); + +/** + * Serialize a TLV stream for the onion_message_tlvs namespace. + * + * This function only considers known fields from the onion_message_tlvs namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `onion_message_tlvs_is_valid`. + */ +void towire_onion_message_tlvs(u8 **pptr, const struct tlv_onion_message_tlvs *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool onion_message_tlvs_is_valid(const struct tlv_onion_message_tlvs *record, + size_t *err_index); + /* SUBTYPE: CHANNEL_UPDATE_CHECKSUMS */ void towire_channel_update_checksums(u8 **p, const struct channel_update_checksums *channel_update_checksums); void fromwire_channel_update_checksums(const u8 **cursor, size_t *plen, struct channel_update_checksums *channel_update_checksums); @@ -589,10 +635,14 @@ bool fromwire_reply_channel_range(const tal_t *ctx, const void *p, struct bitcoi u8 *towire_gossip_timestamp_filter(const tal_t *ctx, const struct bitcoin_blkid *chain_hash, u32 first_timestamp, u32 timestamp_range); bool fromwire_gossip_timestamp_filter(const void *p, struct bitcoin_blkid *chain_hash, u32 *first_timestamp, u32 *timestamp_range); +/* WIRE: ONION_MESSAGE */ +u8 *towire_onion_message(const tal_t *ctx, const u8 *onionmsg, const struct tlv_onion_message_tlvs *onion_message_tlvs); +bool fromwire_onion_message(const tal_t *ctx, const void *p, u8 **onionmsg, struct tlv_onion_message_tlvs *onion_message_tlvs); + /* WIRE: CHANNEL_UPDATE_OPTION_CHANNEL_HTLC_MAX */ u8 *towire_channel_update_option_channel_htlc_max(const tal_t *ctx, const secp256k1_ecdsa_signature *signature, const struct bitcoin_blkid *chain_hash, const struct short_channel_id *short_channel_id, u32 timestamp, u8 message_flags, u8 channel_flags, u16 cltv_expiry_delta, struct amount_msat htlc_minimum_msat, u32 fee_base_msat, u32 fee_proportional_millionths, struct amount_msat htlc_maximum_msat); bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ecdsa_signature *signature, struct bitcoin_blkid *chain_hash, struct short_channel_id *short_channel_id, u32 *timestamp, u8 *message_flags, u8 *channel_flags, u16 *cltv_expiry_delta, struct amount_msat *htlc_minimum_msat, u32 *fee_base_msat, u32 *fee_proportional_millionths, struct amount_msat *htlc_maximum_msat); #endif /* LIGHTNING_WIRE_PEER_WIREGEN_H */ -// SHA256STAMP:efe21d89eef0b58216ab945b85cfbf5fcee08cf783ad4ef4c45501f1a10ac7ef +// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 diff --git a/wire/wire_dummy.c b/wire/wire_dummy.c deleted file mode 100644 index 6b824c7b5..000000000 --- a/wire/wire_dummy.c +++ /dev/null @@ -1,15 +0,0 @@ -#include - -#if !EXPERIMENTAL_FEATURES -/* Stubs, as this subtype is only defined when EXPERIMENTAL_FEATURES */ -void towire_onionmsg_path(u8 **p, const struct onionmsg_path *onionmsg_path) -{ - abort(); -} - -struct onionmsg_path * -fromwire_onionmsg_path(const tal_t *ctx, const u8 **cursor, size_t *plen) -{ - abort(); -} -#endif