From bc107b59587d0f98d278c958ba775e215312b618 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 24 Aug 2022 09:55:18 +0200 Subject: [PATCH] -fix purse deposit when done against non-existing reserve --- src/exchangedb/plugin_exchangedb_postgres.c | 10 +++- src/exchangedb/procedures.sql | 51 +++++++++++++++------ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 505f493e5..e3da5216b 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -908,8 +908,8 @@ prepare_statements (struct PostgresClosure *pg) " out_balance_ok AS balance_ok" ",out_conflict AS conflict" " FROM exchange_do_purse_deposit" - " ($1,$2,$3,$4,$5,$6,$7,$8);", - 8), + " ($1,$2,$3,$4,$5,$6,$7,$8,$9);", + 9), /* Used in #postgres_update_aggregation_transient() */ GNUNET_PQ_make_prepare ( "set_purse_balance", @@ -15875,6 +15875,7 @@ postgres_do_purse_deposit ( bool *conflict) { struct PostgresClosure *pg = cls; + struct GNUNET_TIME_Timestamp reserve_expiration; uint64_t partner_id = 0; /* FIXME #7271: WAD support... */ struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&partner_id), @@ -15883,6 +15884,7 @@ postgres_do_purse_deposit ( GNUNET_PQ_query_param_auto_from_type (coin_pub), GNUNET_PQ_query_param_auto_from_type (coin_sig), TALER_PQ_query_param_amount (amount_minus_fee), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { @@ -15893,6 +15895,10 @@ postgres_do_purse_deposit ( GNUNET_PQ_result_spec_end }; + reserve_expiration + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + pg->legal_reserve_expiration_time)); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "call_purse_deposit", params, diff --git a/src/exchangedb/procedures.sql b/src/exchangedb/procedures.sql index 38f346c01..1940fa7b8 100644 --- a/src/exchangedb/procedures.sql +++ b/src/exchangedb/procedures.sql @@ -1427,6 +1427,7 @@ CREATE OR REPLACE FUNCTION exchange_do_purse_deposit( IN in_coin_sig BYTEA, IN in_amount_without_fee_val INT8, IN in_amount_without_fee_frac INT4, + IN in_reserve_expiration INT8, OUT out_balance_ok BOOLEAN, OUT out_conflict BOOLEAN) LANGUAGE plpgsql @@ -1569,21 +1570,41 @@ THEN WHERE purse_pub=in_purse_pub; ELSE -- This is a local reserve, update balance immediately. - UPDATE reserves - SET - current_balance_frac=current_balance_frac+my_amount_frac - - CASE - WHEN current_balance_frac + my_amount_frac >= 100000000 - THEN 100000000 - ELSE 0 - END, - current_balance_val=current_balance_val+my_amount_val - + CASE - WHEN current_balance_frac + my_amount_frac >= 100000000 - THEN 1 - ELSE 0 - END - WHERE reserve_pub=my_reserve_pub; + INSERT INTO reserves + (reserve_pub + ,current_balance_frac + ,current_balance_val + ,expiration_date + ,gc_date) + VALUES + (my_reserve_pub + ,my_amount_frac + ,my_amount_val + ,in_reserve_expiration + ,in_reserve_expiration) + ON CONFLICT DO NOTHING; + + IF NOT FOUND + THEN + + UPDATE reserves + SET + current_balance_frac=current_balance_frac+my_amount_frac + - CASE + WHEN current_balance_frac + my_amount_frac >= 100000000 + THEN 100000000 + ELSE 0 + END + ,current_balance_val=current_balance_val+my_amount_val + + CASE + WHEN current_balance_frac + my_amount_frac >= 100000000 + THEN 1 + ELSE 0 + END + ,expiration_date=GREATEST(expiration_date,in_reserve_expiration) + ,gc_date=GREATEST(gc_date,in_reserve_expiration) + WHERE reserve_pub=my_reserve_pub; + END IF; -- ... and mark purse as finished. -- FIXME: combine with UPDATE above?