lightningd: ensure htlc htables are always tal objects.

We want to change the htable allocator to use tal, which will need
this.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2023-01-03 15:16:52 +10:30
parent da5eb03bae
commit 763d02e424
10 changed files with 84 additions and 72 deletions

View File

@ -35,9 +35,9 @@ struct htlc_out *channel_has_htlc_out(struct channel *channel)
struct htlc_out *hout;
struct lightningd *ld = channel->peer->ld;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (hout->key.channel == channel)
return hout;
}
@ -51,9 +51,9 @@ struct htlc_in *channel_has_htlc_in(struct channel *channel)
struct htlc_in *hin;
struct lightningd *ld = channel->peer->ld;
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (hin->key.channel == channel)
return hin;
}

View File

@ -89,8 +89,8 @@ static struct htlc_set *new_htlc_set(struct lightningd *ld,
*/
set->timeout = new_reltimer(ld->timers, set, time_from_sec(70),
timeout_htlc_set, set);
htlc_set_map_add(&ld->htlc_sets, set);
tal_add_destructor2(set, destroy_htlc_set, &ld->htlc_sets);
htlc_set_map_add(ld->htlc_sets, set);
tal_add_destructor2(set, destroy_htlc_set, ld->htlc_sets);
return set;
}
@ -131,7 +131,7 @@ void htlc_set_add(struct lightningd *ld,
* - otherwise, if it supports `basic_mpp`:
* - MUST add it to the HTLC set corresponding to that `payment_hash`.
*/
set = htlc_set_map_get(&ld->htlc_sets, &hin->payment_hash);
set = htlc_set_map_get(ld->htlc_sets, &hin->payment_hash);
if (!set)
set = new_htlc_set(ld, hin, total_msat);
else {

View File

@ -168,12 +168,21 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
* list attached to the channel structure itself, or even left them in
* the database rather than making an in-memory version. Obviously
* I was in a premature optimization mood when I wrote this: */
htlc_in_map_init(&ld->htlcs_in);
htlc_out_map_init(&ld->htlcs_out);
ld->htlcs_in = tal(ld, struct htlc_in_map);
htlc_in_map_init(ld->htlcs_in);
/*~ Note also: we didn't need to use an allocation here! We could
* have simply made the `struct htlc_out_map` a member. But we
* override the htable allocation routines to use tal(), and they
* want a tal parent, so we always make our hash table a tallocated
* object. */
ld->htlcs_out = tal(ld, struct htlc_out_map);
htlc_out_map_init(ld->htlcs_out);
/*~ For multi-part payments, we need to keep some incoming payments
* in limbo until we get all the parts, or we time them out. */
htlc_set_map_init(&ld->htlc_sets);
ld->htlc_sets = tal(ld, struct htlc_set_map);
htlc_set_map_init(ld->htlc_sets);
/*~ We have a multi-entry log-book infrastructure: we define a 10MB log
* book to hold all the entries (and trims as necessary), and multiple
@ -1251,8 +1260,8 @@ stop:
ld->wallet->db = tal_free(ld->wallet->db);
/* Clean our our HTLC maps, since they use malloc. */
htlc_in_map_clear(&ld->htlcs_in);
htlc_out_map_clear(&ld->htlcs_out);
htlc_in_map_clear(ld->htlcs_in);
htlc_out_map_clear(ld->htlcs_out);
remove(ld->pidfile);

View File

@ -191,11 +191,11 @@ struct lightningd {
u32 blockheight;
/* HTLCs in flight. */
struct htlc_in_map htlcs_in;
struct htlc_out_map htlcs_out;
struct htlc_in_map *htlcs_in;
struct htlc_out_map *htlcs_out;
/* Sets of HTLCs we are holding onto for MPP. */
struct htlc_set_map htlc_sets;
struct htlc_set_map *htlc_sets;
struct wallet *wallet;

View File

@ -152,9 +152,9 @@ static void finish_report(const struct leak_detect *leaks)
/* First delete known false positives. */
memleak_scan_htable(memtable, &ld->topology->txwatches->raw);
memleak_scan_htable(memtable, &ld->topology->txowatches->raw);
memleak_scan_htable(memtable, &ld->htlcs_in.raw);
memleak_scan_htable(memtable, &ld->htlcs_out.raw);
memleak_scan_htable(memtable, &ld->htlc_sets.raw);
memleak_scan_htable(memtable, &ld->htlcs_in->raw);
memleak_scan_htable(memtable, &ld->htlcs_out->raw);
memleak_scan_htable(memtable, &ld->htlc_sets->raw);
/* Now delete ld and those which it has pointers to. */
memleak_scan_obj(memtable, ld);

View File

@ -27,9 +27,9 @@ static void onchaind_tell_fulfill(struct channel *channel)
u8 *msg;
struct lightningd *ld = channel->peer->ld;
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (hin->key.channel != channel)
continue;
@ -76,7 +76,7 @@ static bool tell_if_missing(const struct channel *channel,
return false;
/* Might not be a current HTLC. */
hout = find_htlc_out(&channel->peer->ld->htlcs_out, channel, stub->id);
hout = find_htlc_out(channel->peer->ld->htlcs_out, channel, stub->id);
if (!hout)
return false;

View File

@ -440,9 +440,9 @@ static void json_add_htlcs(struct lightningd *ld,
/* FIXME: Add more fields. */
json_array_start(response, "htlcs");
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (hin->key.channel != channel)
continue;
@ -464,9 +464,9 @@ static void json_add_htlcs(struct lightningd *ld,
json_object_end(response);
}
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (hout->key.channel != channel)
continue;
@ -528,18 +528,18 @@ static struct amount_sat commit_txfee(const struct channel *channel,
option_anchor_outputs))
num_untrimmed_htlcs++;
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (hin->key.channel != channel)
continue;
if (!htlc_is_trimmed(!side, hin->msat, feerate, dust_limit,
side, option_anchor_outputs))
num_untrimmed_htlcs++;
}
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (hout->key.channel != channel)
continue;
if (!htlc_is_trimmed(side, hout->msat, feerate, dust_limit,
@ -583,9 +583,9 @@ static void subtract_offered_htlcs(const struct channel *channel,
struct htlc_out_map_iter outi;
struct lightningd *ld = channel->peer->ld;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (hout->key.channel != channel)
continue;
if (!amount_msat_sub(amount, *amount, hout->msat))
@ -600,9 +600,9 @@ static void subtract_received_htlcs(const struct channel *channel,
struct htlc_in_map_iter ini;
struct lightningd *ld = channel->peer->ld;
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (hin->key.channel != channel)
continue;
if (!amount_msat_sub(amount, *amount, hin->msat))
@ -2151,14 +2151,14 @@ struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld)
list_for_each(&peer->channels, channel, list) {
if (!wallet_htlcs_load_in_for_channel(ld->wallet,
channel,
&ld->htlcs_in)) {
ld->htlcs_in)) {
fatal("could not load htlcs for channel");
}
}
}
/* Make a copy of the htlc_map: entries removed as they're matched */
htlc_in_map_copy(unconnected_htlcs_in, &ld->htlcs_in);
htlc_in_map_copy(unconnected_htlcs_in, ld->htlcs_in);
/* Now we load the outgoing HTLCs, so we can connect them. */
list_for_each(&ld->peers, peer, list) {
@ -2167,7 +2167,7 @@ struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld)
list_for_each(&peer->channels, channel, list) {
if (!wallet_htlcs_load_out_for_channel(ld->wallet,
channel,
&ld->htlcs_out,
ld->htlcs_out,
unconnected_htlcs_in)) {
fatal("could not load outgoing htlcs for channel");
}

View File

@ -559,7 +559,7 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds UNU
return;
}
if (find_htlc_out(&subd->ld->htlcs_out, hout->key.channel, hout->key.id)
if (find_htlc_out(subd->ld->htlcs_out, hout->key.channel, hout->key.id)
|| hout->key.id == HTLC_INVALID_ID) {
channel_internal_error(subd->channel,
"Bad offer_htlc_reply HTLC id %"PRIu64
@ -570,7 +570,7 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds UNU
}
/* Add it to lookup table now we know id. */
connect_htlc_out(&subd->ld->htlcs_out, hout);
connect_htlc_out(subd->ld->htlcs_out, hout);
/* When channeld includes it in commitment, we'll make it persistent. */
}
@ -1284,7 +1284,7 @@ static bool peer_accepted_htlc(const tal_t *ctx,
*failmsg = NULL;
*badonion = 0;
hin = find_htlc_in(&ld->htlcs_in, channel, id);
hin = find_htlc_in(ld->htlcs_in, channel, id);
if (!hin) {
channel_internal_error(channel,
"peer_got_revoke unknown htlc %"PRIu64, id);
@ -1456,7 +1456,7 @@ static bool peer_fulfilled_our_htlc(struct channel *channel,
struct lightningd *ld = channel->peer->ld;
struct htlc_out *hout;
hout = find_htlc_out(&ld->htlcs_out, channel, fulfilled->id);
hout = find_htlc_out(ld->htlcs_out, channel, fulfilled->id);
if (!hout) {
channel_internal_error(channel,
"fulfilled_our_htlc unknown htlc %"PRIu64,
@ -1482,9 +1482,9 @@ void onchain_fulfilled_htlc(struct channel *channel,
sha256(&payment_hash, preimage, sizeof(*preimage));
/* FIXME: use db to look this up! */
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (hout->key.channel != channel)
continue;
@ -1515,7 +1515,7 @@ static bool peer_failed_our_htlc(struct channel *channel,
struct htlc_out *hout;
struct lightningd *ld = channel->peer->ld;
hout = find_htlc_out(&ld->htlcs_out, channel, failed->id);
hout = find_htlc_out(ld->htlcs_out, channel, failed->id);
if (!hout) {
channel_internal_error(channel,
"failed_our_htlc unknown htlc %"PRIu64,
@ -1633,9 +1633,9 @@ static void fail_dangling_htlc_in(struct lightningd *ld,
struct htlc_in *hin;
struct htlc_in_map_iter ini;
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (!sha256_eq(&hin->payment_hash, payment_hash))
continue;
if (hin->badonion) {
@ -1670,7 +1670,7 @@ void onchain_failed_our_htlc(const struct channel *channel,
struct htlc_out *hout;
log_debug(channel->log, "onchain_failed_our_htlc");
hout = find_htlc_out(&ld->htlcs_out, channel, htlc->id);
hout = find_htlc_out(ld->htlcs_out, channel, htlc->id);
if (!hout) {
/* For penalty transactions, tell onchaind about all possible
* HTLCs: they may not all exist any more. */
@ -1678,8 +1678,8 @@ void onchain_failed_our_htlc(const struct channel *channel,
log_broken(channel->log, "HTLC id %"PRIu64" not found!",
htlc->id);
/* Immediate corruption sanity check if this happens */
htable_check(&ld->htlcs_out.raw, "onchain_failed_our_htlc out");
htable_check(&ld->htlcs_in.raw, "onchain_failed_our_htlc in");
htable_check(&ld->htlcs_out->raw, "onchain_failed_our_htlc out");
htable_check(&ld->htlcs_in->raw, "onchain_failed_our_htlc in");
return;
}
@ -1746,8 +1746,8 @@ void onchain_failed_our_htlc(const struct channel *channel,
htlc->id);
/* Immediate corruption sanity check if this happens */
htable_check(&ld->htlcs_out.raw, "onchain_failed_our_htlc out");
htable_check(&ld->htlcs_in.raw, "onchain_failed_our_htlc in");
htable_check(&ld->htlcs_out->raw, "onchain_failed_our_htlc out");
htable_check(&ld->htlcs_in->raw, "onchain_failed_our_htlc in");
fail_dangling_htlc_in(ld, &hout->payment_hash);
}
}
@ -1864,7 +1864,7 @@ static bool update_in_htlc(struct channel *channel,
struct htlc_in *hin;
struct lightningd *ld = channel->peer->ld;
hin = find_htlc_in(&ld->htlcs_in, channel, id);
hin = find_htlc_in(ld->htlcs_in, channel, id);
if (!hin) {
channel_internal_error(channel, "Can't find in HTLC %"PRIu64, id);
return false;
@ -1887,7 +1887,7 @@ static bool update_out_htlc(struct channel *channel,
struct htlc_out *hout;
struct wallet_payment *payment;
hout = find_htlc_out(&ld->htlcs_out, channel, id);
hout = find_htlc_out(ld->htlcs_out, channel, id);
if (!hout) {
channel_internal_error(channel, "Can't find out HTLC %"PRIu64, id);
return false;
@ -2150,7 +2150,7 @@ static bool channel_added_their_htlc(struct channel *channel,
added->amount);
log_debug(channel->log, "Adding their HTLC %"PRIu64, added->id);
connect_htlc_in(&channel->peer->ld->htlcs_in, hin);
connect_htlc_in(channel->peer->ld->htlcs_in, hin);
return true;
}
@ -2472,11 +2472,11 @@ void peer_got_revoke(struct channel *channel, const u8 *msg)
struct htlc_in *hin;
if (badonions[i]) {
hin = find_htlc_in(&ld->htlcs_in, channel,
hin = find_htlc_in(ld->htlcs_in, channel,
changed[i].id);
local_fail_in_htlc_badonion(hin, badonions[i]);
} else if (failmsgs[i]) {
hin = find_htlc_in(&ld->htlcs_in, channel,
hin = find_htlc_in(ld->htlcs_in, channel,
changed[i].id);
local_fail_in_htlc(hin, failmsgs[i]);
} else
@ -2518,9 +2518,9 @@ const struct existing_htlc **peer_htlcs(const tal_t *ctx,
htlcs = tal_arr(ctx, struct existing_htlc *, 0);
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
struct failed_htlc *f;
struct existing_htlc *existing;
@ -2544,9 +2544,9 @@ const struct existing_htlc **peer_htlcs(const tal_t *ctx,
tal_arr_expand(&htlcs, existing);
}
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
struct failed_htlc *f;
struct existing_htlc *existing;
@ -2592,18 +2592,18 @@ void free_htlcs(struct lightningd *ld, const struct channel *channel)
do {
deleted = false;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (channel && hout->key.channel != channel)
continue;
tal_free(hout);
deleted = true;
}
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (channel && hin->key.channel != channel)
continue;
tal_free(hin);
@ -2657,9 +2657,9 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height)
removed = false;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
/* Not timed out yet? */
if (height < htlc_out_deadline(hout))
continue;
@ -2701,9 +2701,9 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height)
removed = false;
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
for (hin = htlc_in_map_first(ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
struct channel *channel = hin->key.channel;
/* Not fulfilled? If overdue, that's their problem... */
@ -2787,9 +2787,9 @@ void fixup_htlcs_out(struct lightningd *ld)
struct htlc_out_map_iter outi;
struct htlc_out *hout;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
for (hout = htlc_out_map_first(ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (!hout->am_origin)
fixup_hout(ld, hout);
}

View File

@ -1033,7 +1033,8 @@ int main(int argc, char *argv[])
ld = tal(tmpctx, struct lightningd);
list_head_init(&ld->peers);
htlc_in_map_init(&ld->htlcs_in);
ld->htlcs_in = tal(ld, struct htlc_in_map);
htlc_in_map_init(ld->htlcs_in);
chainparams = chainparams_for_network("regtest");
candidates = tal_arr(tmpctx, struct routehint_candidate, 0);

View File

@ -1933,8 +1933,10 @@ int main(int argc, const char *argv[])
ld->rr_counter = 0;
node_id_from_hexstr("02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66, &ld->id);
/* Accessed in peer destructor sanity check */
htlc_in_map_init(&ld->htlcs_in);
htlc_out_map_init(&ld->htlcs_out);
ld->htlcs_in = tal(ld, struct htlc_in_map);
htlc_in_map_init(ld->htlcs_in);
ld->htlcs_out = tal(ld, struct htlc_out_map);
htlc_out_map_init(ld->htlcs_out);
/* We do a runtime test here, so we still check compile! */
if (HAVE_SQLITE3) {