mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-21 14:24:09 +01:00
invoice: fix potential race where invoice is paid/expired while we're calling hook.
There's actually a (very unlikely) race here: we would previously have crashed with an assertion in invoices_resolve. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
a437936c78
commit
1a3c0a0c0d
10 changed files with 25 additions and 19 deletions
|
@ -250,11 +250,17 @@ invoice_payment_hooks_done(struct invoice_payment_hook_payload *payload STEALS)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Paid or expired in the meantime. */
|
||||
if (!wallet_invoice_resolve(ld->wallet, invoice, payload->msat)) {
|
||||
htlc_set_fail(payload->set, take(failmsg_incorrect_or_unknown(
|
||||
NULL, ld, payload->set->htlcs[0])));
|
||||
return;
|
||||
}
|
||||
|
||||
log_info(ld->log, "Resolved invoice '%s' with amount %s in %zu htlcs",
|
||||
payload->label->s,
|
||||
type_to_string(tmpctx, struct amount_msat, &payload->msat),
|
||||
tal_count(payload->set->htlcs));
|
||||
wallet_invoice_resolve(ld->wallet, invoice, payload->msat);
|
||||
htlc_set_fulfill(payload->set, &payload->preimage);
|
||||
}
|
||||
|
||||
|
|
|
@ -643,7 +643,7 @@ const struct invoice_details *wallet_invoice_iterator_deref(const tal_t *ctx UNN
|
|||
const struct invoice_iterator *it UNNEEDED)
|
||||
{ fprintf(stderr, "wallet_invoice_iterator_deref called!\n"); abort(); }
|
||||
/* Generated stub for wallet_invoice_resolve */
|
||||
void wallet_invoice_resolve(struct wallet *wallet UNNEEDED,
|
||||
bool wallet_invoice_resolve(struct wallet *wallet UNNEEDED,
|
||||
struct invoice invoice UNNEEDED,
|
||||
struct amount_msat received UNNEEDED)
|
||||
{ fprintf(stderr, "wallet_invoice_resolve called!\n"); abort(); }
|
||||
|
|
2
wallet/db_postgres_sqlgen.c
generated
2
wallet/db_postgres_sqlgen.c
generated
|
@ -1690,4 +1690,4 @@ struct db_query db_postgres_queries[] = {
|
|||
|
||||
#endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */
|
||||
|
||||
// SHA256STAMP:a61b8b6ea86287e22c696530a9b5cd35ccef271280b8ac34d2665dc5aff42fce
|
||||
// SHA256STAMP:fac2fa6846e0deadf6f24fc9deb6efb0bac04b5947c254ae39300663366178af
|
||||
|
|
2
wallet/db_sqlite3_sqlgen.c
generated
2
wallet/db_sqlite3_sqlgen.c
generated
|
@ -1690,4 +1690,4 @@ struct db_query db_sqlite3_queries[] = {
|
|||
|
||||
#endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */
|
||||
|
||||
// SHA256STAMP:a61b8b6ea86287e22c696530a9b5cd35ccef271280b8ac34d2665dc5aff42fce
|
||||
// SHA256STAMP:fac2fa6846e0deadf6f24fc9deb6efb0bac04b5947c254ae39300663366178af
|
||||
|
|
|
@ -496,7 +496,7 @@ static enum invoice_status invoice_get_status(struct invoices *invoices, struct
|
|||
return state;
|
||||
}
|
||||
|
||||
void invoices_resolve(struct invoices *invoices,
|
||||
bool invoices_resolve(struct invoices *invoices,
|
||||
struct invoice invoice,
|
||||
struct amount_msat received)
|
||||
{
|
||||
|
@ -505,7 +505,8 @@ void invoices_resolve(struct invoices *invoices,
|
|||
u64 paid_timestamp;
|
||||
enum invoice_status state = invoice_get_status(invoices, invoice);
|
||||
|
||||
assert(state == UNPAID);
|
||||
if (state != UNPAID)
|
||||
return false;
|
||||
|
||||
/* Assign a pay-index. */
|
||||
pay_index = get_next_pay_index(invoices->db);
|
||||
|
@ -527,6 +528,7 @@ void invoices_resolve(struct invoices *invoices,
|
|||
|
||||
/* Tell all the waiters about the paid invoice. */
|
||||
trigger_invoice_waiter_resolve(invoices, invoice.id, &invoice);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Called when an invoice waiter is destructed. */
|
||||
|
|
|
@ -174,10 +174,9 @@ const struct invoice_details *invoices_iterator_deref(
|
|||
* @invoice - the invoice to mark as paid.
|
||||
* @received - the actual amount received.
|
||||
*
|
||||
* Precondition: the invoice must not yet be expired (invoices
|
||||
* does not check).
|
||||
* If the invoice is not UNPAID, returns false.
|
||||
*/
|
||||
void invoices_resolve(struct invoices *invoices,
|
||||
bool invoices_resolve(struct invoices *invoices,
|
||||
struct invoice invoice,
|
||||
struct amount_msat received);
|
||||
|
||||
|
|
8
wallet/statements_gettextgen.po
generated
8
wallet/statements_gettextgen.po
generated
|
@ -666,15 +666,15 @@ msgstr ""
|
|||
msgid "SELECT state FROM invoices WHERE id = ?;"
|
||||
msgstr ""
|
||||
|
||||
#: wallet/invoices.c:515
|
||||
#: wallet/invoices.c:516
|
||||
msgid "UPDATE invoices SET state=? , pay_index=? , msatoshi_received=? , paid_timestamp=? WHERE id=?;"
|
||||
msgstr ""
|
||||
|
||||
#: wallet/invoices.c:571
|
||||
#: wallet/invoices.c:573
|
||||
msgid "SELECT id FROM invoices WHERE pay_index IS NOT NULL AND pay_index > ? ORDER BY pay_index ASC LIMIT 1;"
|
||||
msgstr ""
|
||||
|
||||
#: wallet/invoices.c:620
|
||||
#: wallet/invoices.c:622
|
||||
msgid "SELECT state, payment_key, payment_hash, label, msatoshi, expiry_time, pay_index, msatoshi_received, paid_timestamp, bolt11, description, features FROM invoices WHERE id = ?;"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1113,4 +1113,4 @@ msgstr ""
|
|||
#: wallet/test/run-wallet.c:1376
|
||||
msgid "INSERT INTO channels (id) VALUES (1);"
|
||||
msgstr ""
|
||||
# SHA256STAMP:a63bd31a3977b161d8245ffddf5de3a03c972a60436eb8cbc1bb23f0ffb03405
|
||||
# SHA256STAMP:8f226711a58166b481aaa7b8c0593c7159711bee623737e3b4750f6c154d4f65
|
||||
|
|
|
@ -220,7 +220,7 @@ struct invoices *invoices_new(const tal_t *ctx UNNEEDED,
|
|||
struct timers *timers UNNEEDED)
|
||||
{ fprintf(stderr, "invoices_new called!\n"); abort(); }
|
||||
/* Generated stub for invoices_resolve */
|
||||
void invoices_resolve(struct invoices *invoices UNNEEDED,
|
||||
bool invoices_resolve(struct invoices *invoices UNNEEDED,
|
||||
struct invoice invoice UNNEEDED,
|
||||
struct amount_msat received UNNEEDED)
|
||||
{ fprintf(stderr, "invoices_resolve called!\n"); abort(); }
|
||||
|
|
|
@ -2337,11 +2337,11 @@ wallet_invoice_iterator_deref(const tal_t *ctx, struct wallet *wallet,
|
|||
{
|
||||
return invoices_iterator_deref(ctx, wallet->invoices, it);
|
||||
}
|
||||
void wallet_invoice_resolve(struct wallet *wallet,
|
||||
bool wallet_invoice_resolve(struct wallet *wallet,
|
||||
struct invoice invoice,
|
||||
struct amount_msat msatoshi_received)
|
||||
{
|
||||
invoices_resolve(wallet->invoices, invoice, msatoshi_received);
|
||||
return invoices_resolve(wallet->invoices, invoice, msatoshi_received);
|
||||
}
|
||||
void wallet_invoice_waitany(const tal_t *ctx,
|
||||
struct wallet *wallet,
|
||||
|
|
|
@ -883,10 +883,9 @@ const struct invoice_details *wallet_invoice_iterator_deref(const tal_t *ctx,
|
|||
* @invoice - the invoice to mark as paid.
|
||||
* @received - the actual amount received.
|
||||
*
|
||||
* Precondition: the invoice must not yet be expired (wallet
|
||||
* does not check!).
|
||||
* If the invoice is not UNPAID, returns false.
|
||||
*/
|
||||
void wallet_invoice_resolve(struct wallet *wallet,
|
||||
bool wallet_invoice_resolve(struct wallet *wallet,
|
||||
struct invoice invoice,
|
||||
struct amount_msat received);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue