Skip to content

Commit 9b8fe61

Browse files
rustyrussellcdecker
authored andcommitted
pay: remove cmd pointer from htlc_out.
Maintaining it was always fraught, since the command could go away if the JSON RPC died. Most recently, it was broken again on shutdown (see below). In future we may allow pay commands to block on previous payments, so it won't even be a 1:1 mapping. Generalize it: keep commands in a simple list and do a lookup when a payment fails/succeeds. Valgrind error file: valgrind-errors.5732 ==5732== Invalid read of size 8 ==5732== at 0x4149FD: remove_cmd_from_hout (pay.c:292) ==5732== by 0x468BAB: notify (tal.c:237) ==5732== by 0x469077: del_tree (tal.c:400) ==5732== by 0x4690C7: del_tree (tal.c:410) ==5732== by 0x46948A: tal_free (tal.c:509) ==5732== by 0x40F1EA: main (lightningd.c:362) ==5732== Address 0x69df148 is 1,512 bytes inside a block of size 1,544 free'd ==5732== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5732== by 0x469150: del_tree (tal.c:421) ==5732== by 0x46948A: tal_free (tal.c:509) ==5732== by 0x4198F2: free_htlcs (peer_control.c:1281) ==5732== by 0x40EBA9: shutdown_subdaemons (lightningd.c:209) ==5732== by 0x40F1DE: main (lightningd.c:360) ==5732== Block was alloc'd at ==5732== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5732== by 0x468C30: allocate (tal.c:250) ==5732== by 0x4691F7: tal_alloc_ (tal.c:448) ==5732== by 0x40A279: new_htlc_out (htlc_end.c:143) ==5732== by 0x41FD64: send_htlc_out (peer_htlcs.c:397) ==5732== by 0x41511C: send_payment (pay.c:388) ==5732== by 0x41589E: json_sendpay (pay.c:513) ==5732== by 0x40D9B1: parse_request (jsonrpc.c:600) ==5732== by 0x40DCAC: read_json (jsonrpc.c:667) ==5732== by 0x45C706: next_plan (io.c:59) ==5732== by 0x45D1DD: do_plan (io.c:387) ==5732== by 0x45D21B: io_ready (io.c:397) Signed-off-by: Rusty Russell <[email protected]>
1 parent a497a99 commit 9b8fe61

File tree

8 files changed

+70
-44
lines changed

8 files changed

+70
-44
lines changed

lightningd/htlc_end.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ struct htlc_out *htlc_out_check(const struct htlc_out *hout,
125125
htlc_state_name(hout->hstate));
126126
else if (hout->failuremsg && hout->preimage)
127127
return corrupt(hout, abortstr, "Both failed and succeeded");
128-
else if (hout->cmd && hout->in)
129-
return corrupt(hout, abortstr, "Both local and forwarded");
130128

131129
return cast_const(struct htlc_out *, hout);
132130
}
@@ -137,8 +135,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
137135
u64 msatoshi, u32 cltv_expiry,
138136
const struct sha256 *payment_hash,
139137
const u8 *onion_routing_packet,
140-
struct htlc_in *in,
141-
struct command *cmd)
138+
struct htlc_in *in)
142139
{
143140
struct htlc_out *hout = tal(ctx, struct htlc_out);
144141

@@ -150,7 +147,6 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
150147
hout->msatoshi = msatoshi;
151148
hout->cltv_expiry = cltv_expiry;
152149
hout->payment_hash = *payment_hash;
153-
hout->cmd = cmd;
154150
memcpy(hout->onion_routing_packet, onion_routing_packet,
155151
sizeof(hout->onion_routing_packet));
156152

lightningd/htlc_end.h

+1-5
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@ struct htlc_out {
7575

7676
/* Where it's from, if not going to us. */
7777
struct htlc_in *in;
78-
79-
/* Otherwise, this MAY be non-null if there's a pay command waiting */
80-
struct command *cmd;
8178
};
8279

8380
static inline const struct htlc_key *keyof_htlc_in(const struct htlc_in *in)
@@ -132,8 +129,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
132129
u64 msatoshi, u32 cltv_expiry,
133130
const struct sha256 *payment_hash,
134131
const u8 *onion_routing_packet,
135-
struct htlc_in *in,
136-
struct command *cmd);
132+
struct htlc_in *in);
137133

138134
void connect_htlc_in(struct htlc_in_map *map, struct htlc_in *hin);
139135
void connect_htlc_out(struct htlc_out_map *map, struct htlc_out *hout);

lightningd/lightningd.c

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx,
6262
ld->alias = NULL;
6363
ld->rgb = NULL;
6464
list_head_init(&ld->connects);
65+
list_head_init(&ld->pay_commands);
6566
ld->wireaddrs = tal_arr(ld, struct wireaddr, 0);
6667
ld->portnum = DEFAULT_PORT;
6768
timers_init(&ld->timers, time_mono());

lightningd/lightningd.h

+3
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ struct lightningd {
128128

129129
struct wallet *wallet;
130130

131+
/* Outstanding sendpay/pay commands. */
132+
struct list_head pay_commands;
133+
131134
/* Maintained by invoices.c */
132135
struct invoices *invoices;
133136

lightningd/pay.c

+62-28
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,74 @@
1818
#include <lightningd/subd.h>
1919
#include <sodium/randombytes.h>
2020

21-
static void json_pay_success(struct command *cmd, const struct preimage *rval)
21+
/* pay/sendpay command */
22+
struct pay_command {
23+
struct list_node list;
24+
25+
struct sha256 payment_hash;
26+
struct command *cmd;
27+
};
28+
29+
static void destroy_pay_command(struct pay_command *pc)
2230
{
23-
struct json_result *response;
31+
list_del(&pc->list);
32+
}
2433

25-
/* Can be NULL if JSON RPC goes away. */
26-
if (!cmd)
27-
return;
34+
/* Owned by cmd */
35+
static struct pay_command *new_pay_command(struct command *cmd,
36+
const struct sha256 *payment_hash,
37+
struct lightningd *ld)
38+
{
39+
struct pay_command *pc = tal(cmd, struct pay_command);
40+
41+
pc->payment_hash = *payment_hash;
42+
pc->cmd = cmd;
43+
list_add(&ld->pay_commands, &pc->list);
44+
tal_add_destructor(pc, destroy_pay_command);
45+
return pc;
46+
}
47+
48+
static void json_pay_command_success(struct command *cmd,
49+
const struct preimage *payment_preimage)
50+
{
51+
struct json_result *response;
2852

2953
response = new_json_result(cmd);
3054
json_object_start(response, NULL);
31-
json_add_hex(response, "preimage", rval, sizeof(*rval));
55+
json_add_hex(response, "preimage",
56+
payment_preimage, sizeof(*payment_preimage));
3257
json_object_end(response);
3358
command_success(cmd, response);
3459
}
3560

36-
static void json_pay_failed(struct command *cmd,
61+
static void json_pay_success(struct lightningd *ld,
62+
const struct sha256 *payment_hash,
63+
const struct preimage *payment_preimage)
64+
{
65+
struct pay_command *pc, *next;
66+
67+
list_for_each_safe(&ld->pay_commands, pc, next, list) {
68+
if (!structeq(payment_hash, &pc->payment_hash))
69+
continue;
70+
71+
/* Deletes itself. */
72+
json_pay_command_success(pc->cmd, payment_preimage);
73+
}
74+
}
75+
76+
static void json_pay_failed(struct lightningd *ld,
77+
const struct sha256 *payment_hash,
3778
enum onion_type failure_code,
3879
const char *details)
3980
{
40-
/* Can be NULL if JSON RPC goes away. */
41-
if (cmd) {
42-
command_fail(cmd, "Failed: %s (%s)",
81+
struct pay_command *pc, *next;
82+
83+
list_for_each_safe(&ld->pay_commands, pc, next, list) {
84+
if (!structeq(payment_hash, &pc->payment_hash))
85+
continue;
86+
87+
/* Deletes itself. */
88+
command_fail(pc->cmd, "failed: %s (%s)",
4389
onion_type_name(failure_code), details);
4490
}
4591
}
@@ -49,10 +95,7 @@ void payment_succeeded(struct lightningd *ld, struct htlc_out *hout,
4995
{
5096
wallet_payment_set_status(ld->wallet, &hout->payment_hash,
5197
PAYMENT_COMPLETE, rval);
52-
/* Can be NULL if JSON RPC goes away. */
53-
if (hout->cmd)
54-
json_pay_success(hout->cmd, rval);
55-
hout->cmd = NULL;
98+
json_pay_success(ld, &hout->payment_hash, rval);
5699
}
57100

58101
/* Return NULL if the wrapped onion error message has no
@@ -282,17 +325,10 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
282325
* and payment again. */
283326
(void) retry_plausible;
284327

285-
json_pay_failed(hout->cmd, failcode, failmsg);
328+
json_pay_failed(ld, &hout->payment_hash, failcode, failmsg);
286329
tal_free(tmpctx);
287330
}
288331

289-
/* When JSON RPC goes away, cmd is freed: detach from the hout */
290-
static void remove_cmd_from_hout(struct command *cmd, struct htlc_out *hout)
291-
{
292-
assert(hout->cmd == cmd);
293-
hout->cmd = NULL;
294-
}
295-
296332
/* Returns true if it's still pending. */
297333
static bool send_payment(struct command *cmd,
298334
const struct sha256 *rhash,
@@ -362,7 +398,8 @@ static bool send_payment(struct command *cmd,
362398
&payment->destination));
363399
return false;
364400
}
365-
json_pay_success(cmd, payment->payment_preimage);
401+
json_pay_command_success(cmd,
402+
payment->payment_preimage);
366403
return false;
367404
}
368405
wallet_payment_delete(cmd->ld->wallet, rhash);
@@ -387,8 +424,7 @@ static bool send_payment(struct command *cmd,
387424

388425
failcode = send_htlc_out(peer, route[0].amount,
389426
base_expiry + route[0].delay,
390-
rhash, onion, NULL, cmd,
391-
&hout);
427+
rhash, onion, NULL, &hout);
392428
if (failcode) {
393429
command_fail(cmd, "First peer not ready: %s",
394430
onion_type_name(failcode));
@@ -416,9 +452,7 @@ static bool send_payment(struct command *cmd,
416452
/* We write this into db when HTLC is actually sent. */
417453
wallet_payment_setup(cmd->ld->wallet, payment);
418454

419-
/* If we fail, remove cmd ptr from htlc_out. */
420-
tal_add_destructor2(cmd, remove_cmd_from_hout, hout);
421-
455+
new_pay_command(cmd, rhash, cmd->ld);
422456
tal_free(tmpctx);
423457
return true;
424458
}

lightningd/peer_htlcs.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv,
375375
const struct sha256 *payment_hash,
376376
const u8 *onion_routing_packet,
377377
struct htlc_in *in,
378-
struct command *cmd,
379378
struct htlc_out **houtp)
380379
{
381380
struct htlc_out *hout;
@@ -395,8 +394,7 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv,
395394

396395
/* Make peer's daemon own it, catch if it dies. */
397396
hout = new_htlc_out(out->owner, out, amount, cltv,
398-
payment_hash, onion_routing_packet, in,
399-
cmd);
397+
payment_hash, onion_routing_packet, in);
400398
tal_add_destructor(hout, hout_subd_died);
401399

402400
msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash,
@@ -488,7 +486,7 @@ static void forward_htlc(struct htlc_in *hin,
488486

489487
failcode = send_htlc_out(next, amt_to_forward,
490488
outgoing_cltv_value, &hin->payment_hash,
491-
next_onion, hin, NULL, NULL);
489+
next_onion, hin, NULL);
492490
if (!failcode)
493491
return;
494492

lightningd/peer_htlcs.h

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv,
3939
const struct sha256 *payment_hash,
4040
const u8 *onion_routing_packet,
4141
struct htlc_in *in,
42-
struct command *cmd,
4342
struct htlc_out **houtp);
4443

4544
struct htlc_out *find_htlc_out_by_ripemd(const struct peer *peer,

wallet/wallet.c

-1
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,6 @@ static bool wallet_stmt2htlc_out(const struct wallet_channel *channel,
10591059

10601060
out->failuremsg = NULL;
10611061
out->failcode = 0;
1062-
out->cmd = NULL;
10631062

10641063
/* Need to defer wiring until we can look up all incoming
10651064
* htlcs, will wire using origin_htlc_id */

0 commit comments

Comments
 (0)