-add do_purse_delete API

This commit is contained in:
Christian Grothoff 2022-12-27 21:18:12 +01:00
parent 26624bed95
commit 787c56e7e9
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
11 changed files with 197 additions and 125 deletions

View File

@ -212,6 +212,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_insert_denomination_info.h pg_insert_denomination_info.c \ pg_insert_denomination_info.h pg_insert_denomination_info.c \
pg_do_batch_withdraw_insert.h pg_do_batch_withdraw_insert.c \ pg_do_batch_withdraw_insert.h pg_do_batch_withdraw_insert.c \
pg_do_reserve_open.c pg_do_reserve_open.h \ pg_do_reserve_open.c pg_do_reserve_open.h \
pg_do_purse_delete.c pg_do_purse_delete.h \
pg_do_withdraw.h pg_do_withdraw.c \ pg_do_withdraw.h pg_do_withdraw.c \
pg_preflight.h pg_preflight.c \ pg_preflight.h pg_preflight.c \
pg_iterate_active_signkeys.h pg_iterate_active_signkeys.c \ pg_iterate_active_signkeys.h pg_iterate_active_signkeys.c \

View File

@ -0,0 +1,64 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file exchangedb/pg_do_purse_delete.c
* @brief Implementation of the do_purse_delete function for Postgres
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_error_codes.h"
#include "taler_dbevents.h"
#include "taler_pq_lib.h"
#include "pg_do_purse_delete.h"
#include "pg_helper.h"
enum GNUNET_DB_QueryStatus
TEH_PG_do_purse_delete (
void *cls,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseContractSignatureP *purse_sig,
bool *decided,
bool *found)
{
struct PostgresClosure *pg = cls;
struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (purse_pub),
GNUNET_PQ_query_param_auto_from_type (purse_sig),
GNUNET_PQ_query_param_timestamp (&now),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_bool ("decided",
decided),
GNUNET_PQ_result_spec_bool ("found",
found),
GNUNET_PQ_result_spec_end
};
PREPARE (pg,
"call_purse_delete",
"SELECT "
" out_decided AS decided"
",out_found AS found"
" FROM exchange_do_purse_delete"
" ($1,$2,$3);");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"call_purse_delete",
params,
rs);
}

View File

@ -0,0 +1,49 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file exchangedb/pg_do_purse_delete.h
* @brief implementation of the do_purse_delete function for Postgres
* @author Christian Grothoff
*/
#ifndef PG_DO_PURSE_DELETE_H
#define PG_DO_PURSE_DELETE_H
#include "taler_util.h"
#include "taler_json_lib.h"
#include "taler_exchangedb_plugin.h"
/**
* Function called to explicitly delete a purse.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param purse_pub purse to delete
* @param purse_sig signature affirming the deletion
* @param[out] decided set to true if the purse was
* already decided and thus could not be deleted
* @param[out] found set to true if the purse was found
* (if false, purse could not be deleted)
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
TEH_PG_do_purse_delete (
void *cls,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseContractSignatureP *purse_sig,
bool *decided,
bool *found);
#endif

View File

@ -43,7 +43,6 @@ TEH_PG_drop_tables (void *cls)
{ {
GNUNET_PQ_disconnect (pg->conn); GNUNET_PQ_disconnect (pg->conn);
pg->conn = NULL; pg->conn = NULL;
pg->init = false;
} }
conn = GNUNET_PQ_connect_with_cfg (pg->cfg, conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
"exchangedb-postgres", "exchangedb-postgres",

View File

@ -88,12 +88,6 @@ struct PostgresClosure
*/ */
uint32_t def_purse_limit; uint32_t def_purse_limit;
/**
* Did we initialize the prepared statements
* for this session? (To be replaced with @e prep_gen.)
*/
bool init;
}; };

View File

@ -43,6 +43,22 @@ TEH_PG_insert_refresh_reveal (
GNUNET_break (0); GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
PREPARE (pg,
"insert_refresh_revealed_coin",
"INSERT INTO refresh_revealed_coins "
"(melt_serial_id "
",freshcoin_index "
",link_sig "
",denominations_serial "
",coin_ev"
",ewv"
",h_coin_ev"
",ev_sig"
") SELECT $1, $2, $3, "
" denominations_serial, $5, $6, $7, $8"
" FROM denominations"
" WHERE denom_pub_hash=$4"
" ON CONFLICT DO NOTHING;");
for (uint32_t i = 0; i<num_rrcs; i++) for (uint32_t i = 0; i<num_rrcs; i++)
{ {
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i]; const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
@ -76,17 +92,16 @@ TEH_PG_insert_refresh_reveal (
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
/* Used in #postgres_insert_refresh_reveal() to store the transfer /* Used in #postgres_insert_refresh_reveal() to store the transfer
keys we learned */ keys we learned */
PREPARE (pg, PREPARE (pg,
"insert_refresh_transfer_keys", "insert_refresh_transfer_keys",
"INSERT INTO refresh_transfer_keys " "INSERT INTO refresh_transfer_keys "
"(melt_serial_id" "(melt_serial_id"
",transfer_pub" ",transfer_pub"
",transfer_privs" ",transfer_privs"
") VALUES ($1, $2, $3)" ") VALUES ($1, $2, $3)"
" ON CONFLICT DO NOTHING;"); " ON CONFLICT DO NOTHING;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn, return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"insert_refresh_transfer_keys", "insert_refresh_transfer_keys",
params); params);

View File

@ -30,12 +30,10 @@
* Connect to the database if the connection does not exist yet. * Connect to the database if the connection does not exist yet.
* *
* @param pg the plugin-specific state * @param pg the plugin-specific state
* @param skip_prepare true if we should skip prepared statement setup
* @return #GNUNET_OK on success * @return #GNUNET_OK on success
*/ */
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TEH_PG_internal_setup (struct PostgresClosure *pg, TEH_PG_internal_setup (struct PostgresClosure *pg);
bool skip_prepare);
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
@ -47,13 +45,9 @@ TEH_PG_preflight (void *cls)
GNUNET_PQ_EXECUTE_STATEMENT_END GNUNET_PQ_EXECUTE_STATEMENT_END
}; };
if (! pg->init) if (GNUNET_OK !=
{ TEH_PG_internal_setup (pg))
if (GNUNET_OK != return GNUNET_SYSERR;
TEH_PG_internal_setup (pg,
false))
return GNUNET_SYSERR;
}
if (NULL == pg->transaction_name) if (NULL == pg->transaction_name)
return GNUNET_OK; /* all good */ return GNUNET_OK; /* all good */
if (GNUNET_OK == if (GNUNET_OK ==

View File

@ -178,7 +178,7 @@ TEH_PG_select_refunds_above_serial_id (
}; };
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
/* Fetch refunds with rowid '\geq' the given parameter */ /* Fetch refunds with rowid '\geq' the given parameter */
PREPARE (pg, PREPARE (pg,
"audit_get_refunds_incr", "audit_get_refunds_incr",
"SELECT" "SELECT"
@ -200,6 +200,19 @@ TEH_PG_select_refunds_above_serial_id (
" ON (kc.denominations_serial=denom.denominations_serial)" " ON (kc.denominations_serial=denom.denominations_serial)"
" WHERE ref.refund_serial_id>=$1" " WHERE ref.refund_serial_id>=$1"
" ORDER BY ref.refund_serial_id ASC;"); " ORDER BY ref.refund_serial_id ASC;");
PREPARE (pg,
"test_refund_full",
"SELECT"
" CAST(SUM(CAST(ref.amount_with_fee_frac AS INT8)) AS INT8) AS s_f"
",CAST(SUM(ref.amount_with_fee_val) AS INT8) AS s_v"
",dep.amount_with_fee_val"
",dep.amount_with_fee_frac"
" FROM refunds ref"
" JOIN deposits dep"
" ON (ref.coin_pub=dep.coin_pub AND ref.deposit_serial_id=dep.deposit_serial_id)"
" WHERE ref.refund_serial_id=$1"
" GROUP BY (dep.amount_with_fee_val, dep.amount_with_fee_frac);");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"audit_get_refunds_incr", "audit_get_refunds_incr",
params, params,

View File

@ -51,6 +51,16 @@ TEH_PG_update_kyc_process_by_row (
}; };
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
PREPARE (pg,
"update_legitimization_process",
"UPDATE legitimization_processes"
" SET provider_user_id=$4"
" ,provider_legitimization_id=$5"
" ,expiration_time=GREATEST(expiration_time,$6)"
" WHERE"
" h_payto=$3"
" AND legitimization_process_serial_id=$1"
" AND provider_section=$2;");
qs = GNUNET_PQ_eval_prepared_non_select ( qs = GNUNET_PQ_eval_prepared_non_select (
pg->conn, pg->conn,
"update_legitimization_process", "update_legitimization_process",

View File

@ -23,6 +23,9 @@
* @author Marcello Stanisci * @author Marcello Stanisci
*/ */
#include "platform.h" #include "platform.h"
#include <poll.h>
#include <pthread.h>
#include <libpq-fe.h>
#include "taler_error_codes.h" #include "taler_error_codes.h"
#include "taler_dbevents.h" #include "taler_dbevents.h"
#include "taler_pq_lib.h" #include "taler_pq_lib.h"
@ -56,11 +59,6 @@
#include "pg_select_reserve_close_info.h" #include "pg_select_reserve_close_info.h"
#include "pg_select_reserve_closed_above_serial_id.h" #include "pg_select_reserve_closed_above_serial_id.h"
#include "pg_select_reserve_open_above_serial_id.h" #include "pg_select_reserve_open_above_serial_id.h"
#include <poll.h>
#include <pthread.h>
#include <libpq-fe.h>
/**NEW INCLUDES**/
#include "pg_insert_purse_request.h" #include "pg_insert_purse_request.h"
#include "pg_iterate_active_signkeys.h" #include "pg_iterate_active_signkeys.h"
#include "pg_preflight.h" #include "pg_preflight.h"
@ -94,6 +92,7 @@
#include "pg_begin_revolving_shard.h" #include "pg_begin_revolving_shard.h"
#include "pg_get_extension_manifest.h" #include "pg_get_extension_manifest.h"
#include "pg_insert_history_request.h" #include "pg_insert_history_request.h"
#include "pg_do_purse_delete.h"
#include "pg_do_purse_merge.h" #include "pg_do_purse_merge.h"
#include "pg_start_read_committed.h" #include "pg_start_read_committed.h"
#include "pg_start_read_only.h" #include "pg_start_read_only.h"
@ -232,95 +231,14 @@
} while (0) } while (0)
/**
* Initialize prepared statements for @a pg.
*
* @param[in,out] pg connection to initialize
* @return #GNUNET_OK on success
*/
enum GNUNET_GenericReturnValue
prepare_statements (struct PostgresClosure *pg)
{
enum GNUNET_GenericReturnValue ret;
struct GNUNET_PQ_PreparedStatement ps[] = {
GNUNET_PQ_make_prepare (
"get_kyc_h_payto",
"SELECT"
" wire_target_h_payto"
" FROM wire_targets"
" WHERE wire_target_h_payto=$1"
" LIMIT 1;"),
/* Used in #postgres_ensure_coin_known() */
GNUNET_PQ_make_prepare (
"get_known_coin_dh",
"SELECT"
" denominations.denom_pub_hash"
" FROM known_coins"
" JOIN denominations USING (denominations_serial)"
" WHERE coin_pub=$1;"),
/* Store information about the desired denominations for a
refresh operation, used in #postgres_insert_refresh_reveal() */
GNUNET_PQ_make_prepare (
"insert_refresh_revealed_coin",
"INSERT INTO refresh_revealed_coins "
"(melt_serial_id "
",freshcoin_index "
",link_sig "
",denominations_serial "
",coin_ev"
",ewv"
",h_coin_ev"
",ev_sig"
") SELECT $1, $2, $3, "
" denominations_serial, $5, $6, $7, $8"
" FROM denominations"
" WHERE denom_pub_hash=$4"
" ON CONFLICT DO NOTHING;"),
GNUNET_PQ_make_prepare (
"test_refund_full",
"SELECT"
" CAST(SUM(CAST(ref.amount_with_fee_frac AS INT8)) AS INT8) AS s_f"
",CAST(SUM(ref.amount_with_fee_val) AS INT8) AS s_v"
",dep.amount_with_fee_val"
",dep.amount_with_fee_frac"
" FROM refunds ref"
" JOIN deposits dep"
" ON (ref.coin_pub=dep.coin_pub AND ref.deposit_serial_id=dep.deposit_serial_id)"
" WHERE ref.refund_serial_id=$1"
" GROUP BY (dep.amount_with_fee_val, dep.amount_with_fee_frac);"),
/* Used in #postgres_update_kyc_requirement_by_row() */
GNUNET_PQ_make_prepare (
"update_legitimization_process",
"UPDATE legitimization_processes"
" SET provider_user_id=$4"
" ,provider_legitimization_id=$5"
" ,expiration_time=GREATEST(expiration_time,$6)"
" WHERE"
" h_payto=$3"
" AND legitimization_process_serial_id=$1"
" AND provider_section=$2;"),
GNUNET_PQ_PREPARED_STATEMENT_END
};
ret = GNUNET_PQ_prepare_statements (pg->conn,
ps);
if (GNUNET_OK != ret)
return ret;
pg->init = true;
return GNUNET_OK;
}
/** /**
* Connect to the database if the connection does not exist yet. * Connect to the database if the connection does not exist yet.
* *
* @param pg the plugin-specific state * @param pg the plugin-specific state
* @param skip_prepare true if we should skip prepared statement setup
* @return #GNUNET_OK on success * @return #GNUNET_OK on success
*/ */
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TEH_PG_internal_setup (struct PostgresClosure *pg, TEH_PG_internal_setup (struct PostgresClosure *pg)
bool skip_prepare)
{ {
if (NULL == pg->conn) if (NULL == pg->conn)
{ {
@ -366,11 +284,7 @@ TEH_PG_internal_setup (struct PostgresClosure *pg,
} }
if (NULL == pg->transaction_name) if (NULL == pg->transaction_name)
GNUNET_PQ_reconnect_if_down (pg->conn); GNUNET_PQ_reconnect_if_down (pg->conn);
if (pg->init) return GNUNET_OK;
return GNUNET_OK;
if (skip_prepare)
return GNUNET_OK;
return prepare_statements (pg);
} }
@ -472,8 +386,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
return NULL; return NULL;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TEH_PG_internal_setup (pg, TEH_PG_internal_setup (pg))
true))
{ {
GNUNET_free (pg->exchange_url); GNUNET_free (pg->exchange_url);
GNUNET_free (pg->currency); GNUNET_free (pg->currency);
@ -483,7 +396,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
} }
plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin); plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin);
plugin->cls = pg; plugin->cls = pg;
/* New style, sort alphabetically! */
plugin->do_reserve_open plugin->do_reserve_open
= &TEH_PG_do_reserve_open; = &TEH_PG_do_reserve_open;
plugin->drop_tables plugin->drop_tables
@ -542,7 +454,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_select_reserve_closed_above_serial_id; = &TEH_PG_select_reserve_closed_above_serial_id;
plugin->select_reserve_open_above_serial_id plugin->select_reserve_open_above_serial_id
= &TEH_PG_select_reserve_open_above_serial_id; = &TEH_PG_select_reserve_open_above_serial_id;
/*need to sort*/
plugin->insert_purse_request plugin->insert_purse_request
= &TEH_PG_insert_purse_request; = &TEH_PG_insert_purse_request;
plugin->iterate_active_signkeys plugin->iterate_active_signkeys
@ -555,7 +466,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_insert_aggregation_tracking; = &TEH_PG_insert_aggregation_tracking;
plugin->select_aggregation_amounts_for_kyc_check plugin->select_aggregation_amounts_for_kyc_check
= &TEH_PG_select_aggregation_amounts_for_kyc_check; = &TEH_PG_select_aggregation_amounts_for_kyc_check;
plugin->select_satisfied_kyc_processes plugin->select_satisfied_kyc_processes
= &TEH_PG_select_satisfied_kyc_processes; = &TEH_PG_select_satisfied_kyc_processes;
plugin->kyc_provider_account_lookup plugin->kyc_provider_account_lookup
@ -610,6 +520,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_insert_history_request; = &TEH_PG_insert_history_request;
plugin->do_purse_merge plugin->do_purse_merge
= &TEH_PG_do_purse_merge; = &TEH_PG_do_purse_merge;
plugin->do_purse_delete
= &TEH_PG_do_purse_delete;
plugin->start_read_committed plugin->start_read_committed
= &TEH_PG_start_read_committed; = &TEH_PG_start_read_committed;
plugin->start_read_only plugin->start_read_only

View File

@ -5933,6 +5933,27 @@ struct TALER_EXCHANGEDB_Plugin
bool *conflict); bool *conflict);
/**
* Function called to explicitly delete a purse.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param purse_pub purse to delete
* @param purse_sig signature affirming the deletion
* @param[out] decided set to true if the purse was
* already decided and thus could not be deleted
* @param[out] found set to true if the purse was found
* (if false, purse could not be deleted)
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
(*do_purse_delete)(
void *cls,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseContractSignatureP *purse_sig,
bool *dediced,
bool *found);
/** /**
* Set the current @a balance in the purse * Set the current @a balance in the purse
* identified by @a purse_pub. Used by the auditor * identified by @a purse_pub. Used by the auditor