Skip to content

Commit fdd477d

Browse files
committed
lightningd: Add extra_tlvs to htlc_accepted_hook
Add serializing and deserializing of the extra tlvs to to the htlc_accepted_hook to allow plugin users to replace the tlv stream that is attached to the update_add_htlc message on forwards. Signed-off-by: Peter Neuroth <[email protected]>
1 parent a7aac65 commit fdd477d

File tree

7 files changed

+156
-11
lines changed

7 files changed

+156
-11
lines changed

lightningd/htlc_end.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
#include "ccan/tal/tal.h"
2+
#include "common/utils.h"
13
#include "config.h"
4+
#include "wire/tlvstream.h"
25
#include <ccan/cast/cast.h>
36
#include <ccan/crypto/siphash24/siphash24.h>
47
#include <ccan/tal/str/str.h>
@@ -130,6 +133,7 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
130133
const struct secret *shared_secret TAKES,
131134
const struct pubkey *path_key TAKES,
132135
const u8 *onion_routing_packet,
136+
const struct tlv_field *extra_tlvs,
133137
bool fail_immediate)
134138
{
135139
struct htlc_in *hin = tal(ctx, struct htlc_in);
@@ -146,6 +150,15 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
146150
hin->path_key = tal_dup_or_null(hin, struct pubkey, path_key);
147151
memcpy(hin->onion_routing_packet, onion_routing_packet,
148152
sizeof(hin->onion_routing_packet));
153+
if (extra_tlvs) {
154+
hin->extra_tlvs = tal_dup_talarr(hin, struct tlv_field, extra_tlvs);
155+
for (size_t i = 0; i < tal_count(extra_tlvs); i++) {
156+
/* We need to attach the value to the correct parent */
157+
hin->extra_tlvs[i].value = tal_dup_talarr(hin, u8, hin->extra_tlvs[i].value);
158+
}
159+
} else {
160+
hin->extra_tlvs = NULL;
161+
}
149162

150163
hin->hstate = RCVD_ADD_COMMIT;
151164
hin->badonion = 0;
@@ -265,6 +278,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
265278
const struct sha256 *payment_hash,
266279
const u8 *onion_routing_packet,
267280
const struct pubkey *path_key,
281+
const struct tlv_field* extra_tlvs,
268282
bool am_origin,
269283
struct amount_msat final_msat,
270284
u64 partid,
@@ -291,6 +305,17 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
291305
hout->timeout = NULL;
292306

293307
hout->path_key = tal_dup_or_null(hout, struct pubkey, path_key);
308+
309+
if (extra_tlvs) {
310+
hout->extra_tlvs = tal_dup_talarr(hout, struct tlv_field, extra_tlvs);
311+
for (size_t i = 0; i < tal_count(extra_tlvs); i++) {
312+
/* We need to attach the value to the correct parent */
313+
hout->extra_tlvs[i].value = tal_dup_talarr(hout, u8, hout->extra_tlvs[i].value);
314+
}
315+
} else {
316+
hout->extra_tlvs = NULL;
317+
}
318+
294319
hout->am_origin = am_origin;
295320
if (am_origin) {
296321
hout->partid = partid;

lightningd/htlc_end.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ struct htlc_in {
5858

5959
/* The decoded onion payload after hooks processed it. */
6060
struct onion_payload *payload;
61+
62+
/* Incommimg extra update_add_htlc_tlv tlvs */
63+
struct tlv_field *extra_tlvs;
6164
};
6265

6366
struct htlc_out {
@@ -106,6 +109,9 @@ struct htlc_out {
106109

107110
/* Timer we use in case they don't add an HTLC in a timely manner. */
108111
struct oneshot *timeout;
112+
113+
/* Extra tlvs that are extended to the update_add_htlc_tlvs */
114+
struct tlv_field *extra_tlvs;
109115
};
110116

111117
static inline const struct htlc_key *keyof_htlc_in(const struct htlc_in *in)
@@ -158,6 +164,7 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
158164
const struct secret *shared_secret TAKES,
159165
const struct pubkey *path_key TAKES,
160166
const u8 *onion_routing_packet,
167+
const struct tlv_field *extra_tlvs TAKES,
161168
bool fail_immediate);
162169

163170
/* You need to set the ID, then connect_htlc_out this! */
@@ -168,6 +175,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
168175
const struct sha256 *payment_hash,
169176
const u8 *onion_routing_packet,
170177
const struct pubkey *path_key,
178+
const struct tlv_field *extra_tlvs,
171179
bool am_origin,
172180
struct amount_msat final_msat,
173181
u64 partid,

lightningd/pay.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -783,8 +783,8 @@ static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld,
783783
return send_htlc_out(ctx, channel, first_hop->amount,
784784
base_expiry + first_hop->delay,
785785
final_amount, payment_hash,
786-
path_key, partid, groupid, onion, NULL, hout);
787-
}
786+
path_key, NULL, partid, groupid, onion, NULL, hout);
787+
}
788788

789789
static struct command_result *check_invoice_request_usage(struct command *cmd,
790790
const struct sha256 *local_invreq_id)
@@ -2093,7 +2093,7 @@ static struct command_result *json_injectpaymentonion(struct command *cmd,
20932093
failmsg = send_htlc_out(tmpctx, next, *msat,
20942094
*cltv, *destination_msat,
20952095
payment_hash,
2096-
next_path_key, *partid, *groupid,
2096+
next_path_key, NULL, *partid, *groupid,
20972097
serialize_onionpacket(tmpctx, rs->next),
20982098
NULL, &hout);
20992099
if (failmsg) {

lightningd/peer_htlcs.c

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1+
#include "bitcoin/pubkey.h"
2+
#include "ccan/tal/tal.h"
3+
#include "common/json_parse_simple.h"
4+
#include "common/json_stream.h"
5+
#include "common/utils.h"
16
#include "config.h"
7+
#include "jsmn.h"
8+
#include "lightningd/log.h"
9+
#include "wire/peer_wiregen.h"
210
#include <ccan/cast/cast.h>
311
#include <ccan/mem/mem.h>
412
#include <ccan/tal/str/str.h>
@@ -11,6 +19,7 @@
1119
#include <common/onion_decode.h>
1220
#include <common/onionreply.h>
1321
#include <common/timeout.h>
22+
#include <common/bigsize.h>
1423
#include <connectd/connectd_wiregen.h>
1524
#include <db/exec.h>
1625
#include <gossipd/gossipd_wiregen.h>
@@ -23,6 +32,9 @@
2332
#include <lightningd/plugin_hook.h>
2433
#include <lightningd/subd.h>
2534
#include <onchaind/onchaind_wiregen.h>
35+
#include <stdio.h>
36+
#include <wire/tlvstream.h>
37+
#include <wire/onion_wiregen.h>
2638

2739
#ifndef SUPERVERBOSE
2840
#define SUPERVERBOSE(...)
@@ -695,6 +707,7 @@ const u8 *send_htlc_out(const tal_t *ctx,
695707
struct amount_msat final_msat,
696708
const struct sha256 *payment_hash,
697709
const struct pubkey *path_key,
710+
const struct tlv_field *extra_tlvs,
698711
u64 partid,
699712
u64 groupid,
700713
const u8 *onion_routing_packet,
@@ -729,7 +742,8 @@ const u8 *send_htlc_out(const tal_t *ctx,
729742
/* Make peer's daemon own it, catch if it dies. */
730743
*houtp = new_htlc_out(out->owner, out, amount, cltv,
731744
payment_hash, onion_routing_packet,
732-
path_key, in == NULL,
745+
path_key, extra_tlvs,
746+
in == NULL,
733747
final_msat,
734748
partid, groupid, in);
735749
tal_add_destructor(*houtp, destroy_hout_subd_died);
@@ -742,6 +756,13 @@ const u8 *send_htlc_out(const tal_t *ctx,
742756
*houtp);
743757
}
744758

759+
if (extra_tlvs) {
760+
raw_tlvs = tal_arr(tmpctx, u8, 0);
761+
towire_tlvstream_raw(&raw_tlvs,
762+
tal_dup_talarr(tmpctx, struct tlv_field,
763+
extra_tlvs));
764+
}
765+
745766
msg = towire_channeld_offer_htlc(out, amount, cltv, payment_hash,
746767
onion_routing_packet, path_key,
747768
raw_tlvs);
@@ -797,7 +818,8 @@ static void forward_htlc(struct htlc_in *hin,
797818
const struct short_channel_id *forward_scid,
798819
const struct channel_id *forward_to,
799820
const u8 next_onion[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
800-
const struct pubkey *next_path_key)
821+
const struct pubkey *next_path_key,
822+
const struct tlv_field *extra_tlvs)
801823
{
802824
const u8 *failmsg;
803825
struct lightningd *ld = hin->key.channel->peer->ld;
@@ -912,7 +934,7 @@ static void forward_htlc(struct htlc_in *hin,
912934
failmsg = send_htlc_out(tmpctx, next, amt_to_forward,
913935
outgoing_cltv_value, AMOUNT_MSAT(0),
914936
&hin->payment_hash,
915-
next_path_key, 0 /* partid */, 0 /* groupid */,
937+
next_path_key, extra_tlvs, 0 /* partid */, 0 /* groupid */,
916938
next_onion, hin, &hout);
917939
if (!failmsg)
918940
return;
@@ -942,6 +964,7 @@ struct htlc_accepted_hook_payload {
942964
u64 failtlvtype;
943965
size_t failtlvpos;
944966
const char *failexplanation;
967+
u8 *extra_tlvs_raw;
945968
};
946969

947970
static void
@@ -998,8 +1021,8 @@ static bool htlc_accepted_hook_deserialize(struct htlc_accepted_hook_payload *re
9981021
struct htlc_in *hin = request->hin;
9991022
struct lightningd *ld = request->ld;
10001023
struct preimage payment_preimage;
1001-
const jsmntok_t *resulttok, *paykeytok, *payloadtok, *fwdtok;
1002-
u8 *failonion;
1024+
const jsmntok_t *resulttok, *paykeytok, *payloadtok, *fwdtok, *extra_tlvs_tok;
1025+
u8 *failonion, *raw_tlvs;
10031026

10041027
if (!toks || !buffer)
10051028
return true;
@@ -1013,6 +1036,49 @@ static bool htlc_accepted_hook_deserialize(struct htlc_accepted_hook_payload *re
10131036
json_strdup(tmpctx, buffer, toks));
10141037
}
10151038

1039+
extra_tlvs_tok = json_get_member(buffer, toks, "extra_tlvs");
1040+
if (extra_tlvs_tok) {
1041+
size_t max;
1042+
struct tlv_update_add_htlc_tlvs *check_extra_tlvs;
1043+
1044+
raw_tlvs = json_tok_bin_from_hex(tmpctx, buffer,
1045+
extra_tlvs_tok);
1046+
if (!raw_tlvs)
1047+
fatal("Bad custom tlvs for htlc_accepted"
1048+
" hook: %.*s",
1049+
extra_tlvs_tok->end - extra_tlvs_tok->start,
1050+
buffer + extra_tlvs_tok->start);
1051+
1052+
max = tal_bytelen(raw_tlvs);
1053+
1054+
/* We check if the custom tlvs are still valid BOLT#1 tlvs.
1055+
* As these are appended to forwarded htlcs we check for valid
1056+
* update_add_htlc_tlvs (restricts to known even types).
1057+
* NOTE: We may be less strict and allow unknown evens .*/
1058+
const u8 *cursor = raw_tlvs;
1059+
check_extra_tlvs = fromwire_tlv_update_add_htlc_tlvs(tmpctx,
1060+
&cursor,
1061+
&max);
1062+
if (!check_extra_tlvs) {
1063+
fatal("htlc_accepted_hook returned bad extra_tlvs %s",
1064+
tal_hex(tmpctx, raw_tlvs));
1065+
}
1066+
1067+
/* If we got a blinded path key we replace the next path key
1068+
* with it. */
1069+
if (check_extra_tlvs->blinded_path) {
1070+
tal_free(request->next_path_key);
1071+
request->next_path_key
1072+
= tal_steal(request,
1073+
check_extra_tlvs->blinded_path);
1074+
}
1075+
1076+
/* We made it and got a valid extra_tlvs: Replace the current
1077+
* extra_tlvs with it. */
1078+
tal_free(request->extra_tlvs_raw);
1079+
request->extra_tlvs_raw = tal_steal(request, raw_tlvs);
1080+
}
1081+
10161082
payloadtok = json_get_member(buffer, toks, "payload");
10171083
if (payloadtok) {
10181084
u8 *payload = json_tok_bin_from_hex(rs, buffer, payloadtok);
@@ -1170,6 +1236,9 @@ static void htlc_accepted_hook_serialize(struct htlc_accepted_hook_payload *p,
11701236
json_add_u32(s, "cltv_expiry", expiry);
11711237
json_add_s32(s, "cltv_expiry_relative", expiry - blockheight);
11721238
json_add_sha256(s, "payment_hash", &hin->payment_hash);
1239+
if (p->extra_tlvs_raw) {
1240+
json_add_hex_talarr(s, "extra_tlvs", p->extra_tlvs_raw);
1241+
}
11731242
json_object_end(s);
11741243
}
11751244

@@ -1200,13 +1269,25 @@ htlc_accepted_hook_final(struct htlc_accepted_hook_payload *request STEALS)
12001269
NULL, request->failtlvtype,
12011270
request->failtlvpos)));
12021271
} else if (rs->nextcase == ONION_FORWARD) {
1272+
struct tlv_field *extra_tlvs;
1273+
1274+
if (request->extra_tlvs_raw) {
1275+
const u8 *cursor = request->extra_tlvs_raw;
1276+
size_t max = tal_bytelen(cursor);
1277+
extra_tlvs = tal_arr(request, struct tlv_field, 0);
1278+
fromwire_tlv(&cursor, &max, NULL, 0, request,
1279+
&extra_tlvs, NULL, NULL, NULL);
1280+
} else {
1281+
extra_tlvs = NULL;
1282+
}
1283+
12031284
forward_htlc(hin, hin->cltv_expiry,
12041285
request->payload->amt_to_forward,
12051286
request->payload->outgoing_cltv,
12061287
request->payload->forward_channel,
12071288
request->fwd_channel_id,
12081289
serialize_onionpacket(tmpctx, rs->next),
1209-
request->next_path_key);
1290+
request->next_path_key, extra_tlvs);
12101291
} else
12111292
handle_localpay(hin,
12121293
request->payload->amt_to_forward,
@@ -1484,6 +1565,14 @@ static bool peer_accepted_htlc(const tal_t *ctx,
14841565
hook_payload->fwd_channel_id
14851566
= calc_forwarding_channel(ld, hook_payload);
14861567

1568+
if(hin->extra_tlvs) {
1569+
hook_payload->extra_tlvs_raw = tal_arr(hook_payload, u8, 0);
1570+
towire_tlvstream_raw(&hook_payload->extra_tlvs_raw,
1571+
hin->extra_tlvs);
1572+
} else {
1573+
hook_payload->extra_tlvs_raw = NULL;
1574+
}
1575+
14871576
plugin_hook_call_htlc_accepted(ld, NULL, hook_payload);
14881577

14891578
/* Falling through here is ok, after all the HTLC locked */
@@ -2210,6 +2299,7 @@ static bool channel_added_their_htlc(struct channel *channel,
22102299
op ? &shared_secret : NULL,
22112300
added->path_key,
22122301
added->onion_routing_packet,
2302+
added->extra_tlvs,
22132303
added->fail_immediate);
22142304

22152305
/* Save an incoming htlc to the wallet */
@@ -2641,13 +2731,15 @@ const struct existing_htlc **peer_htlcs(const tal_t *ctx,
26412731
else
26422732
f = NULL;
26432733

2734+
26442735
existing = new_existing_htlc(htlcs, hin->key.id, hin->hstate,
26452736
hin->msat, &hin->payment_hash,
26462737
hin->cltv_expiry,
26472738
hin->onion_routing_packet,
26482739
hin->path_key,
26492740
hin->preimage,
2650-
f, NULL);
2741+
f,
2742+
hin->extra_tlvs);
26512743
tal_arr_expand(&htlcs, existing);
26522744
}
26532745

@@ -2679,7 +2771,8 @@ const struct existing_htlc **peer_htlcs(const tal_t *ctx,
26792771
hout->onion_routing_packet,
26802772
hout->path_key,
26812773
hout->preimage,
2682-
f, NULL);
2774+
f,
2775+
hout->extra_tlvs);
26832776
tal_arr_expand(&htlcs, existing);
26842777
}
26852778

lightningd/peer_htlcs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const u8 *send_htlc_out(const tal_t *ctx,
3333
struct amount_msat final_msat,
3434
const struct sha256 *payment_hash,
3535
const struct pubkey *path_key,
36+
const struct tlv_field *extra_tlvs,
3637
u64 partid,
3738
u64 groupid,
3839
const u8 *onion_routing_packet,

wallet/test/run-wallet.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,10 @@ bool fromwire_onchaind_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNE
365365
/* Generated stub for fromwire_openingd_dev_memleak_reply */
366366
bool fromwire_openingd_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
367367
{ fprintf(stderr, "fromwire_openingd_dev_memleak_reply called!\n"); abort(); }
368+
/* Generated stub for fromwire_tlv_update_add_htlc_tlvs */
369+
struct tlv_update_add_htlc_tlvs *fromwire_tlv_update_add_htlc_tlvs(const tal_t *ctx UNNEEDED,
370+
const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
371+
{ fprintf(stderr, "fromwire_tlv_update_add_htlc_tlvs called!\n"); abort(); }
368372
/* Generated stub for get_network_blockheight */
369373
u32 get_network_blockheight(const struct chain_topology *topo UNNEEDED)
370374
{ fprintf(stderr, "get_network_blockheight called!\n"); abort(); }

wallet/wallet.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3408,6 +3408,13 @@ static bool wallet_stmt2htlc_in(struct channel *channel,
34083408
/* FIXME: save path_key in db !*/
34093409
in->path_key = NULL;
34103410
in->payload = NULL;
3411+
/* FIXME: save extra_tlvs in db! But: check the implications that a
3412+
* spammy peer - giving us big extra tlvs - would have on our database.
3413+
* Right now, not saving the extra tlvs in the db seems OK as it is
3414+
* only relevant in the case that I forward but restart in the middle
3415+
* of a payment.
3416+
*/
3417+
in->extra_tlvs = NULL;
34113418

34123419
db_col_sha256(stmt, "payment_hash", &in->payment_hash);
34133420

@@ -3480,6 +3487,13 @@ static bool wallet_stmt2htlc_out(struct wallet *wallet,
34803487
db_col_sha256(stmt, "payment_hash", &out->payment_hash);
34813488
/* FIXME: save path_key in db !*/
34823489
out->path_key = NULL;
3490+
/* FIXME: save extra_tlvs in db! But: check the implications that a
3491+
* spammy peer - giving us big extra tlvs - would have on our database.
3492+
* Right now, not saving the extra tlvs in the db seems OK as it is
3493+
* only relevant in the case that I forward but restart in the middle
3494+
* of a payment.
3495+
*/
3496+
out->extra_tlvs = NULL;
34833497

34843498
out->preimage = db_col_optional(out, stmt, "payment_key", preimage);
34853499

0 commit comments

Comments
 (0)