Skip to content

Commit 0495295

Browse files
rustyrussellcdecker
authored andcommitted
lightningd: delay reprocessing of incoming htlcs at startup until plugins ready.
Fixes: #2923 Signed-off-by: Rusty Russell <[email protected]>
1 parent f0ab4d7 commit 0495295

File tree

9 files changed

+48
-27
lines changed

9 files changed

+48
-27
lines changed

lightningd/lightningd.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ int main(int argc, char *argv[])
632632
int stop_fd;
633633
struct timers *timers;
634634
const char *stop_response;
635+
struct htlc_in_map *unprocessed_htlcs;
635636

636637
/*~ What happens in strange locales should stay there. */
637638
setup_locale();
@@ -769,7 +770,7 @@ int main(int argc, char *argv[])
769770
* topology is initialized since some decisions rely on being able to
770771
* know the blockheight. */
771772
db_begin_transaction(ld->wallet->db);
772-
load_channels_from_wallet(ld);
773+
unprocessed_htlcs = load_channels_from_wallet(ld);
773774
db_commit_transaction(ld->wallet->db);
774775

775776
/*~ Create RPC socket: now lightning-cli can send us JSON RPC commands
@@ -780,6 +781,11 @@ int main(int argc, char *argv[])
780781
* can start talking to us. */
781782
plugins_config(ld->plugins);
782783

784+
/*~ Process any HTLCs we were in the middle of when we exited, now
785+
* that plugins (who might want to know via htlc_accepted hook) are
786+
* active. */
787+
htlcs_resubmit(ld, unprocessed_htlcs);
788+
783789
/*~ Activate connect daemon. Needs to be after the initialization of
784790
* chaintopology, otherwise peers may connect and ask for
785791
* uninitialized data. */

lightningd/peer_control.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,7 @@ void activate_peers(struct lightningd *ld)
14191419
}
14201420

14211421
/* Pull peers, channels and HTLCs from db, and wire them up. */
1422-
void load_channels_from_wallet(struct lightningd *ld)
1422+
struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld)
14231423
{
14241424
struct peer *peer;
14251425

@@ -1442,7 +1442,7 @@ void load_channels_from_wallet(struct lightningd *ld)
14421442
}
14431443

14441444
/* Now connect HTLC pointers together */
1445-
htlcs_reconnect(ld, &ld->htlcs_in, &ld->htlcs_out);
1445+
return htlcs_reconnect(ld, &ld->htlcs_in, &ld->htlcs_out);
14461446
}
14471447

14481448
static struct command_result *json_disconnect(struct command *cmd,

lightningd/peer_control.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel, bool cooperat
9090

9191
void channel_watch_funding(struct lightningd *ld, struct channel *channel);
9292

93-
/* Pull peers, channels and HTLCs from db, and wire them up. */
94-
void load_channels_from_wallet(struct lightningd *ld);
93+
/* Pull peers, channels and HTLCs from db, and wire them up.
94+
* Returns any HTLCs we have to resubmit via htlcs_resubmit. */
95+
struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld);
9596

9697
#if DEVELOPER
9798
void peer_dev_memleak(struct command *cmd);

lightningd/peer_htlcs.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,29 +2018,30 @@ static void fixup_hout(struct lightningd *ld, struct htlc_out *hout)
20182018
* For each outgoing HTLC find the incoming HTLC that triggered it. If
20192019
* we are the origin of the transfer then we cannot resolve the
20202020
* incoming HTLC in which case we just leave it `NULL`.
2021+
*
2022+
* Returns a map of any htlcs we need to retry.
20212023
*/
2022-
void htlcs_reconnect(struct lightningd *ld,
2023-
struct htlc_in_map *htlcs_in,
2024-
struct htlc_out_map *htlcs_out)
2024+
struct htlc_in_map *htlcs_reconnect(struct lightningd *ld,
2025+
struct htlc_in_map *htlcs_in,
2026+
struct htlc_out_map *htlcs_out)
20252027
{
20262028
struct htlc_in_map_iter ini;
20272029
struct htlc_out_map_iter outi;
20282030
struct htlc_in *hin;
20292031
struct htlc_out *hout;
2030-
struct htlc_in_map unprocessed;
2031-
enum onion_type failcode COMPILER_WANTS_INIT("gcc7.4.0 bad, 8.3 OK");
2032+
struct htlc_in_map *unprocessed = tal(NULL, struct htlc_in_map);
20322033

20332034
/* Any HTLCs which happened to be incoming and weren't forwarded before
20342035
* we shutdown/crashed: fail them now.
20352036
*
20362037
* Note that since we do local processing synchronously, so this never
20372038
* captures local payments. But if it did, it would be a tiny corner
20382039
* case. */
2039-
htlc_in_map_init(&unprocessed);
2040+
htlc_in_map_init(unprocessed);
20402041
for (hin = htlc_in_map_first(htlcs_in, &ini); hin;
20412042
hin = htlc_in_map_next(htlcs_in, &ini)) {
20422043
if (hin->hstate == RCVD_ADD_ACK_REVOCATION)
2043-
htlc_in_map_add(&unprocessed, hin);
2044+
htlc_in_map_add(unprocessed, hin);
20442045
}
20452046

20462047
for (hout = htlc_out_map_first(htlcs_out, &outi); hout;
@@ -2081,12 +2082,22 @@ void htlcs_reconnect(struct lightningd *ld,
20812082
#endif
20822083

20832084
if (hout->in)
2084-
htlc_in_map_del(&unprocessed, hout->in);
2085+
htlc_in_map_del(unprocessed, hout->in);
20852086
}
20862087

2088+
return unprocessed;
2089+
}
2090+
2091+
void htlcs_resubmit(struct lightningd *ld, struct htlc_in_map *unprocessed)
2092+
{
2093+
struct htlc_in *hin;
2094+
struct htlc_in_map_iter ini;
2095+
enum onion_type failcode COMPILER_WANTS_INIT("gcc7.4.0 bad, 8.3 OK");
2096+
20872097
/* Now fail any which were stuck. */
2088-
for (hin = htlc_in_map_first(&unprocessed, &ini); hin;
2089-
hin = htlc_in_map_next(&unprocessed, &ini)) {
2098+
for (hin = htlc_in_map_first(unprocessed, &ini);
2099+
hin;
2100+
hin = htlc_in_map_next(unprocessed, &ini)) {
20902101
log_unusual(hin->key.channel->log,
20912102
"Replaying old unprocessed HTLC #%"PRIu64,
20922103
hin->key.id);
@@ -2102,10 +2113,10 @@ void htlcs_reconnect(struct lightningd *ld,
21022113
}
21032114

21042115
/* Don't leak memory! */
2105-
htlc_in_map_clear(&unprocessed);
2116+
htlc_in_map_clear(unprocessed);
2117+
tal_free(unprocessed);
21062118
}
21072119

2108-
21092120
#if DEVELOPER
21102121
static struct command_result *json_dev_ignore_htlcs(struct command *cmd,
21112122
const char *buffer,

lightningd/peer_htlcs.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ void onchain_fulfilled_htlc(struct channel *channel,
6363

6464
void htlcs_notify_new_block(struct lightningd *ld, u32 height);
6565

66-
void htlcs_reconnect(struct lightningd *ld,
67-
struct htlc_in_map *htlcs_in,
68-
struct htlc_out_map *htlcs_out);
66+
struct htlc_in_map *htlcs_reconnect(struct lightningd *ld,
67+
struct htlc_in_map *htlcs_in,
68+
struct htlc_out_map *htlcs_out);
69+
70+
void htlcs_resubmit(struct lightningd *ld, struct htlc_in_map *unprocessed);
6971

7072
/* For HTLCs which terminate here, invoice payment calls one of these. */
7173
void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage);

lightningd/test/run-find_my_abspath.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,17 @@ void hsm_init(struct lightningd *ld UNNEEDED)
9696
/* Generated stub for htlcs_notify_new_block */
9797
void htlcs_notify_new_block(struct lightningd *ld UNNEEDED, u32 height UNNEEDED)
9898
{ fprintf(stderr, "htlcs_notify_new_block called!\n"); abort(); }
99+
/* Generated stub for htlcs_resubmit */
100+
void htlcs_resubmit(struct lightningd *ld UNNEEDED, struct htlc_in_map *unprocessed UNNEEDED)
101+
{ fprintf(stderr, "htlcs_resubmit called!\n"); abort(); }
99102
/* Generated stub for jsonrpc_listen */
100103
void jsonrpc_listen(struct jsonrpc *rpc UNNEEDED, struct lightningd *ld UNNEEDED)
101104
{ fprintf(stderr, "jsonrpc_listen called!\n"); abort(); }
102105
/* Generated stub for jsonrpc_setup */
103106
void jsonrpc_setup(struct lightningd *ld UNNEEDED)
104107
{ fprintf(stderr, "jsonrpc_setup called!\n"); abort(); }
105108
/* Generated stub for load_channels_from_wallet */
106-
void load_channels_from_wallet(struct lightningd *ld UNNEEDED)
109+
struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld UNNEEDED)
107110
{ fprintf(stderr, "load_channels_from_wallet called!\n"); abort(); }
108111
/* Generated stub for log_ */
109112
void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED, bool call_notifier UNNEEDED, const char *fmt UNNEEDED, ...)

lightningd/test/run-invoice-select-inchan.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ bool htlc_is_trimmed(enum side htlc_owner UNNEEDED,
126126
enum side side UNNEEDED)
127127
{ fprintf(stderr, "htlc_is_trimmed called!\n"); abort(); }
128128
/* Generated stub for htlcs_reconnect */
129-
void htlcs_reconnect(struct lightningd *ld UNNEEDED,
130-
struct htlc_in_map *htlcs_in UNNEEDED,
131-
struct htlc_out_map *htlcs_out UNNEEDED)
129+
struct htlc_in_map *htlcs_reconnect(struct lightningd *ld UNNEEDED,
130+
struct htlc_in_map *htlcs_in UNNEEDED,
131+
struct htlc_out_map *htlcs_out UNNEEDED)
132132
{ fprintf(stderr, "htlcs_reconnect called!\n"); abort(); }
133133
/* Generated stub for json_add_address */
134134
void json_add_address(struct json_stream *response UNNEEDED, const char *fieldname UNNEEDED,

tests/test_plugin.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,6 @@ def test_htlc_accepted_hook_resolve(node_factory):
466466
assert len(inv) == 1 and inv[0]['status'] == 'unpaid'
467467

468468

469-
@pytest.mark.xfail(strict=True)
470469
def test_htlc_accepted_hook_direct_restart(node_factory, executor):
471470
"""l2 restarts while it is pondering what to do with an HTLC.
472471
"""
@@ -492,7 +491,6 @@ def test_htlc_accepted_hook_direct_restart(node_factory, executor):
492491

493492

494493
@unittest.skipIf(not DEVELOPER, "without DEVELOPER=1, gossip v slow")
495-
@pytest.mark.xfail(strict=True)
496494
def test_htlc_accepted_hook_forward_restart(node_factory, executor):
497495
"""l2 restarts while it is pondering what to do with an HTLC.
498496
"""

wallet/test/run-wallet.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx)
11951195
"Failed loading HTLCs");
11961196
db_commit_transaction(w->db);
11971197

1198-
htlcs_reconnect(w->ld, htlcs_in, htlcs_out);
1198+
htlcs_resubmit(w->ld, htlcs_reconnect(w->ld, htlcs_in, htlcs_out));
11991199
CHECK(!wallet_err);
12001200

12011201
hin = htlc_in_map_get(htlcs_in, &in.key);

0 commit comments

Comments
 (0)