diff --git a/lightningd/pay.c b/lightningd/pay.c index 03c46a16f..f4dd83b19 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -33,6 +33,7 @@ struct sendpay_command { struct sha256 payment_hash; u64 partid; + u64 groupid; struct command *cmd; }; @@ -77,12 +78,13 @@ static void add_sendpay_waiter(struct lightningd *ld, struct command *cmd, const struct sha256 *payment_hash, - u64 partid) + u64 partid, u64 groupid) { struct sendpay_command *pc = tal(cmd, struct sendpay_command); pc->payment_hash = *payment_hash; pc->partid = partid; + pc->groupid = groupid; pc->cmd = cmd; list_add(&ld->sendpay_commands, &pc->list); tal_add_destructor(pc, destroy_sendpay_command); @@ -94,12 +96,13 @@ static void add_waitsendpay_waiter(struct lightningd *ld, struct command *cmd, const struct sha256 *payment_hash, - u64 partid) + u64 partid, u64 groupid) { struct sendpay_command *pc = tal(cmd, struct sendpay_command); pc->payment_hash = *payment_hash; pc->partid = partid; + pc->groupid = groupid; pc->cmd = cmd; list_add(&ld->waitsendpay_commands, &pc->list); tal_add_destructor(pc, destroy_sendpay_command); @@ -285,6 +288,8 @@ static void tell_waiters_failed(struct lightningd *ld, continue; if (payment->partid != pc->partid) continue; + if (payment->groupid != pc->groupid) + continue; sendpay_fail(pc->cmd, payment, pay_errcode, onionreply, fail, errmsg); @@ -311,6 +316,8 @@ static void tell_waiters_success(struct lightningd *ld, continue; if (payment->partid != pc->partid) continue; + if (payment->groupid != pc->groupid) + continue; sendpay_success(pc->cmd, payment); } @@ -327,7 +334,7 @@ void payment_succeeded(struct lightningd *ld, struct htlc_out *hout, PAYMENT_COMPLETE, rval); payment = wallet_payment_by_hash(tmpctx, ld->wallet, &hout->payment_hash, - hout->partid); + hout->partid, hout->groupid); assert(payment); if (payment->local_offer_id) @@ -539,7 +546,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, payment = wallet_payment_by_hash(tmpctx, ld->wallet, &hout->payment_hash, - hout->partid); + hout->partid, hout->groupid); #ifdef COMPAT_V052 /* Prior to "pay: delete HTLC when we delete payment." we would @@ -652,7 +659,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, static struct command_result *wait_payment(struct lightningd *ld, struct command *cmd, const struct sha256 *payment_hash, - u64 partid) + u64 partid, u64 groupid) { struct wallet_payment *payment; struct onionreply *failonionreply; @@ -668,7 +675,7 @@ static struct command_result *wait_payment(struct lightningd *ld, errcode_t rpcerrorcode; payment = wallet_payment_by_hash(tmpctx, ld->wallet, - payment_hash, partid); + payment_hash, partid, groupid); if (!payment) { return command_fail(cmd, PAY_NO_SUCH_PAYMENT, "Never attempted payment part %"PRIu64 @@ -678,12 +685,12 @@ static struct command_result *wait_payment(struct lightningd *ld, payment_hash)); } - log_debug(cmd->ld->log, "Payment part %"PRIu64"/%"PRIu64" status %u", - partid, payment->partid, payment->status); + log_debug(cmd->ld->log, "Payment part %"PRIu64"/%"PRIu64"/%"PRIu64" status %u", + partid, payment->partid, payment->groupid, payment->status); switch (payment->status) { case PAYMENT_PENDING: - add_waitsendpay_waiter(ld, cmd, payment_hash, partid); + add_waitsendpay_waiter(ld, cmd, payment_hash, partid, groupid); return NULL; case PAYMENT_COMPLETE: @@ -694,6 +701,7 @@ static struct command_result *wait_payment(struct lightningd *ld, wallet_payment_get_failinfo(tmpctx, ld->wallet, payment_hash, partid, + groupid, &failonionreply, &faildestperm, &failindex, @@ -1078,7 +1086,7 @@ send_payment_core(struct lightningd *ld, /* We write this into db when HTLC is actually sent. */ wallet_payment_setup(ld->wallet, payment); - add_sendpay_waiter(ld, cmd, rhash, partid); + add_sendpay_waiter(ld, cmd, rhash, partid, group); return command_still_pending(cmd); } @@ -1487,16 +1495,21 @@ static struct command_result *json_waitsendpay(struct command *cmd, struct sha256 *rhash; unsigned int *timeout; struct command_result *res; - u64 *partid; + u64 *partid, *groupid; if (!param(cmd, buffer, params, p_req("payment_hash", param_sha256, &rhash), p_opt("timeout", param_number, &timeout), p_opt_def("partid", param_u64, &partid, 0), + p_opt("groupid", param_u64, &groupid), NULL)) return command_param_failed(); - res = wait_payment(cmd->ld, cmd, rhash, *partid); + if (groupid == NULL) { + groupid = tal(cmd, u64); + *groupid = wallet_payment_get_groupid(cmd->ld->wallet, rhash); + } + res = wait_payment(cmd->ld, cmd, rhash, *partid, *groupid); if (res) return res; diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index e040a23b3..1f9891efd 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1622,7 +1622,8 @@ static bool update_out_htlc(struct channel *channel, if (hout->am_origin) { payment = wallet_payment_by_hash(tmpctx, ld->wallet, &hout->payment_hash, - hout->partid); + hout->partid, + hout->groupid); assert(payment); payment_store(ld, take(payment)); } diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 8fad8c585..d803df4e6 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -1490,6 +1490,7 @@ static struct command_result *payment_sendonion_success(struct command *cmd, payment_waitsendpay_finished, p); json_add_sha256(req->js, "payment_hash", p->payment_hash); json_add_num(req->js, "partid", p->partid); + json_add_u64(req->js, "groupid", p->groupid); send_outreq(p->plugin, req); return command_still_pending(cmd); diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 67cace886..33e788b01 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1820,13 +1820,13 @@ 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; + t->groupid = 12345; db_begin_transaction(w->db); t2 = tal_dup(NULL, struct wallet_payment, t); wallet_payment_setup(w, t2); wallet_payment_store(w, take(t2)); - t2 = wallet_payment_by_hash(ctx, w, &t->payment_hash, 0); + t2 = wallet_payment_by_hash(ctx, w, &t->payment_hash, 0, t->groupid); CHECK(t2 != NULL); CHECK(t2->status == t->status); CHECK(sha256_eq(&t2->payment_hash, &t->payment_hash)); @@ -1842,7 +1842,7 @@ static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx) memset(t->payment_preimage, 2, sizeof(*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); + t2 = wallet_payment_by_hash(ctx, w, &t->payment_hash, t->partid, t->groupid); CHECK(t2 != NULL); CHECK(t2->status == t->status); CHECK(sha256_eq(&t2->payment_hash, &t->payment_hash)); diff --git a/wallet/wallet.c b/wallet/wallet.c index dbb5f22e0..0fc3f2878 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2910,9 +2910,10 @@ void wallet_payment_store(struct wallet *wallet, stmt = db_prepare_v2(wallet->db, SQL("SELECT status FROM payments" " WHERE payment_hash=?" - " AND partid = ?;")); + " AND partid = ? AND groupid = ?;")); db_bind_sha256(stmt, 0, &payment->payment_hash); db_bind_u64(stmt, 1, payment->partid); + db_bind_u64(stmt, 2, payment->groupid); db_query_prepared(stmt); res = db_step(stmt); assert(res); @@ -3134,10 +3135,7 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx, } else payment->local_offer_id = NULL; - if (!db_column_is_null(stmt, 17)) - payment->groupid = db_column_u64(stmt, 17); - else - payment->groupid = 0; + payment->groupid = db_column_u64(stmt, 17); return payment; } @@ -3145,7 +3143,7 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx, struct wallet_payment * wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, const struct sha256 *payment_hash, - u64 partid) + u64 partid, u64 groupid) { struct db_stmt *stmt; struct wallet_payment *payment; @@ -3176,10 +3174,11 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, ", groupid" " FROM payments" " 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_query_prepared(stmt); if (db_step(stmt)) { payment = wallet_stmt2payment(ctx, stmt); @@ -3245,6 +3244,7 @@ void wallet_payment_get_failinfo(const tal_t *ctx, struct wallet *wallet, const struct sha256 *payment_hash, u64 partid, + u64 groupid, /* outputs */ struct onionreply **failonionreply, bool *faildestperm, @@ -3266,9 +3266,10 @@ void wallet_payment_get_failinfo(const tal_t *ctx, ", failnode, failchannel" ", failupdate, faildetail, faildirection" " FROM payments" - " WHERE payment_hash=? AND partid=?;")); + " WHERE payment_hash=? AND partid=? AND groupid=?;")); db_bind_sha256(stmt, 0, payment_hash); db_bind_u64(stmt, 1, partid); + db_bind_u64(stmt, 2, groupid); db_query_prepared(stmt); resb = db_step(stmt); assert(resb); diff --git a/wallet/wallet.h b/wallet/wallet.h index 2dbfa36d0..95e4814aa 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -1048,7 +1048,7 @@ void wallet_local_htlc_out_delete(struct wallet *wallet, struct wallet_payment * wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, const struct sha256 *payment_hash, - u64 partid); + u64 partid, u64 groupid); /** * Retrieve maximum groupid for a given payment_hash. @@ -1082,6 +1082,7 @@ void wallet_payment_get_failinfo(const tal_t *ctx, struct wallet *wallet, const struct sha256 *payment_hash, u64 partid, + u64 groupid, /* outputs */ struct onionreply **failonionreply, bool *faildestperm,