exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

plugin_exchangedb_postgres.c (29960B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2014--2025 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify it under the
      6    terms of the GNU General Public License as published by the Free Software
      7    Foundation; either version 3, or (at your option) any later version.
      8 
      9    TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13    You should have received a copy of the GNU General Public License along with
     14    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 
     17 /**
     18  * @file plugin_exchangedb_postgres.c
     19  * @brief Low-level (statement-level) Postgres database access for the exchange
     20  * @author Florian Dold
     21  * @author Christian Grothoff
     22  * @author Sree Harsha Totakura
     23  * @author Marcello Stanisci
     24  * @author Özgür Kesim
     25  */
     26 #include "taler/platform.h"
     27 #include <poll.h>
     28 #include <pthread.h>
     29 #include <libpq-fe.h>
     30 #include "pg_abort_shard.h"
     31 #include "pg_activate_signing_key.h"
     32 #include "pg_add_denomination_key.h"
     33 #include "pg_add_policy_fulfillment_proof.h"
     34 #include "pg_aggregate.h"
     35 #include "pg_batch_ensure_coin_known.h"
     36 #include "pg_begin_revolving_shard.h"
     37 #include "pg_begin_shard.h"
     38 #include "pg_clear_aml_lock.h"
     39 #include "pg_commit.h"
     40 #include "pg_complete_shard.h"
     41 #include "pg_compute_shard.h"
     42 #include "pg_count_known_coins.h"
     43 #include "pg_create_aggregation_transient.h"
     44 #include "pg_create_tables.h"
     45 #include "pg_delete_aggregation_transient.h"
     46 #include "pg_delete_shard_locks.h"
     47 #include "pg_disable_rules.h"
     48 #include "pg_do_withdraw.h"
     49 #include "pg_do_check_deposit_idempotent.h"
     50 #include "pg_do_deposit.h"
     51 #include "pg_do_purse_delete.h"
     52 #include "pg_do_purse_deposit.h"
     53 #include "pg_do_purse_merge.h"
     54 #include "pg_do_recoup.h"
     55 #include "pg_do_recoup_refresh.h"
     56 #include "pg_do_refresh.h"
     57 #include "pg_do_refund.h"
     58 #include "pg_do_reserve_open.h"
     59 #include "pg_do_reserve_purse.h"
     60 #include "pg_drain_kyc_alert.h"
     61 #include "pg_drop_tables.h"
     62 #include "pg_enable_rules.h"
     63 #include "pg_ensure_coin_known.h"
     64 #include "pg_event_listen.h"
     65 #include "pg_event_listen_cancel.h"
     66 #include "pg_event_notify.h"
     67 #include "pg_expire_purse.h"
     68 #include "pg_find_aggregation_transient.h"
     69 #include "pg_gc.h"
     70 #include "pg_get_withdraw.h"
     71 #include "pg_get_coin_denomination.h"
     72 #include "pg_get_coin_transactions.h"
     73 #include "pg_get_denomination_info.h"
     74 #include "pg_get_denomination_by_serial.h"
     75 #include "pg_get_denomination_revocation.h"
     76 #include "pg_get_drain_profit.h"
     77 #include "pg_get_expired_reserves.h"
     78 #include "pg_get_extension_manifest.h"
     79 #include "pg_get_global_fee.h"
     80 #include "pg_get_global_fees.h"
     81 #include "pg_get_known_coin.h"
     82 #include "pg_get_kyc_rules.h"
     83 #include "pg_get_old_coin_by_h_blind.h"
     84 #include "pg_get_pending_kyc_requirement_process.h"
     85 #include "pg_get_policy_details.h"
     86 #include "pg_get_purse_deposit.h"
     87 #include "pg_get_purse_request.h"
     88 #include "pg_get_ready_deposit.h"
     89 #include "pg_get_refresh.h"
     90 #include "pg_get_reserve_balance.h"
     91 #include "pg_get_reserve_by_h_planchets.h"
     92 #include "pg_get_reserve_history.h"
     93 #include "pg_get_signature_for_known_coin.h"
     94 #include "pg_get_unfinished_close_requests.h"
     95 #include "pg_get_wire_accounts.h"
     96 #include "pg_get_wire_fee.h"
     97 #include "pg_get_wire_fees.h"
     98 #include "pg_get_wire_hash_for_contract.h"
     99 #include "pg_have_deposit2.h"
    100 #include "pg_helper.h"
    101 #include "pg_inject_auditor_triggers.h"
    102 #include "pg_insert_active_legitimization_measure.h"
    103 #include "pg_insert_aml_decision.h"
    104 #include "pg_insert_aml_officer.h"
    105 #include "pg_insert_aml_program_failure.h"
    106 #include "pg_insert_auditor.h"
    107 #include "pg_insert_auditor_denom_sig.h"
    108 #include "pg_insert_close_request.h"
    109 #include "pg_insert_contract.h"
    110 #include "pg_insert_denomination_info.h"
    111 #include "pg_insert_denomination_revocation.h"
    112 #include "pg_insert_drain_profit.h"
    113 #include "pg_insert_global_fee.h"
    114 #include "pg_insert_kyc_failure.h"
    115 #include "pg_insert_kyc_requirement_process.h"
    116 #include "pg_insert_partner.h"
    117 #include "pg_insert_purse_request.h"
    118 #include "pg_insert_records_by_table.h"
    119 #include "pg_insert_refund.h"
    120 #include "pg_insert_reserve_closed.h"
    121 #include "pg_insert_reserve_open_deposit.h"
    122 #include "pg_insert_sanction_list_hit.h"
    123 #include "pg_insert_signkey_revocation.h"
    124 #include "pg_insert_successor_measure.h"
    125 #include "pg_insert_wire.h"
    126 #include "pg_insert_wire_fee.h"
    127 #include "pg_iterate_active_auditors.h"
    128 #include "pg_iterate_active_signkeys.h"
    129 #include "pg_iterate_auditor_denominations.h"
    130 #include "pg_iterate_denomination_info.h"
    131 #include "pg_iterate_denominations.h"
    132 #include "pg_iterate_kyc_reference.h"
    133 #include "pg_iterate_reserve_close_info.h"
    134 #include "pg_kyc_provider_account_lookup.h"
    135 #include "pg_kycauth_in_insert.h"
    136 #include "pg_lookup_active_legitimization.h"
    137 #include "pg_lookup_aml_file_number.h"
    138 #include "pg_lookup_aml_history.h"
    139 #include "pg_lookup_aml_officer.h"
    140 #include "pg_lookup_auditor_status.h"
    141 #include "pg_lookup_auditor_timestamp.h"
    142 #include "pg_lookup_completed_legitimization.h"
    143 #include "pg_lookup_denomination_key.h"
    144 #include "pg_lookup_global_fee_by_time.h"
    145 #include "pg_lookup_h_payto_by_access_token.h"
    146 #include "pg_lookup_kyc_history.h"
    147 #include "pg_lookup_kyc_process_by_account.h"
    148 #include "pg_lookup_kyc_requirement_by_row.h"
    149 #include "pg_lookup_kyc_status_by_token.h"
    150 #include "pg_lookup_pending_legitimization.h"
    151 #include "pg_lookup_records_by_table.h"
    152 #include "pg_lookup_rules_by_access_token.h"
    153 #include "pg_lookup_serial_by_table.h"
    154 #include "pg_lookup_signing_key.h"
    155 #include "pg_lookup_signkey_revocation.h"
    156 #include "pg_lookup_transfer_by_deposit.h"
    157 #include "pg_lookup_wire_fee_by_time.h"
    158 #include "pg_lookup_wire_timestamp.h"
    159 #include "pg_lookup_wire_transfer.h"
    160 #include "pg_mark_refresh_reveal_success.h"
    161 #include "pg_persist_kyc_attributes.h"
    162 #include "pg_persist_policy_details.h"
    163 #include "pg_preflight.h"
    164 #include "pg_profit_drains_get_pending.h"
    165 #include "pg_profit_drains_set_finished.h"
    166 #include "pg_release_revolving_shard.h"
    167 #include "pg_reserves_get.h"
    168 #include "pg_reserves_get_origin.h"
    169 #include "pg_reserves_in_insert.h"
    170 #include "pg_reserves_update.h"
    171 #include "pg_rollback.h"
    172 #include "pg_select_account_merges_above_serial_id.h"
    173 #include "pg_select_aggregation_amounts_for_kyc_check.h"
    174 #include "pg_select_aggregation_transient.h"
    175 #include "pg_select_aggregations_above_serial.h"
    176 #include "pg_select_all_kyc_attributes.h"
    177 #include "pg_select_all_purse_decisions_above_serial_id.h"
    178 #include "pg_select_all_purse_deletions_above_serial_id.h"
    179 #include "pg_select_aml_attributes.h"
    180 #include "pg_select_aml_decisions.h"
    181 #include "pg_select_aml_measures.h"
    182 #include "pg_select_aml_statistics.h"
    183 #include "pg_select_auditor_denom_sig.h"
    184 #include "pg_select_batch_deposits_missing_wire.h"
    185 #include "pg_select_coin_deposits_above_serial_id.h"
    186 #include "pg_select_contract.h"
    187 #include "pg_select_contract_by_purse.h"
    188 #include "pg_select_deposit_amounts_for_kyc_check.h"
    189 #include "pg_select_exchange_credit_transfers.h"
    190 #include "pg_select_exchange_debit_transfers.h"
    191 #include "pg_select_exchange_kycauth_transfers.h"
    192 #include "pg_select_kyc_accounts.h"
    193 #include "pg_select_kyc_attributes.h"
    194 #include "pg_select_merge_amounts_for_kyc_check.h"
    195 #include "pg_select_purse.h"
    196 #include "pg_select_purse_by_merge_pub.h"
    197 #include "pg_select_purse_decisions_above_serial_id.h"
    198 #include "pg_select_purse_deposits_above_serial_id.h"
    199 #include "pg_select_purse_deposits_by_purse.h"
    200 #include "pg_select_purse_merge.h"
    201 #include "pg_select_purse_merges_above_serial_id.h"
    202 #include "pg_select_purse_requests_above_serial_id.h"
    203 #include "pg_select_recoup_above_serial_id.h"
    204 #include "pg_select_recoup_refresh_above_serial_id.h"
    205 #include "pg_select_refreshes_above_serial_id.h"
    206 #include "pg_select_refunds_above_serial_id.h"
    207 #include "pg_select_refunds_by_coin.h"
    208 #include "pg_select_reserve_close_info.h"
    209 #include "pg_select_reserve_closed_above_serial_id.h"
    210 #include "pg_select_reserve_open_above_serial_id.h"
    211 #include "pg_select_reserves_in_above_serial_id.h"
    212 #include "pg_select_reserves_in_above_serial_id_by_account.h"
    213 #include "pg_select_wire_out_above_serial_id.h"
    214 #include "pg_select_wire_out_above_serial_id_by_account.h"
    215 #include "pg_select_withdraw_amounts_for_kyc_check.h"
    216 #include "pg_select_withdrawals_above_serial_id.h"
    217 #include "pg_set_aml_lock.h"
    218 #include "pg_set_extension_manifest.h"
    219 #include "pg_set_purse_balance.h"
    220 #include "pg_start.h"
    221 #include "pg_start_deferred_wire_out.h"
    222 #include "pg_start_read_committed.h"
    223 #include "pg_start_read_only.h"
    224 #include "pg_store_wire_transfer_out.h"
    225 #include "pg_test_aml_officer.h"
    226 #include "pg_trigger_kyc_rule_for_account.h"
    227 #include "pg_update_aggregation_transient.h"
    228 #include "pg_update_auditor.h"
    229 #include "pg_update_kyc_process_by_row.h"
    230 #include "pg_update_wire.h"
    231 #include "pg_wad_in_insert.h"
    232 #include "pg_wire_prepare_data_get.h"
    233 #include "pg_wire_prepare_data_insert.h"
    234 #include "pg_wire_prepare_data_mark_failed.h"
    235 #include "pg_wire_prepare_data_mark_finished.h"
    236 #include "plugin_exchangedb_common.h"
    237 #include "plugin_exchangedb_postgres.h"
    238 #include "taler/taler_dbevents.h"
    239 #include "taler/taler_error_codes.h"
    240 #include "taler/taler_exchangedb_plugin.h"
    241 #include "taler/taler_json_lib.h"
    242 #include "taler/taler_pq_lib.h"
    243 #include "taler/taler_util.h"
    244 
    245 /**
    246  * Set to 1 to enable Postgres auto_explain module. This will
    247  * slow down things a _lot_, but also provide extensive logging
    248  * in the Postgres database logger for performance analysis.
    249  */
    250 #define AUTO_EXPLAIN 0
    251 
    252 
    253 /**
    254  * Log a really unexpected PQ error with all the details we can get hold of.
    255  *
    256  * @param result PQ result object of the PQ operation that failed
    257  * @param conn SQL connection that was used
    258  */
    259 #define BREAK_DB_ERR(result,conn) do {                                  \
    260           GNUNET_break (0);                                                   \
    261           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                                \
    262                       "Database failure: %s/%s/%s/%s/%s",                     \
    263                       PQresultErrorField (result, PG_DIAG_MESSAGE_PRIMARY),   \
    264                       PQresultErrorField (result, PG_DIAG_MESSAGE_DETAIL),    \
    265                       PQresultErrorMessage (result),                          \
    266                       PQresStatus (PQresultStatus (result)),                  \
    267                       PQerrorMessage (conn));                                 \
    268 } while (0)
    269 
    270 
    271 /**
    272  * Initialize Postgres database subsystem.
    273  *
    274  * @param cls a configuration instance
    275  * @return NULL on error, otherwise a `struct
    276  *         TALER_EXCHANGEDB_Plugin`
    277  */
    278 void *
    279 libtaler_plugin_exchangedb_postgres_init (void *cls);
    280 
    281 /* Declaration used to squash compiler warning */
    282 void *
    283 libtaler_plugin_exchangedb_postgres_init (void *cls)
    284 {
    285   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    286   struct PostgresClosure *pg;
    287   struct TALER_EXCHANGEDB_Plugin *plugin;
    288   unsigned long long dpl;
    289 
    290   pg = GNUNET_new (struct PostgresClosure);
    291   plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin);
    292   pg->cfg = cfg;
    293   if (GNUNET_OK !=
    294       GNUNET_CONFIGURATION_get_value_filename (cfg,
    295                                                "exchangedb-postgres",
    296                                                "SQL_DIR",
    297                                                &pg->sql_dir))
    298   {
    299     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    300                                "exchangedb-postgres",
    301                                "SQL_DIR");
    302     goto fail;
    303   }
    304   if (GNUNET_OK !=
    305       GNUNET_CONFIGURATION_get_value_string (cfg,
    306                                              "exchange",
    307                                              "BASE_URL",
    308                                              &pg->exchange_url))
    309   {
    310     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    311                                "exchange",
    312                                "BASE_URL");
    313     goto fail;
    314   }
    315   if (GNUNET_OK !=
    316       GNUNET_CONFIGURATION_get_value_time (cfg,
    317                                            "exchangedb",
    318                                            "IDLE_RESERVE_EXPIRATION_TIME",
    319                                            &pg->idle_reserve_expiration_time))
    320   {
    321     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    322                                "exchangedb",
    323                                "IDLE_RESERVE_EXPIRATION_TIME");
    324     goto fail;
    325   }
    326   if (GNUNET_OK !=
    327       GNUNET_CONFIGURATION_get_value_time (cfg,
    328                                            "exchangedb",
    329                                            "MAX_AML_PROGRAM_RUNTIME",
    330                                            &plugin->max_aml_program_runtime))
    331   {
    332     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    333                                "exchangedb",
    334                                "MAX_AML_PROGRAM_RUNTIME");
    335     goto fail;
    336   }
    337   if (GNUNET_OK !=
    338       GNUNET_CONFIGURATION_get_value_time (cfg,
    339                                            "exchangedb",
    340                                            "LEGAL_RESERVE_EXPIRATION_TIME",
    341                                            &pg->legal_reserve_expiration_time))
    342   {
    343     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    344                                "exchangedb",
    345                                "LEGAL_RESERVE_EXPIRATION_TIME");
    346     goto fail;
    347   }
    348   if (GNUNET_OK !=
    349       GNUNET_CONFIGURATION_get_value_time (cfg,
    350                                            "exchangedb",
    351                                            "AGGREGATOR_SHIFT",
    352                                            &pg->aggregator_shift))
    353   {
    354     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
    355                                "exchangedb",
    356                                "AGGREGATOR_SHIFT");
    357   }
    358   if (GNUNET_OK !=
    359       GNUNET_CONFIGURATION_get_value_number (cfg,
    360                                              "exchangedb",
    361                                              "DEFAULT_PURSE_LIMIT",
    362                                              &dpl))
    363   {
    364     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
    365                                "exchangedb",
    366                                "DEFAULT_PURSE_LIMIT");
    367     pg->def_purse_limit = 1;
    368   }
    369   else
    370   {
    371     pg->def_purse_limit = (uint32_t) dpl;
    372   }
    373 
    374   if (GNUNET_OK !=
    375       TALER_config_get_currency (cfg,
    376                                  "exchange",
    377                                  &pg->currency))
    378   {
    379     goto fail;
    380   }
    381   plugin->cls = pg;
    382   plugin->do_reserve_open
    383     = &TEH_PG_do_reserve_open;
    384   plugin->drop_tables
    385     = &TEH_PG_drop_tables;
    386   plugin->free_coin_transaction_list
    387     = &TEH_COMMON_free_coin_transaction_list;
    388   plugin->free_reserve_history
    389     = &TEH_COMMON_free_reserve_history;
    390   plugin->get_coin_transactions
    391     = &TEH_PG_get_coin_transactions;
    392   plugin->get_expired_reserves
    393     = &TEH_PG_get_expired_reserves;
    394   plugin->get_purse_request
    395     = &TEH_PG_get_purse_request;
    396   plugin->get_reserve_history
    397     = &TEH_PG_get_reserve_history;
    398   plugin->get_unfinished_close_requests
    399     = &TEH_PG_get_unfinished_close_requests;
    400   plugin->insert_records_by_table
    401     = &TEH_PG_insert_records_by_table;
    402   plugin->insert_reserve_open_deposit
    403     = &TEH_PG_insert_reserve_open_deposit;
    404   plugin->insert_close_request
    405     = &TEH_PG_insert_close_request;
    406   plugin->delete_aggregation_transient
    407     = &TEH_PG_delete_aggregation_transient;
    408   plugin->iterate_reserve_close_info
    409     = &TEH_PG_iterate_reserve_close_info;
    410   plugin->iterate_kyc_reference
    411     = &TEH_PG_iterate_kyc_reference;
    412   plugin->lookup_records_by_table
    413     = &TEH_PG_lookup_records_by_table;
    414   plugin->lookup_serial_by_table
    415     = &TEH_PG_lookup_serial_by_table;
    416   plugin->select_account_merges_above_serial_id
    417     = &TEH_PG_select_account_merges_above_serial_id;
    418   plugin->select_all_purse_decisions_above_serial_id
    419     = &TEH_PG_select_all_purse_decisions_above_serial_id;
    420   plugin->select_all_purse_deletions_above_serial_id
    421     = &TEH_PG_select_all_purse_deletions_above_serial_id;
    422   plugin->select_purse
    423     = &TEH_PG_select_purse;
    424   plugin->select_purse_deposits_above_serial_id
    425     = &TEH_PG_select_purse_deposits_above_serial_id;
    426   plugin->select_purse_merges_above_serial_id
    427     = &TEH_PG_select_purse_merges_above_serial_id;
    428   plugin->select_purse_requests_above_serial_id
    429     = &TEH_PG_select_purse_requests_above_serial_id;
    430   plugin->select_reserve_close_info
    431     = &TEH_PG_select_reserve_close_info;
    432   plugin->select_reserve_closed_above_serial_id
    433     = &TEH_PG_select_reserve_closed_above_serial_id;
    434   plugin->select_reserve_open_above_serial_id
    435     = &TEH_PG_select_reserve_open_above_serial_id;
    436   plugin->insert_purse_request
    437     = &TEH_PG_insert_purse_request;
    438   plugin->iterate_active_signkeys
    439     = &TEH_PG_iterate_active_signkeys;
    440   plugin->commit
    441     = &TEH_PG_commit;
    442   plugin->preflight
    443     = &TEH_PG_preflight;
    444   plugin->select_aggregation_amounts_for_kyc_check
    445     = &TEH_PG_select_aggregation_amounts_for_kyc_check;
    446   plugin->get_kyc_rules
    447     = &TEH_PG_get_kyc_rules;
    448   plugin->get_kyc_rules2
    449     = &TEH_PG_get_kyc_rules2;
    450   plugin->kyc_provider_account_lookup
    451     = &TEH_PG_kyc_provider_account_lookup;
    452   plugin->lookup_kyc_process_by_account
    453     = &TEH_PG_lookup_kyc_process_by_account;
    454   plugin->update_kyc_process_by_row
    455     = &TEH_PG_update_kyc_process_by_row;
    456   plugin->insert_kyc_requirement_process
    457     = &TEH_PG_insert_kyc_requirement_process;
    458   plugin->select_withdraw_amounts_for_kyc_check
    459     = &TEH_PG_select_withdraw_amounts_for_kyc_check;
    460   plugin->select_merge_amounts_for_kyc_check
    461     = &TEH_PG_select_merge_amounts_for_kyc_check;
    462   plugin->profit_drains_set_finished
    463     = &TEH_PG_profit_drains_set_finished;
    464   plugin->profit_drains_get_pending
    465     = &TEH_PG_profit_drains_get_pending;
    466   plugin->get_drain_profit
    467     = &TEH_PG_get_drain_profit;
    468   plugin->get_purse_deposit
    469     = &TEH_PG_get_purse_deposit;
    470   plugin->insert_contract
    471     = &TEH_PG_insert_contract;
    472   plugin->select_contract
    473     = &TEH_PG_select_contract;
    474   plugin->select_purse_merge
    475     = &TEH_PG_select_purse_merge;
    476   plugin->select_contract_by_purse
    477     = &TEH_PG_select_contract_by_purse;
    478   plugin->insert_drain_profit
    479     = &TEH_PG_insert_drain_profit;
    480   plugin->do_reserve_purse
    481     = &TEH_PG_do_reserve_purse;
    482   plugin->lookup_global_fee_by_time
    483     = &TEH_PG_lookup_global_fee_by_time;
    484   plugin->do_purse_deposit
    485     = &TEH_PG_do_purse_deposit;
    486   plugin->activate_signing_key
    487     = &TEH_PG_activate_signing_key;
    488   plugin->update_auditor
    489     = &TEH_PG_update_auditor;
    490   plugin->begin_revolving_shard
    491     = &TEH_PG_begin_revolving_shard;
    492   plugin->get_extension_manifest
    493     = &TEH_PG_get_extension_manifest;
    494   plugin->do_purse_merge
    495     = &TEH_PG_do_purse_merge;
    496   plugin->do_purse_delete
    497     = &TEH_PG_do_purse_delete;
    498   plugin->start_read_committed
    499     = &TEH_PG_start_read_committed;
    500   plugin->start_read_only
    501     = &TEH_PG_start_read_only;
    502   plugin->insert_denomination_info
    503     = &TEH_PG_insert_denomination_info;
    504   plugin->lookup_wire_fee_by_time
    505     = &TEH_PG_lookup_wire_fee_by_time;
    506   plugin->start
    507     = &TEH_PG_start;
    508   plugin->rollback
    509     = &TEH_PG_rollback;
    510   plugin->create_tables
    511     = &TEH_PG_create_tables;
    512   plugin->event_listen
    513     = &TEH_PG_event_listen;
    514   plugin->event_listen_cancel
    515     = &TEH_PG_event_listen_cancel;
    516   plugin->event_notify
    517     = &TEH_PG_event_notify;
    518   plugin->get_denomination_info
    519     = &TEH_PG_get_denomination_info;
    520   plugin->get_denomination_by_serial
    521     = &TEH_PG_get_denomination_by_serial;
    522   plugin->iterate_denomination_info
    523     = &TEH_PG_iterate_denomination_info;
    524   plugin->iterate_denominations
    525     = &TEH_PG_iterate_denominations;
    526   plugin->iterate_active_auditors
    527     = &TEH_PG_iterate_active_auditors;
    528   plugin->iterate_auditor_denominations
    529     = &TEH_PG_iterate_auditor_denominations;
    530   plugin->lookup_rules_by_access_token
    531     = &TEH_PG_lookup_rules_by_access_token;
    532   plugin->reserves_get
    533     = &TEH_PG_reserves_get;
    534   plugin->reserves_get_origin
    535     = &TEH_PG_reserves_get_origin;
    536   plugin->drain_kyc_alert
    537     = &TEH_PG_drain_kyc_alert;
    538   plugin->reserves_in_insert
    539     = &TEH_PG_reserves_in_insert;
    540   plugin->do_withdraw
    541     = &TEH_PG_do_withdraw;
    542   plugin->get_withdraw
    543     = &TEH_PG_get_withdraw;
    544   plugin->wad_in_insert
    545     = &TEH_PG_wad_in_insert;
    546   plugin->kycauth_in_insert
    547     = &TEH_PG_kycauth_in_insert;
    548   plugin->get_policy_details
    549     = &TEH_PG_get_policy_details;
    550   plugin->persist_policy_details
    551     = &TEH_PG_persist_policy_details;
    552   plugin->do_deposit
    553     = &TEH_PG_do_deposit;
    554   plugin->get_wire_hash_for_contract
    555     = &TEH_PG_get_wire_hash_for_contract;
    556   plugin->add_policy_fulfillment_proof
    557     = &TEH_PG_add_policy_fulfillment_proof;
    558   plugin->do_refresh
    559     = &TEH_PG_do_refresh;
    560   plugin->mark_refresh_reveal_success
    561     = &TEH_PG_mark_refresh_reveal_success;
    562   plugin->do_refund
    563     = &TEH_PG_do_refund;
    564   plugin->do_recoup
    565     = &TEH_PG_do_recoup;
    566   plugin->do_recoup_refresh
    567     = &TEH_PG_do_recoup_refresh;
    568   plugin->get_reserve_balance
    569     = &TEH_PG_get_reserve_balance;
    570   plugin->count_known_coins
    571     = &TEH_PG_count_known_coins;
    572   plugin->ensure_coin_known
    573     = &TEH_PG_ensure_coin_known;
    574   plugin->get_known_coin
    575     = &TEH_PG_get_known_coin;
    576   plugin->get_signature_for_known_coin
    577     = &TEH_PG_get_signature_for_known_coin;
    578   plugin->get_coin_denomination
    579     = &TEH_PG_get_coin_denomination;
    580   plugin->have_deposit2
    581     = &TEH_PG_have_deposit2;
    582   plugin->aggregate
    583     = &TEH_PG_aggregate;
    584   plugin->create_aggregation_transient
    585     = &TEH_PG_create_aggregation_transient;
    586   plugin->select_aggregation_transient
    587     = &TEH_PG_select_aggregation_transient;
    588   plugin->find_aggregation_transient
    589     = &TEH_PG_find_aggregation_transient;
    590   plugin->update_aggregation_transient
    591     = &TEH_PG_update_aggregation_transient;
    592   plugin->get_ready_deposit
    593     = &TEH_PG_get_ready_deposit;
    594   plugin->insert_refund
    595     = &TEH_PG_insert_refund;
    596   plugin->select_refunds_by_coin
    597     = &TEH_PG_select_refunds_by_coin;
    598   plugin->select_aml_measures
    599     = &TEH_PG_select_aml_measures;
    600   plugin->get_refresh
    601     = &TEH_PG_get_refresh;
    602   plugin->lookup_wire_transfer
    603     = &TEH_PG_lookup_wire_transfer;
    604   plugin->lookup_transfer_by_deposit
    605     = &TEH_PG_lookup_transfer_by_deposit;
    606   plugin->insert_wire_fee
    607     = &TEH_PG_insert_wire_fee;
    608   plugin->insert_global_fee
    609     = &TEH_PG_insert_global_fee;
    610   plugin->get_wire_fee
    611     = &TEH_PG_get_wire_fee;
    612   plugin->get_global_fee
    613     = &TEH_PG_get_global_fee;
    614   plugin->get_global_fees
    615     = &TEH_PG_get_global_fees;
    616   plugin->insert_reserve_closed
    617     = &TEH_PG_insert_reserve_closed;
    618   plugin->wire_prepare_data_insert
    619     = &TEH_PG_wire_prepare_data_insert;
    620   plugin->wire_prepare_data_mark_finished
    621     = &TEH_PG_wire_prepare_data_mark_finished;
    622   plugin->wire_prepare_data_mark_failed
    623     = &TEH_PG_wire_prepare_data_mark_failed;
    624   plugin->wire_prepare_data_get
    625     = &TEH_PG_wire_prepare_data_get;
    626   plugin->start_deferred_wire_out
    627     = &TEH_PG_start_deferred_wire_out;
    628   plugin->store_wire_transfer_out
    629     = &TEH_PG_store_wire_transfer_out;
    630   plugin->gc
    631     = &TEH_PG_gc;
    632   plugin->select_coin_deposits_above_serial_id
    633     = &TEH_PG_select_coin_deposits_above_serial_id;
    634   plugin->lookup_aml_file_number
    635     = &TEH_PG_lookup_aml_file_number;
    636   plugin->lookup_aml_history
    637     = &TEH_PG_lookup_aml_history;
    638   plugin->lookup_kyc_history
    639     = &TEH_PG_lookup_kyc_history;
    640   plugin->select_purse_decisions_above_serial_id
    641     = &TEH_PG_select_purse_decisions_above_serial_id;
    642   plugin->select_purse_deposits_by_purse
    643     = &TEH_PG_select_purse_deposits_by_purse;
    644   plugin->select_refreshes_above_serial_id
    645     = &TEH_PG_select_refreshes_above_serial_id;
    646   plugin->select_refunds_above_serial_id
    647     = &TEH_PG_select_refunds_above_serial_id;
    648   plugin->select_reserves_in_above_serial_id
    649     = &TEH_PG_select_reserves_in_above_serial_id;
    650   plugin->select_reserves_in_above_serial_id_by_account
    651     = &TEH_PG_select_reserves_in_above_serial_id_by_account;
    652   plugin->select_withdrawals_above_serial_id
    653     = &TEH_PG_select_withdrawals_above_serial_id;
    654   plugin->select_wire_out_above_serial_id
    655     = &TEH_PG_select_wire_out_above_serial_id;
    656   plugin->select_wire_out_above_serial_id_by_account
    657     = &TEH_PG_select_wire_out_above_serial_id_by_account;
    658   plugin->select_recoup_above_serial_id
    659     = &TEH_PG_select_recoup_above_serial_id;
    660   plugin->select_recoup_refresh_above_serial_id
    661     = &TEH_PG_select_recoup_refresh_above_serial_id;
    662   plugin->get_reserve_by_h_planchets
    663     = &TEH_PG_get_reserve_by_h_planchets;
    664   plugin->get_old_coin_by_h_blind
    665     = &TEH_PG_get_old_coin_by_h_blind;
    666   plugin->insert_denomination_revocation
    667     = &TEH_PG_insert_denomination_revocation;
    668   plugin->get_denomination_revocation
    669     = &TEH_PG_get_denomination_revocation;
    670   plugin->select_batch_deposits_missing_wire
    671     = &TEH_PG_select_batch_deposits_missing_wire;
    672   plugin->select_aggregations_above_serial
    673     = &TEH_PG_select_aggregations_above_serial;
    674   plugin->lookup_auditor_timestamp
    675     = &TEH_PG_lookup_auditor_timestamp;
    676   plugin->lookup_auditor_status
    677     = &TEH_PG_lookup_auditor_status;
    678   plugin->insert_auditor
    679     = &TEH_PG_insert_auditor;
    680   plugin->lookup_wire_timestamp
    681     = &TEH_PG_lookup_wire_timestamp;
    682   plugin->insert_wire
    683     = &TEH_PG_insert_wire;
    684   plugin->update_wire
    685     = &TEH_PG_update_wire;
    686   plugin->get_wire_accounts
    687     = &TEH_PG_get_wire_accounts;
    688   plugin->get_wire_fees
    689     = &TEH_PG_get_wire_fees;
    690   plugin->select_aml_decisions
    691     = &TEH_PG_select_aml_decisions;
    692   plugin->select_deposit_amounts_for_kyc_check
    693     = &TEH_PG_select_deposit_amounts_for_kyc_check;
    694   plugin->do_check_deposit_idempotent
    695     = &TEH_PG_do_check_deposit_idempotent;
    696   plugin->insert_signkey_revocation
    697     = &TEH_PG_insert_signkey_revocation;
    698   plugin->select_aml_attributes
    699     = &TEH_PG_select_aml_attributes;
    700   plugin->select_aml_statistics
    701     = &TEH_PG_select_aml_statistics;
    702   plugin->lookup_signkey_revocation
    703     = &TEH_PG_lookup_signkey_revocation;
    704   plugin->lookup_denomination_key
    705     = &TEH_PG_lookup_denomination_key;
    706   plugin->lookup_completed_legitimization
    707     = &TEH_PG_lookup_completed_legitimization;
    708   plugin->lookup_pending_legitimization
    709     = &TEH_PG_lookup_pending_legitimization;
    710   plugin->lookup_active_legitimization
    711     = &TEH_PG_lookup_active_legitimization;
    712   plugin->insert_auditor_denom_sig
    713     = &TEH_PG_insert_auditor_denom_sig;
    714   plugin->select_auditor_denom_sig
    715     = &TEH_PG_select_auditor_denom_sig;
    716   plugin->select_kyc_accounts
    717     = &TEH_PG_select_kyc_accounts;
    718   plugin->add_denomination_key
    719     = &TEH_PG_add_denomination_key;
    720   plugin->lookup_signing_key
    721     = &TEH_PG_lookup_signing_key;
    722   plugin->lookup_h_payto_by_access_token
    723     = &TEH_PG_lookup_h_payto_by_access_token;
    724   plugin->insert_sanction_list_hit
    725     = &TEH_PG_insert_sanction_list_hit;
    726   plugin->select_exchange_debit_transfers
    727     = &TEH_PG_select_exchange_debit_transfers;
    728   plugin->select_exchange_credit_transfers
    729     = &TEH_PG_select_exchange_credit_transfers;
    730   plugin->select_exchange_kycauth_transfers
    731     = &TEH_PG_select_exchange_kycauth_transfers;
    732   plugin->select_all_kyc_attributes
    733     = &TEH_PG_select_all_kyc_attributes;
    734   plugin->begin_shard
    735     = &TEH_PG_begin_shard;
    736   plugin->abort_shard
    737     = &TEH_PG_abort_shard;
    738   plugin->insert_kyc_failure
    739     = &TEH_PG_insert_kyc_failure;
    740   plugin->complete_shard
    741     = &TEH_PG_complete_shard;
    742   plugin->release_revolving_shard
    743     = &TEH_PG_release_revolving_shard;
    744   plugin->delete_shard_locks
    745     = &TEH_PG_delete_shard_locks;
    746   plugin->set_extension_manifest
    747     = &TEH_PG_set_extension_manifest;
    748   plugin->insert_partner
    749     = &TEH_PG_insert_partner;
    750   plugin->expire_purse
    751     = &TEH_PG_expire_purse;
    752   plugin->select_purse_by_merge_pub
    753     = &TEH_PG_select_purse_by_merge_pub;
    754   plugin->set_purse_balance
    755     = &TEH_PG_set_purse_balance;
    756   plugin->get_pending_kyc_requirement_process
    757     = &TEH_PG_get_pending_kyc_requirement_process;
    758   plugin->select_kyc_attributes
    759     = &TEH_PG_select_kyc_attributes;
    760   plugin->insert_aml_officer
    761     = &TEH_PG_insert_aml_officer;
    762   plugin->enable_rules
    763     = &TEH_PG_enable_rules;
    764   plugin->disable_rules
    765     = &TEH_PG_disable_rules;
    766   plugin->test_aml_officer
    767     = &TEH_PG_test_aml_officer;
    768   plugin->lookup_aml_officer
    769     = &TEH_PG_lookup_aml_officer;
    770   plugin->insert_active_legitimization_measure
    771     = &TEH_PG_insert_active_legitimization_measure;
    772   plugin->insert_aml_decision
    773     = &TEH_PG_insert_aml_decision;
    774   plugin->lookup_kyc_requirement_by_row
    775     = &TEH_PG_lookup_kyc_requirement_by_row;
    776   plugin->trigger_kyc_rule_for_account
    777     = &TEH_PG_trigger_kyc_rule_for_account;
    778   plugin->lookup_kyc_status_by_token
    779     = &TEH_PG_lookup_kyc_status_by_token;
    780   plugin->batch_ensure_coin_known
    781     = &TEH_PG_batch_ensure_coin_known;
    782   plugin->inject_auditor_triggers
    783     = &TEH_PG_inject_auditor_triggers;
    784   plugin->insert_successor_measure
    785     = &TEH_PG_insert_successor_measure;
    786   plugin->insert_aml_program_failure
    787     = &TEH_PG_insert_aml_program_failure;
    788   plugin->persist_kyc_attributes
    789     = &TEH_PG_persist_kyc_attributes;
    790   plugin->clear_aml_lock
    791     = &TEH_PG_clear_aml_lock;
    792   plugin->set_aml_lock
    793     = &TEH_PG_set_aml_lock;
    794 
    795   return plugin;
    796 
    797 fail:
    798   GNUNET_free (pg->exchange_url);
    799   GNUNET_free (pg->sql_dir);
    800   GNUNET_free (pg);
    801   GNUNET_free (plugin);
    802   return NULL;
    803 }
    804 
    805 
    806 /**
    807  * Shutdown Postgres database subsystem.
    808  *
    809  * @param cls a `struct TALER_EXCHANGEDB_Plugin`
    810  * @return NULL (always)
    811  */
    812 void *
    813 libtaler_plugin_exchangedb_postgres_done (void *cls);
    814 
    815 /* Declaration used to squash compiler warning */
    816 void *
    817 libtaler_plugin_exchangedb_postgres_done (void *cls)
    818 {
    819   struct TALER_EXCHANGEDB_Plugin *plugin = cls;
    820   struct PostgresClosure *pg = plugin->cls;
    821 
    822   if (NULL != pg->conn)
    823   {
    824     GNUNET_PQ_disconnect (pg->conn);
    825     pg->conn = NULL;
    826   }
    827   GNUNET_free (pg->exchange_url);
    828   GNUNET_free (pg->sql_dir);
    829   GNUNET_free (pg->currency);
    830   GNUNET_free (pg);
    831   GNUNET_free (plugin);
    832   return NULL;
    833 }
    834 
    835 
    836 /* end of plugin_exchangedb_postgres.c */