/*
This file is part of TALER
Copyright (C) 2014--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
*/
/**
* @file plugin_exchangedb_postgres.c
* @brief Low-level (statement-level) Postgres database access for the exchange
* @author Florian Dold
* @author Christian Grothoff
* @author Sree Harsha Totakura
* @author Marcello Stanisci
*/
#include "platform.h"
#include "taler_error_codes.h"
#include "taler_dbevents.h"
#include "taler_pq_lib.h"
#include "taler_util.h"
#include "taler_json_lib.h"
#include "taler_exchangedb_plugin.h"
#include "plugin_exchangedb_common.h"
#include "pg_delete_aggregation_transient.h"
#include "pg_get_link_data.h"
#include "pg_helper.h"
#include "pg_do_reserve_open.h"
#include "pg_do_withdraw.h"
#include "pg_get_coin_transactions.h"
#include "pg_get_expired_reserves.h"
#include "pg_get_purse_request.h"
#include "pg_get_reserve_history.h"
#include "pg_get_unfinished_close_requests.h"
#include "pg_insert_close_request.h"
#include "pg_insert_records_by_table.h"
#include "pg_insert_reserve_open_deposit.h"
#include "pg_iterate_kyc_reference.h"
#include "pg_iterate_reserve_close_info.h"
#include "pg_lookup_records_by_table.h"
#include "pg_lookup_serial_by_table.h"
#include "pg_select_account_merges_above_serial_id.h"
#include "pg_select_all_purse_decisions_above_serial_id.h"
#include "pg_select_purse.h"
#include "pg_select_purse_deposits_above_serial_id.h"
#include "pg_select_purse_merges_above_serial_id.h"
#include "pg_select_purse_requests_above_serial_id.h"
#include "pg_select_reserve_close_info.h"
#include "pg_select_reserve_closed_above_serial_id.h"
#include "pg_select_reserve_open_above_serial_id.h"
#include
#include
#include
/**NEW INCLUDES**/
#include "pg_insert_purse_request.h"
#include "pg_iterate_active_signkeys.h"
#include "pg_preflight.h"
#include "pg_commit.h"
#include "pg_insert_aggregation_tracking.h"
#include "pg_drop_tables.h"
#include "pg_select_satisfied_kyc_processes.h"
#include "pg_select_aggregation_amounts_for_kyc_check.h"
#include "pg_kyc_provider_account_lookup.h"
#include "pg_lookup_kyc_requirement_by_row.h"
#include "pg_insert_kyc_requirement_for_account.h"
#include "pg_lookup_kyc_process_by_account.h"
#include "pg_update_kyc_process_by_row.h"
#include "pg_insert_kyc_requirement_process.h"
#include "pg_select_withdraw_amounts_for_kyc_check.h"
#include "pg_select_merge_amounts_for_kyc_check.h"
#include "pg_profit_drains_set_finished.h"
#include "pg_profit_drains_get_pending.h"
#include "pg_get_drain_profit.h"
#include "pg_get_purse_deposit.h"
#include "pg_insert_contract.h"
#include "pg_select_contract.h"
#include "pg_select_purse_merge.h"
#include "pg_select_contract_by_purse.h"
#include "pg_insert_drain_profit.h"
#include "pg_do_reserve_purse.h"
#include "pg_lookup_global_fee_by_time.h"
#include "pg_do_purse_deposit.h"
#include "pg_activate_signing_key.h"
#include "pg_update_auditor.h"
#include "pg_begin_revolving_shard.h"
#include "pg_get_extension_manifest.h"
#include "pg_insert_history_request.h"
#include "pg_do_purse_merge.h"
#include "pg_start_read_committed.h"
#include "pg_start_read_only.h"
#include "pg_insert_denomination_info.h"
#include "pg_do_batch_withdraw_insert.h"
#include "pg_lookup_wire_fee_by_time.h"
#include "pg_start.h"
#include "pg_rollback.h"
#include "pg_create_tables.h"
#include "pg_event_listen.h"
#include "pg_event_listen_cancel.h"
#include "pg_event_notify.h"
#include "pg_get_denomination_info.h"
#include "pg_iterate_denomination_info.h"
#include "pg_iterate_denominations.h"
#include "pg_iterate_active_auditors.h"
#include "pg_iterate_auditor_denominations.h"
#include "pg_reserves_get.h"
#include "pg_reserves_get_origin.h"
#include "pg_drain_kyc_alert.h"
#include "pg_reserves_in_insert.h"
#include "pg_get_withdraw_info.h"
#include "pg_do_batch_withdraw.h"
#include "pg_get_policy_details.h"
#include "pg_persist_policy_details.h"
#include "pg_do_deposit.h"
#include "pg_add_policy_fulfillment_proof.h"
#include "pg_do_melt.h"
#include "pg_do_refund.h"
#include "pg_do_recoup.h"
#include "pg_do_recoup_refresh.h"
#include "pg_get_reserve_balance.h"
#include "pg_count_known_coins.h"
#include "pg_ensure_coin_known.h"
#include "pg_get_known_coin.h"
#include "pg_get_coin_denomination.h"
#include "pg_have_deposit2.h"
#include "pg_aggregate.h"
#include "pg_create_aggregation_transient.h"
#include "pg_select_aggregation_transient.h"
#include "pg_find_aggregation_transient.h"
#include "pg_update_aggregation_transient.h"
#include "pg_get_ready_deposit.h"
#include "pg_insert_deposit.h"
#include "pg_insert_refund.h"
#include "pg_select_refunds_by_coin.h"
#include "pg_get_melt.h"
#include "pg_insert_refresh_reveal.h"
#include "pg_get_refresh_reveal.h"
#include "pg_lookup_wire_transfer.h"
#include "pg_lookup_transfer_by_deposit.h"
#include "pg_insert_wire_fee.h"
#include "pg_insert_global_fee.h"
#include "pg_get_wire_fee.h"
#include "pg_get_global_fee.h"
#include "pg_get_global_fees.h"
#include "pg_insert_reserve_closed.h"
#include "pg_wire_prepare_data_insert.h"
#include "pg_wire_prepare_data_mark_finished.h"
#include "pg_wire_prepare_data_mark_failed.h"
#include "pg_wire_prepare_data_get.h"
#include "pg_start_deferred_wire_out.h"
#include "pg_store_wire_transfer_out.h"
#include "pg_gc.h"
#include "pg_select_deposits_above_serial_id.h"
#include "pg_select_history_requests_above_serial_id.h"
#include "pg_select_purse_decisions_above_serial_id.h"
#include "pg_select_purse_deposits_by_purse.h"
#include "pg_select_refreshes_above_serial_id.h"
#include "pg_select_refunds_above_serial_id.h"
#include "pg_select_reserves_in_above_serial_id.h"
#include "pg_select_reserves_in_above_serial_id_by_account.h"
#include "pg_select_withdrawals_above_serial_id.h"
#include "pg_select_wire_out_above_serial_id.h"
#include "pg_select_wire_out_above_serial_id_by_account.h"
#include "pg_select_recoup_above_serial_id.h"
#include "pg_select_recoup_refresh_above_serial_id.h"
#include "pg_get_reserve_by_h_blind.h"
#include "pg_get_old_coin_by_h_blind.h"
#include "pg_insert_denomination_revocation.h"
#include "pg_get_denomination_revocation.h"
#include "pg_select_deposits_missing_wire.h"
#include "pg_lookup_auditor_timestamp.h"
#include "pg_lookup_auditor_status.h"
#include "pg_insert_auditor.h"
#include "pg_lookup_wire_timestamp.h"
#include "pg_insert_wire.h"
#include "pg_update_wire.h"
#include "pg_get_wire_accounts.h"
#include "pg_get_wire_fees.h"
#include "pg_insert_signkey_revocation.h"
#include "pg_lookup_signkey_revocation.h"
#include "pg_lookup_denomination_key.h"
#include "pg_insert_auditor_denom_sig.h"
#include "pg_select_auditor_denom_sig.h"
#include "pg_add_denomination_key.h"
#include "pg_lookup_signing_key.h"
#include "pg_begin_shard.h"
#include "pg_abort_shard.h"
#include "pg_complete_shard.h"
#include "pg_release_revolving_shard.h"
#include "pg_delete_shard_locks.h"
#include "pg_set_extension_manifest.h"
#include "pg_insert_partner.h"
#include "pg_expire_purse.h"
#include "pg_select_purse_by_merge_pub.h"
#include "pg_set_purse_balance.h"
#include "pg_reserves_update.h"
#include "pg_setup_wire_target.h"
#include "pg_compute_shard.h"
#include "pg_batch_reserves_in_insert.h"
#include "pg_batch2_reserves_in_insert.h"
/**
* Set to 1 to enable Postgres auto_explain module. This will
* slow down things a _lot_, but also provide extensive logging
* in the Postgres database logger for performance analysis.
*/
#define AUTO_EXPLAIN 1
/**
* Log a really unexpected PQ error with all the details we can get hold of.
*
* @param result PQ result object of the PQ operation that failed
* @param conn SQL connection that was used
*/
#define BREAK_DB_ERR(result,conn) do { \
GNUNET_break (0); \
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \
"Database failure: %s/%s/%s/%s/%s", \
PQresultErrorField (result, PG_DIAG_MESSAGE_PRIMARY), \
PQresultErrorField (result, PG_DIAG_MESSAGE_DETAIL), \
PQresultErrorMessage (result), \
PQresStatus (PQresultStatus (result)), \
PQerrorMessage (conn)); \
} 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.
*
* @param pg the plugin-specific state
* @param skip_prepare true if we should skip prepared statement setup
* @return #GNUNET_OK on success
*/
enum GNUNET_GenericReturnValue
TEH_PG_internal_setup (struct PostgresClosure *pg,
bool skip_prepare)
{
if (NULL == pg->conn)
{
#if AUTO_EXPLAIN
/* Enable verbose logging to see where queries do not
properly use indices */
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"),
GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"),
GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"),
GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"),
/* https://wiki.postgresql.org/wiki/Serializable suggests to really
force the default to 'serializable' if SSI is to be used. */
GNUNET_PQ_make_try_execute (
"SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
GNUNET_PQ_EXECUTE_STATEMENT_END
};
#else
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_try_execute (
"SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
GNUNET_PQ_make_try_execute ("SET autocommit=OFF;"),
GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
GNUNET_PQ_EXECUTE_STATEMENT_END
};
#endif
struct GNUNET_PQ_Context *db_conn;
db_conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
"exchangedb-postgres",
NULL,
es,
NULL);
if (NULL == db_conn)
return GNUNET_SYSERR;
pg->prep_gen++;
pg->conn = db_conn;
}
if (NULL == pg->transaction_name)
GNUNET_PQ_reconnect_if_down (pg->conn);
if (pg->init)
return GNUNET_OK;
if (skip_prepare)
return GNUNET_OK;
return prepare_statements (pg);
}
/**
* Initialize Postgres database subsystem.
*
* @param cls a configuration instance
* @return NULL on error, otherwise a `struct
* TALER_EXCHANGEDB_Plugin`
*/
void *
libtaler_plugin_exchangedb_postgres_init (void *cls)
{
const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
struct PostgresClosure *pg;
struct TALER_EXCHANGEDB_Plugin *plugin;
unsigned long long dpl;
pg = GNUNET_new (struct PostgresClosure);
pg->cfg = cfg;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
"exchangedb-postgres",
"SQL_DIR",
&pg->sql_dir))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchangedb-postgres",
"SQL_DIR");
GNUNET_free (pg);
return NULL;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"exchange",
"BASE_URL",
&pg->exchange_url))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"BASE_URL");
GNUNET_free (pg->sql_dir);
GNUNET_free (pg);
return NULL;
}
if ( (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (cfg,
"exchangedb",
"IDLE_RESERVE_EXPIRATION_TIME",
&pg->idle_reserve_expiration_time))
||
(GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (cfg,
"exchangedb",
"LEGAL_RESERVE_EXPIRATION_TIME",
&pg->legal_reserve_expiration_time)) )
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchangedb",
"LEGAL/IDLE_RESERVE_EXPIRATION_TIME");
GNUNET_free (pg->exchange_url);
GNUNET_free (pg->sql_dir);
GNUNET_free (pg);
return NULL;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (cfg,
"exchangedb",
"AGGREGATOR_SHIFT",
&pg->aggregator_shift))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
"exchangedb",
"AGGREGATOR_SHIFT");
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
"exchangedb",
"DEFAULT_PURSE_LIMIT",
&dpl))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
"exchangedb",
"DEFAULT_PURSE_LIMIT");
pg->def_purse_limit = 1;
}
else
{
pg->def_purse_limit = (uint32_t) dpl;
}
if (GNUNET_OK !=
TALER_config_get_currency (cfg,
&pg->currency))
{
GNUNET_free (pg->exchange_url);
GNUNET_free (pg->sql_dir);
GNUNET_free (pg);
return NULL;
}
if (GNUNET_OK !=
TEH_PG_internal_setup (pg,
true))
{
GNUNET_free (pg->exchange_url);
GNUNET_free (pg->currency);
GNUNET_free (pg->sql_dir);
GNUNET_free (pg);
return NULL;
}
plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin);
plugin->cls = pg;
/* New style, sort alphabetically! */
plugin->do_reserve_open
= &TEH_PG_do_reserve_open;
plugin->drop_tables
= &TEH_PG_drop_tables;
plugin->do_withdraw
= &TEH_PG_do_withdraw;
plugin->free_coin_transaction_list
= &TEH_COMMON_free_coin_transaction_list;
plugin->free_reserve_history
= &TEH_COMMON_free_reserve_history;
plugin->get_coin_transactions
= &TEH_PG_get_coin_transactions;
plugin->get_expired_reserves
= &TEH_PG_get_expired_reserves;
plugin->get_purse_request
= &TEH_PG_get_purse_request;
plugin->get_reserve_history
= &TEH_PG_get_reserve_history;
plugin->get_reserve_status
= &TEH_PG_get_reserve_status;
plugin->get_unfinished_close_requests
= &TEH_PG_get_unfinished_close_requests;
plugin->insert_records_by_table
= &TEH_PG_insert_records_by_table;
plugin->insert_reserve_open_deposit
= &TEH_PG_insert_reserve_open_deposit;
plugin->insert_close_request
= &TEH_PG_insert_close_request;
plugin->delete_aggregation_transient
= &TEH_PG_delete_aggregation_transient;
plugin->get_link_data
= &TEH_PG_get_link_data;
plugin->iterate_reserve_close_info
= &TEH_PG_iterate_reserve_close_info;
plugin->iterate_kyc_reference
= &TEH_PG_iterate_kyc_reference;
plugin->lookup_records_by_table
= &TEH_PG_lookup_records_by_table;
plugin->lookup_serial_by_table
= &TEH_PG_lookup_serial_by_table;
plugin->select_account_merges_above_serial_id
= &TEH_PG_select_account_merges_above_serial_id;
plugin->select_all_purse_decisions_above_serial_id
= &TEH_PG_select_all_purse_decisions_above_serial_id;
plugin->select_purse
= &TEH_PG_select_purse;
plugin->select_purse_deposits_above_serial_id
= &TEH_PG_select_purse_deposits_above_serial_id;
plugin->select_purse_merges_above_serial_id
= &TEH_PG_select_purse_merges_above_serial_id;
plugin->select_purse_requests_above_serial_id
= &TEH_PG_select_purse_requests_above_serial_id;
plugin->select_reserve_close_info
= &TEH_PG_select_reserve_close_info;
plugin->select_reserve_closed_above_serial_id
= &TEH_PG_select_reserve_closed_above_serial_id;
plugin->select_reserve_open_above_serial_id
= &TEH_PG_select_reserve_open_above_serial_id;
/*need to sort*/
plugin->insert_purse_request
= &TEH_PG_insert_purse_request;
plugin->iterate_active_signkeys
= &TEH_PG_iterate_active_signkeys;
plugin->commit
= &TEH_PG_commit;
plugin->preflight
= &TEH_PG_preflight;
plugin->insert_aggregation_tracking
= &TEH_PG_insert_aggregation_tracking;
plugin->select_aggregation_amounts_for_kyc_check
= &TEH_PG_select_aggregation_amounts_for_kyc_check;
plugin->select_satisfied_kyc_processes
= &TEH_PG_select_satisfied_kyc_processes;
plugin->kyc_provider_account_lookup
= &TEH_PG_kyc_provider_account_lookup;
plugin->lookup_kyc_requirement_by_row
= &TEH_PG_lookup_kyc_requirement_by_row;
plugin->insert_kyc_requirement_for_account
= &TEH_PG_insert_kyc_requirement_for_account;
plugin->lookup_kyc_process_by_account
= &TEH_PG_lookup_kyc_process_by_account;
plugin->update_kyc_process_by_row
= &TEH_PG_update_kyc_process_by_row;
plugin->insert_kyc_requirement_process
= &TEH_PG_insert_kyc_requirement_process;
plugin->select_withdraw_amounts_for_kyc_check
= &TEH_PG_select_withdraw_amounts_for_kyc_check;
plugin->select_merge_amounts_for_kyc_check
= &TEH_PG_select_merge_amounts_for_kyc_check;
plugin->profit_drains_set_finished
= &TEH_PG_profit_drains_set_finished;
plugin->profit_drains_get_pending
= &TEH_PG_profit_drains_get_pending;
plugin->get_drain_profit
= &TEH_PG_get_drain_profit;
plugin->get_purse_deposit
= &TEH_PG_get_purse_deposit;
plugin->insert_contract
= &TEH_PG_insert_contract;
plugin->select_contract
= &TEH_PG_select_contract;
plugin->select_purse_merge
= &TEH_PG_select_purse_merge;
plugin->select_contract_by_purse
= &TEH_PG_select_contract_by_purse;
plugin->insert_drain_profit
= &TEH_PG_insert_drain_profit;
plugin->do_reserve_purse
= &TEH_PG_do_reserve_purse;
plugin->lookup_global_fee_by_time
= &TEH_PG_lookup_global_fee_by_time;
plugin->do_purse_deposit
= &TEH_PG_do_purse_deposit;
plugin->activate_signing_key
= &TEH_PG_activate_signing_key;
plugin->update_auditor
= &TEH_PG_update_auditor;
plugin->begin_revolving_shard
= &TEH_PG_begin_revolving_shard;
plugin->get_extension_manifest
= &TEH_PG_get_extension_manifest;
plugin->insert_history_request
= &TEH_PG_insert_history_request;
plugin->do_purse_merge
= &TEH_PG_do_purse_merge;
plugin->start_read_committed
= &TEH_PG_start_read_committed;
plugin->start_read_only
= &TEH_PG_start_read_only;
plugin->insert_denomination_info
= &TEH_PG_insert_denomination_info;
plugin->do_batch_withdraw_insert
= &TEH_PG_do_batch_withdraw_insert;
plugin->lookup_wire_fee_by_time
= &TEH_PG_lookup_wire_fee_by_time;
plugin->start
= &TEH_PG_start;
plugin->rollback
= &TEH_PG_rollback;
plugin->create_tables
= &TEH_PG_create_tables;
plugin->event_listen
= &TEH_PG_event_listen;
plugin->event_listen_cancel
= &TEH_PG_event_listen_cancel;
plugin->event_notify
= &TEH_PG_event_notify;
plugin->get_denomination_info
= &TEH_PG_get_denomination_info;
plugin->iterate_denomination_info
= &TEH_PG_iterate_denomination_info;
plugin->iterate_denominations
= &TEH_PG_iterate_denominations;
plugin->iterate_active_auditors
= &TEH_PG_iterate_active_auditors;
plugin->iterate_auditor_denominations
= &TEH_PG_iterate_auditor_denominations;
plugin->reserves_get
= &TEH_PG_reserves_get;
plugin->reserves_get_origin
= &TEH_PG_reserves_get_origin;
plugin->drain_kyc_alert
= &TEH_PG_drain_kyc_alert;
plugin->reserves_in_insert
= &TEH_PG_reserves_in_insert;
plugin->get_withdraw_info
= &TEH_PG_get_withdraw_info;
plugin->do_batch_withdraw
= &TEH_PG_do_batch_withdraw;
plugin->get_policy_details
= &TEH_PG_get_policy_details;
plugin->persist_policy_details
= &TEH_PG_persist_policy_details;
plugin->do_deposit
= &TEH_PG_do_deposit;
plugin->add_policy_fulfillment_proof
= &TEH_PG_add_policy_fulfillment_proof;
plugin->do_melt
= &TEH_PG_do_melt;
plugin->do_refund
= &TEH_PG_do_refund;
plugin->do_recoup
= &TEH_PG_do_recoup;
plugin->do_recoup_refresh
= &TEH_PG_do_recoup_refresh;
plugin->get_reserve_balance
= &TEH_PG_get_reserve_balance;
plugin->count_known_coins
= &TEH_PG_count_known_coins;
plugin->ensure_coin_known
= &TEH_PG_ensure_coin_known;
plugin->get_known_coin
= &TEH_PG_get_known_coin;
plugin->get_coin_denomination
= &TEH_PG_get_coin_denomination;
plugin->have_deposit2
= &TEH_PG_have_deposit2;
plugin->aggregate
= &TEH_PG_aggregate;
plugin->create_aggregation_transient
= &TEH_PG_create_aggregation_transient;
plugin->select_aggregation_transient
= &TEH_PG_select_aggregation_transient;
plugin->find_aggregation_transient
= &TEH_PG_find_aggregation_transient;
plugin->update_aggregation_transient
= &TEH_PG_update_aggregation_transient;
plugin->get_ready_deposit
= &TEH_PG_get_ready_deposit;
plugin->insert_deposit
= &TEH_PG_insert_deposit;
plugin->insert_refund
= &TEH_PG_insert_refund;
plugin->select_refunds_by_coin
= &TEH_PG_select_refunds_by_coin;
plugin->get_melt
= &TEH_PG_get_melt;
plugin->insert_refresh_reveal
= &TEH_PG_insert_refresh_reveal;
plugin->get_refresh_reveal
= &TEH_PG_get_refresh_reveal;
plugin->lookup_wire_transfer
= &TEH_PG_lookup_wire_transfer;
plugin->lookup_transfer_by_deposit
= &TEH_PG_lookup_transfer_by_deposit;
plugin->insert_wire_fee
= &TEH_PG_insert_wire_fee;
plugin->insert_global_fee
= &TEH_PG_insert_global_fee;
plugin->get_wire_fee
= &TEH_PG_get_wire_fee;
plugin->get_global_fee
= &TEH_PG_get_global_fee;
plugin->get_global_fees
= &TEH_PG_get_global_fees;
plugin->insert_reserve_closed
= &TEH_PG_insert_reserve_closed;
plugin->wire_prepare_data_insert
= &TEH_PG_wire_prepare_data_insert;
plugin->wire_prepare_data_mark_finished
= &TEH_PG_wire_prepare_data_mark_finished;
plugin->wire_prepare_data_mark_failed
= &TEH_PG_wire_prepare_data_mark_failed;
plugin->wire_prepare_data_get
= &TEH_PG_wire_prepare_data_get;
plugin->start_deferred_wire_out
= &TEH_PG_start_deferred_wire_out;
plugin->store_wire_transfer_out
= &TEH_PG_store_wire_transfer_out;
plugin->gc
= &TEH_PG_gc;
plugin->select_deposits_above_serial_id
= &TEH_PG_select_deposits_above_serial_id;
plugin->select_history_requests_above_serial_id
= &TEH_PG_select_history_requests_above_serial_id;
plugin->select_purse_decisions_above_serial_id
= &TEH_PG_select_purse_decisions_above_serial_id;
plugin->select_purse_deposits_by_purse
= &TEH_PG_select_purse_deposits_by_purse;
plugin->select_refreshes_above_serial_id
= &TEH_PG_select_refreshes_above_serial_id;
plugin->select_refunds_above_serial_id
= &TEH_PG_select_refunds_above_serial_id;
plugin->select_reserves_in_above_serial_id
= &TEH_PG_select_reserves_in_above_serial_id;
plugin->select_reserves_in_above_serial_id_by_account
= &TEH_PG_select_reserves_in_above_serial_id_by_account;
plugin->select_withdrawals_above_serial_id
= &TEH_PG_select_withdrawals_above_serial_id;
plugin->select_wire_out_above_serial_id
= &TEH_PG_select_wire_out_above_serial_id;
plugin->select_wire_out_above_serial_id_by_account
= &TEH_PG_select_wire_out_above_serial_id_by_account;
plugin->select_recoup_above_serial_id
= &TEH_PG_select_recoup_above_serial_id;
plugin->select_recoup_refresh_above_serial_id
= &TEH_PG_select_recoup_refresh_above_serial_id;
plugin->get_reserve_by_h_blind
= &TEH_PG_get_reserve_by_h_blind;
plugin->get_old_coin_by_h_blind
= &TEH_PG_get_old_coin_by_h_blind;
plugin->insert_denomination_revocation
= &TEH_PG_insert_denomination_revocation;
plugin->get_denomination_revocation
= &TEH_PG_get_denomination_revocation;
plugin->select_deposits_missing_wire
= &TEH_PG_select_deposits_missing_wire;
plugin->lookup_auditor_timestamp
= &TEH_PG_lookup_auditor_timestamp;
plugin->lookup_auditor_status
= &TEH_PG_lookup_auditor_status;
plugin->insert_auditor
= &TEH_PG_insert_auditor;
plugin->lookup_wire_timestamp
= &TEH_PG_lookup_wire_timestamp;
plugin->insert_wire
= &TEH_PG_insert_wire;
plugin->update_wire
= &TEH_PG_update_wire;
plugin->get_wire_accounts
= &TEH_PG_get_wire_accounts;
plugin->get_wire_fees
= &TEH_PG_get_wire_fees;
plugin->insert_signkey_revocation
= &TEH_PG_insert_signkey_revocation;
plugin->lookup_signkey_revocation
= &TEH_PG_lookup_signkey_revocation;
plugin->lookup_denomination_key
= &TEH_PG_lookup_denomination_key;
plugin->insert_auditor_denom_sig
= &TEH_PG_insert_auditor_denom_sig;
plugin->select_auditor_denom_sig
= &TEH_PG_select_auditor_denom_sig;
plugin->add_denomination_key
= &TEH_PG_add_denomination_key;
plugin->lookup_signing_key
= &TEH_PG_lookup_signing_key;
plugin->begin_shard
= &TEH_PG_begin_shard;
plugin->abort_shard
= &TEH_PG_abort_shard;
plugin->complete_shard
= &TEH_PG_complete_shard;
plugin->release_revolving_shard
= &TEH_PG_release_revolving_shard;
plugin->delete_shard_locks
= &TEH_PG_delete_shard_locks;
plugin->set_extension_manifest
= &TEH_PG_set_extension_manifest;
plugin->insert_partner
= &TEH_PG_insert_partner;
plugin->expire_purse
= &TEH_PG_expire_purse;
plugin->select_purse_by_merge_pub
= &TEH_PG_select_purse_by_merge_pub;
plugin->set_purse_balance
= &TEH_PG_set_purse_balance;
plugin->batch_reserves_in_insert
= &TEH_PG_batch_reserves_in_insert;
plugin->batch2_reserves_in_insert
= &TEH_PG_batch2_reserves_in_insert;
return plugin;
}
/**
* Shutdown Postgres database subsystem.
*
* @param cls a `struct TALER_EXCHANGEDB_Plugin`
* @return NULL (always)
*/
void *
libtaler_plugin_exchangedb_postgres_done (void *cls)
{
struct TALER_EXCHANGEDB_Plugin *plugin = cls;
struct PostgresClosure *pg = plugin->cls;
if (NULL != pg->conn)
{
GNUNET_PQ_disconnect (pg->conn);
pg->conn = NULL;
}
GNUNET_free (pg->exchange_url);
GNUNET_free (pg->sql_dir);
GNUNET_free (pg->currency);
GNUNET_free (pg);
GNUNET_free (plugin);
return NULL;
}
/* end of plugin_exchangedb_postgres.c */