From 817b1b361ef84bfa6f944ff19d584342dfafb479 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 29 Sep 2021 12:33:57 +0200 Subject: [PATCH] db: Add `groupid` to HTLCs --- lightningd/htlc_end.c | 5 ++++- lightningd/htlc_end.h | 4 ++++ lightningd/pay.c | 11 ++++++----- lightningd/peer_htlcs.c | 7 ++++--- lightningd/peer_htlcs.h | 1 + wallet/db.c | 3 +++ wallet/test/run-wallet.c | 5 +++-- wallet/wallet.c | 26 +++++++++++++++++++------- wallet/wallet.h | 2 +- 9 files changed, 45 insertions(+), 19 deletions(-) diff --git a/lightningd/htlc_end.c b/lightningd/htlc_end.c index 8bcdc7bde..b5589c2e5 100644 --- a/lightningd/htlc_end.c +++ b/lightningd/htlc_end.c @@ -277,6 +277,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx, const struct pubkey *blinding, bool am_origin, u64 partid, + u64 groupid, struct htlc_in *in) { struct htlc_out *hout = tal(ctx, struct htlc_out); @@ -303,8 +304,10 @@ struct htlc_out *new_htlc_out(const tal_t *ctx, else hout->blinding = NULL; hout->am_origin = am_origin; - if (am_origin) + if (am_origin) { hout->partid = partid; + hout->groupid = groupid; + } hout->in = NULL; if (in) htlc_out_connect_htlc_in(hout, in); diff --git a/lightningd/htlc_end.h b/lightningd/htlc_end.h index 1ea13da65..f6a4fd9fc 100644 --- a/lightningd/htlc_end.h +++ b/lightningd/htlc_end.h @@ -91,6 +91,9 @@ struct htlc_out { /* If am_origin, this is the partid of the payment. */ u64 partid; + /* Is this is part of a group of HTLCs, which group is it? */ + u64 groupid; + /* Where it's from, if not going to us. */ struct htlc_in *in; @@ -163,6 +166,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx, const struct pubkey *blinding, bool am_origin, u64 partid, + u64 groupid, struct htlc_in *in); void connect_htlc_in(struct htlc_in_map *map, struct htlc_in *hin); diff --git a/lightningd/pay.c b/lightningd/pay.c index 31a81757b..03c46a16f 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -323,7 +323,7 @@ void payment_succeeded(struct lightningd *ld, struct htlc_out *hout, struct wallet_payment *payment; wallet_payment_set_status(ld->wallet, &hout->payment_hash, - hout->partid, + hout->partid, hout->groupid, PAYMENT_COMPLETE, rval); payment = wallet_payment_by_hash(tmpctx, ld->wallet, &hout->payment_hash, @@ -627,7 +627,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, /* Save to DB */ payment_store(ld, payment); wallet_payment_set_status(ld->wallet, &hout->payment_hash, - hout->partid, + hout->partid, hout->groupid, PAYMENT_FAILED, NULL); wallet_payment_set_failinfo(ld->wallet, &hout->payment_hash, @@ -767,6 +767,7 @@ static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld, const struct sha256 *payment_hash, const struct pubkey *blinding, u64 partid, + u64 groupid, struct channel *channel, struct htlc_out **hout) { @@ -776,8 +777,8 @@ static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld, base_expiry = get_block_height(ld->topology) + 1; onion = serialize_onionpacket(tmpctx, packet); return send_htlc_out(ctx, channel, first_hop->amount, - base_expiry + first_hop->delay, - payment_hash, blinding, partid, onion, NULL, hout, + base_expiry + first_hop->delay, payment_hash, + blinding, partid, groupid, onion, NULL, hout, &dont_care_about_channel_update); } @@ -1010,7 +1011,7 @@ send_payment_core(struct lightningd *ld, } failmsg = send_onion(tmpctx, ld, packet, first_hop, rhash, NULL, partid, - channel, &hout); + group, channel, &hout); if (failmsg) { fail = immediate_routing_failure(cmd, ld, diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index d7ec61315..e040a23b3 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -621,6 +621,7 @@ const u8 *send_htlc_out(const tal_t *ctx, const struct sha256 *payment_hash, const struct pubkey *blinding, u64 partid, + u64 groupid, const u8 *onion_routing_packet, struct htlc_in *in, struct htlc_out **houtp, @@ -654,7 +655,7 @@ const u8 *send_htlc_out(const tal_t *ctx, *houtp = new_htlc_out(out->owner, out, amount, cltv, payment_hash, onion_routing_packet, blinding, in == NULL, - partid, in); + partid, groupid, in); tal_add_destructor(*houtp, destroy_hout_subd_died); /* Give channel 30 seconds to commit this htlc. */ @@ -766,8 +767,8 @@ static void forward_htlc(struct htlc_in *hin, failmsg = send_htlc_out(tmpctx, next, amt_to_forward, outgoing_cltv_value, &hin->payment_hash, - next_blinding, 0, next_onion, hin, - &hout, &needs_update_appended); + next_blinding, 0 /* partid */, 0 /* groupid */, + next_onion, hin, &hout, &needs_update_appended); if (!failmsg) return; diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 35375756e..50618a749 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -46,6 +46,7 @@ const u8 *send_htlc_out(const tal_t *ctx, const struct sha256 *payment_hash, const struct pubkey *blinding, u64 partid, + u64 groupid, const u8 *onion_routing_packet, struct htlc_in *in, struct htlc_out **houtp, diff --git a/wallet/db.c b/wallet/db.c index cd3e9671c..e08c62d8a 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -832,6 +832,9 @@ static struct migration dbmigrations[] = { ", 0" ", local_offer_id FROM temp_payments;"), NULL}, {SQL("DROP TABLE temp_payments;"), NULL}, + /* HTLCs also need to carry the groupid around so we can + * selectively update them. */ + {SQL("ALTER TABLE channel_htlcs ADD groupid BIGINT;"), NULL}, }; /* Leak tracking. */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 2dd00b48d..67cace886 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1820,6 +1820,7 @@ static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx) t->payment_preimage = NULL; memset(&t->payment_hash, 1, sizeof(t->payment_hash)); t->partid = 0; + t->groupid = 0; db_begin_transaction(w->db); t2 = tal_dup(NULL, struct wallet_payment, t); @@ -1839,8 +1840,8 @@ static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx) t->status = PAYMENT_COMPLETE; t->payment_preimage = tal(w, struct preimage); memset(t->payment_preimage, 2, sizeof(*t->payment_preimage)); - wallet_payment_set_status(w, &t->payment_hash, t->partid, t->status, - t->payment_preimage); + wallet_payment_set_status(w, &t->payment_hash, t->partid, t->groupid, + t->status, t->payment_preimage); t2 = wallet_payment_by_hash(ctx, w, &t->payment_hash, t->partid); CHECK(t2 != NULL); CHECK(t2->status == t->status); diff --git a/wallet/wallet.c b/wallet/wallet.c index 053d35a39..dbb5f22e0 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2368,7 +2368,9 @@ void wallet_htlc_save_out(struct wallet *wallet, " hstate," " routing_onion," " malformed_onion," - " partid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?);")); + " partid," + " groupid" + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?);")); db_bind_u64(stmt, 0, chan->dbid); db_bind_u64(stmt, 1, out->key.id); @@ -2389,10 +2391,15 @@ void wallet_htlc_save_out(struct wallet *wallet, db_bind_blob(stmt, 9, out->onion_routing_packet, sizeof(out->onion_routing_packet)); - if (!out->am_origin) + + /* groupid and partid are only relevant when we are the origin */ + if (!out->am_origin) { db_bind_null(stmt, 10); - else + db_bind_null(stmt, 11); + } else { db_bind_u64(stmt, 10, out->partid); + db_bind_u64(stmt, 11, out->groupid); + } db_exec_prepared_v2(stmt); out->dbid = db_last_insert_id_v2(stmt); @@ -2587,6 +2594,7 @@ static bool wallet_stmt2htlc_out(struct wallet *wallet, } } else { out->partid = db_column_u64(stmt, 13); + out->groupid = db_column_u64(stmt, 15); out->am_origin = true; } @@ -2697,6 +2705,7 @@ bool wallet_htlcs_load_out_for_channel(struct wallet *wallet, ", received_time" ", partid" ", localfailmsg" + ", groupid" " FROM channel_htlcs" " WHERE direction = ?" " AND channel_id = ?" @@ -3181,7 +3190,7 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, void wallet_payment_set_status(struct wallet *wallet, const struct sha256 *payment_hash, - u64 partid, + u64 partid, u64 groupid, const enum wallet_payment_status newstatus, const struct preimage *preimage) { @@ -3198,21 +3207,23 @@ void wallet_payment_set_status(struct wallet *wallet, stmt = db_prepare_v2(wallet->db, SQL("UPDATE payments SET status=? " - "WHERE payment_hash=? AND partid=?")); + "WHERE payment_hash=? AND partid=? AND groupid=?")); db_bind_int(stmt, 0, wallet_payment_status_in_db(newstatus)); db_bind_sha256(stmt, 1, payment_hash); db_bind_u64(stmt, 2, partid); + db_bind_u64(stmt, 3, groupid); db_exec_prepared_v2(take(stmt)); if (preimage) { stmt = db_prepare_v2(wallet->db, SQL("UPDATE payments SET payment_preimage=? " - "WHERE payment_hash=? AND partid=?")); + "WHERE payment_hash=? AND partid=? AND groupid=?")); db_bind_preimage(stmt, 0, preimage); db_bind_sha256(stmt, 1, payment_hash); db_bind_u64(stmt, 2, partid); + db_bind_u64(stmt, 3, groupid); db_exec_prepared_v2(take(stmt)); } if (newstatus != PAYMENT_PENDING) { @@ -3222,9 +3233,10 @@ void wallet_payment_set_status(struct wallet *wallet, " , route_nodes = NULL" " , route_channels = NULL" " WHERE payment_hash = ?" - " AND partid = ?;")); + " AND partid = ? AND groupid=?;")); db_bind_sha256(stmt, 0, payment_hash); db_bind_u64(stmt, 1, partid); + db_bind_u64(stmt, 2, groupid); db_exec_prepared_v2(take(stmt)); } } diff --git a/wallet/wallet.h b/wallet/wallet.h index 400ecb496..2dbfa36d0 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -1067,7 +1067,7 @@ u64 wallet_payment_get_groupid(struct wallet *wallet, */ void wallet_payment_set_status(struct wallet *wallet, const struct sha256 *payment_hash, - u64 partid, + u64 partid, u64 groupid, const enum wallet_payment_status newstatus, const struct preimage *preimage);