Skip to content

Commit 956350e

Browse files
committed
lightningd: check peers don't leave dangling HTLCs when they die.
Signed-off-by: Rusty Russell <[email protected]>
1 parent e933782 commit 956350e

File tree

4 files changed

+47
-7
lines changed

4 files changed

+47
-7
lines changed

lightningd/lightningd.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ static void shutdown_subdaemons(struct lightningd *ld)
198198
close(ld->hsm_fd);
199199
subd_shutdown(ld->gossip, 10);
200200

201+
free_htlcs(ld, NULL);
202+
201203
while ((p = list_top(&ld->peers, struct peer, list)) != NULL)
202204
tal_free(p);
203205
}

lightningd/peer_control.c

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,32 @@ static void peer_set_owner(struct peer *peer, struct subd *owner)
9090

9191
static void destroy_peer(struct peer *peer)
9292
{
93+
/* Must not have any HTLCs! */
94+
struct htlc_out_map_iter outi;
95+
struct htlc_out *hout;
96+
struct htlc_in_map_iter ini;
97+
struct htlc_in *hin;
98+
99+
for (hout = htlc_out_map_first(&peer->ld->htlcs_out, &outi);
100+
hout;
101+
hout = htlc_out_map_next(&peer->ld->htlcs_out, &outi)) {
102+
if (hout->key.peer != peer)
103+
continue;
104+
fatal("Freeing peer %s has hout %s",
105+
peer_state_name(peer->state),
106+
htlc_state_name(hout->hstate));
107+
}
108+
109+
for (hin = htlc_in_map_first(&peer->ld->htlcs_in, &ini);
110+
hin;
111+
hin = htlc_in_map_next(&peer->ld->htlcs_in, &ini)) {
112+
if (hin->key.peer != peer)
113+
continue;
114+
fatal("Freeing peer %s has hin %s",
115+
peer_state_name(peer->state),
116+
htlc_state_name(hin->hstate));
117+
}
118+
93119
/* Free any old owner still hanging around. */
94120
peer_set_owner(peer, NULL);
95121
list_del_from(&peer->ld->peers, &peer->list);
@@ -1163,7 +1189,8 @@ static void handle_onchain_htlc_timeout(struct peer *peer, const u8 *msg)
11631189
onchain_failed_our_htlc(peer, &htlc, "timed out");
11641190
}
11651191

1166-
static void handle_irrevocably_resolved(struct peer *peer, const u8 *msg)
1192+
/* If peer is NULL, free them all (for shutdown) */
1193+
void free_htlcs(struct lightningd *ld, const struct peer *peer)
11671194
{
11681195
struct htlc_out_map_iter outi;
11691196
struct htlc_out *hout;
@@ -1175,25 +1202,31 @@ static void handle_irrevocably_resolved(struct peer *peer, const u8 *msg)
11751202

11761203
do {
11771204
deleted = false;
1178-
for (hout = htlc_out_map_first(&peer->ld->htlcs_out, &outi);
1205+
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
11791206
hout;
1180-
hout = htlc_out_map_next(&peer->ld->htlcs_out, &outi)) {
1181-
if (hout->key.peer != peer)
1207+
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
1208+
if (peer && hout->key.peer != peer)
11821209
continue;
11831210
tal_free(hout);
11841211
deleted = true;
11851212
}
11861213

1187-
for (hin = htlc_in_map_first(&peer->ld->htlcs_in, &ini);
1214+
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
11881215
hin;
1189-
hin = htlc_in_map_next(&peer->ld->htlcs_in, &ini)) {
1190-
if (hin->key.peer != peer)
1216+
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
1217+
if (peer && hin->key.peer != peer)
11911218
continue;
11921219
tal_free(hin);
11931220
deleted = true;
11941221
}
11951222
/* Can skip over elements due to iterating while deleting. */
11961223
} while (deleted);
1224+
}
1225+
1226+
static void handle_irrevocably_resolved(struct peer *peer, const u8 *msg)
1227+
{
1228+
/* FIXME: Implement check_htlcs to ensure no dangling hout->in ptrs! */
1229+
free_htlcs(peer->ld, peer);
11971230

11981231
/* FIXME: Remove peer from db. */
11991232
log_info(peer->log, "onchaind complete, forgetting peer");

lightningd/peer_control.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,6 @@ const char *peer_state_name(enum peer_state state);
210210
void peer_set_condition(struct peer *peer, enum peer_state oldstate,
211211
enum peer_state state);
212212
void setup_listeners(struct lightningd *ld);
213+
214+
void free_htlcs(struct lightningd *ld, const struct peer *peer);
213215
#endif /* LIGHTNING_LIGHTNINGD_PEER_CONTROL_H */

lightningd/test/run-find_my_path.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ int debug_poll(struct pollfd *fds UNNEEDED, nfds_t nfds UNNEEDED, int timeout UN
1919
/* Generated stub for fatal */
2020
void fatal(const char *fmt UNNEEDED, ...)
2121
{ fprintf(stderr, "fatal called!\n"); abort(); }
22+
/* Generated stub for free_htlcs */
23+
void free_htlcs(struct lightningd *ld UNNEEDED, const struct peer *peer UNNEEDED)
24+
{ fprintf(stderr, "free_htlcs called!\n"); abort(); }
2225
/* Generated stub for gossip_init */
2326
void gossip_init(struct lightningd *ld UNNEEDED)
2427
{ fprintf(stderr, "gossip_init called!\n"); abort(); }

0 commit comments

Comments
 (0)