-add DB logic for purse expiration

This commit is contained in:
Christian Grothoff 2022-05-17 08:50:28 +02:00
parent f089bbe536
commit 802649c270
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
2 changed files with 100 additions and 5 deletions

View File

@ -1977,7 +1977,7 @@ BEGIN
END;
$$;
COMMENT ON FUNCTION exchange_do_recoup_by_reserve
COMMENT ON FUNCTION exchange_do_recoup_by_reserve
IS 'Recoup by reserve as a function to make sure we hit only the needed partition and not all when joining as joins on distributed tables fetch ALL rows from the shards';
@ -2505,7 +2505,8 @@ UPDATE known_coins
THEN 1
ELSE 0
END
WHERE coin_pub=in_coin_pub;
WHERE coin_pub=in_coin_pub
LIMIT 1; -- just to be extra safe
out_conflict=FALSE;
@ -3360,6 +3361,70 @@ BEGIN
END $$;
CREATE OR REPLACE FUNCTION exchange_do_expire_purse(
IN in_partner_id INT8,
IN in_start_time INT8,
IN in_end_time INT8,
OUT out_found BOOLEAN)
LANGUAGE plpgsql
AS $$
DECLARE
my_purse_pub BYTEA;
DECLARE
my_deposit record;
BEGIN
UPDATE purse_requests
SET refunded=TRUE,
finished=TRUE
WHERE (purse_expiration >= in_start_time) AND
(purse_expiration < in_end_time) AND
(NOT finished) AND
(NOT refunded)
RETURNING purse_pub
,in_reserve_quota
,flags
INTO my_purse_pub
,my_rq
,my_flags;
out_found = FOUND;
IF NOT FOUND
THEN
RETURN;
END IF;
-- restore balance to each coin deposited into the purse
FOR my_deposit IN
SELECT coin_pub
,amount_with_fee_val
,amount_with_fee_frac
FROM purse_deposits
WHERE purse_pub = my_purse_pub
LOOP
UPDATE
remaining_frac=remaining_frac+my_deposit.amount_with_fee_frac
- CASE
WHEN remaining_frac+my_deposit.amount_with_fee_frac >= 100000000
THEN 100000000
ELSE 0
END,
remaining_val=remaining_val+my_deposit.amount_with_fee_val
+ CASE
WHEN remaining_frac+my_deposit.amount_with_fee_frac >= 100000000
THEN 1
ELSE 0
END
FROM known_coins
WHERE coin_pub = my_deposit.coin_pub
LIMIT 1; -- just to be extra safe
END LOOP;
END $$;
COMMENT ON FUNCTION exchange_do_expire_purse(INT8,INT8)
IS 'Finds an expired purse in the given time range and refunds the coins (if any).';
CREATE OR REPLACE FUNCTION exchange_do_history_request(
IN in_reserve_pub BYTEA,
IN in_reserve_sig BYTEA,

View File

@ -904,6 +904,14 @@ prepare_statements (struct PostgresClosure *pg)
" FROM exchange_do_purse_deposit"
" ($1,$2,$3,$4,$5,$6,$7,$8);",
8),
/* used in #postgres_expire_purse() */
GNUNET_PQ_make_prepare (
"call_expire_purse",
"SELECT "
" out_found AS found"
" FROM exchange_do_expire_purse"
" ($1,$2);",
2),
/* Used in #postgres_do_melt() to melt a coin. */
GNUNET_PQ_make_prepare (
"call_melt",
@ -13337,7 +13345,7 @@ postgres_select_contract_by_purse (void *cls,
* @param[out] in_conflict set to true if @a econtract
* conflicts with an existing contract;
* in this case, the return value will be
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
* #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure
* @return transaction status code
*/
static enum GNUNET_DB_QueryStatus
@ -13568,8 +13576,30 @@ postgres_expire_purse (
struct GNUNET_TIME_Absolute start_time,
struct GNUNET_TIME_Absolute end_time)
{
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_absolute_time (&start_time),
GNUNET_PQ_query_param_absolute_time (&end_time),
GNUNET_PQ_query_param_end
};
bool found = false;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_bool ("found",
&found),
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"call_expire_purse",
params,
rs);
if (qs < 0)
return qs;
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
return found
? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
: GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}