LCOV - code coverage report
Current view: top level - auditordb - plugin_auditordb_postgres.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 633 691 91.6 %
Date: 2021-08-30 06:43:37 Functions: 59 61 96.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2021 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             :  * @file plugin_auditordb_postgres.c
      18             :  * @brief Low-level (statement-level) Postgres database access for the auditor
      19             :  * @author Christian Grothoff
      20             :  * @author Gabor X Toth
      21             :  */
      22             : #include "platform.h"
      23             : #include "taler_pq_lib.h"
      24             : #include "taler_auditordb_plugin.h"
      25             : #include <pthread.h>
      26             : #include <libpq-fe.h>
      27             : 
      28             : 
      29             : #define LOG(kind,...) GNUNET_log_from (kind, "taler-auditordb-postgres", \
      30             :                                        __VA_ARGS__)
      31             : 
      32             : 
      33             : /**
      34             :  * Wrapper macro to add the currency from the plugin's state
      35             :  * when fetching amounts from the database.
      36             :  *
      37             :  * @param field name of the database field to fetch amount from
      38             :  * @param[out] amountp pointer to amount to set
      39             :  */
      40             : #define TALER_PQ_RESULT_SPEC_AMOUNT(field,amountp) \
      41             :   TALER_PQ_result_spec_amount (                    \
      42             :     field,pg->currency,amountp)
      43             : 
      44             : /**
      45             :  * Wrapper macro to add the currency from the plugin's state
      46             :  * when fetching amounts from the database.  NBO variant.
      47             :  *
      48             :  * @param field name of the database field to fetch amount from
      49             :  * @param[out] amountp pointer to amount to set
      50             :  */
      51             : #define TALER_PQ_RESULT_SPEC_AMOUNT_NBO(field, \
      52             :                                         amountp) TALER_PQ_result_spec_amount_nbo ( \
      53             :     field,pg->currency,amountp)
      54             : 
      55             : 
      56             : /**
      57             :  * Type of the "cls" argument given to each of the functions in
      58             :  * our API.
      59             :  */
      60             : struct PostgresClosure
      61             : {
      62             : 
      63             :   /**
      64             :    * Postgres connection handle.
      65             :    */
      66             :   struct GNUNET_PQ_Context *conn;
      67             : 
      68             :   /**
      69             :    * Name of the ongoing transaction, used to debug cases where
      70             :    * a transaction is not properly terminated via COMMIT or
      71             :    * ROLLBACK.
      72             :    */
      73             :   const char *transaction_name;
      74             : 
      75             :   /**
      76             :    * Our configuration.
      77             :    */
      78             :   const struct GNUNET_CONFIGURATION_Handle *cfg;
      79             : 
      80             :   /**
      81             :    * Which currency should we assume all amounts to be in?
      82             :    */
      83             :   char *currency;
      84             : };
      85             : 
      86             : 
      87             : /**
      88             :  * Drop all auditor tables OR deletes recoverable auditor state.
      89             :  * This should only be used by testcases or when restarting the
      90             :  * auditor from scratch.
      91             :  *
      92             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
      93             :  * @param drop_exchangelist drop all tables, including schema versioning
      94             :  *        and the exchange and deposit_confirmations table; NOT to be
      95             :  *        used when restarting the auditor
      96             :  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
      97             :  */
      98             : static enum GNUNET_GenericReturnValue
      99          51 : postgres_drop_tables (void *cls,
     100             :                       int drop_exchangelist)
     101             : {
     102          51 :   struct PostgresClosure *pc = cls;
     103             :   struct GNUNET_PQ_Context *conn;
     104             : 
     105          51 :   conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
     106             :                                      "auditordb-postgres",
     107             :                                      (drop_exchangelist) ? "drop" : "restart",
     108             :                                      NULL,
     109             :                                      NULL);
     110          51 :   if (NULL == conn)
     111           2 :     return GNUNET_SYSERR;
     112          49 :   GNUNET_PQ_disconnect (conn);
     113          49 :   return GNUNET_OK;
     114             : }
     115             : 
     116             : 
     117             : /**
     118             :  * Create the necessary tables if they are not present
     119             :  *
     120             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     121             :  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
     122             :  */
     123             : static enum GNUNET_GenericReturnValue
     124          63 : postgres_create_tables (void *cls)
     125             : {
     126          63 :   struct PostgresClosure *pc = cls;
     127             :   struct GNUNET_PQ_Context *conn;
     128             : 
     129          63 :   conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
     130             :                                      "auditordb-postgres",
     131             :                                      "auditor-",
     132             :                                      NULL,
     133             :                                      NULL);
     134          63 :   if (NULL == conn)
     135           0 :     return GNUNET_SYSERR;
     136          63 :   GNUNET_PQ_disconnect (conn);
     137          63 :   return GNUNET_OK;
     138             : }
     139             : 
     140             : 
     141             : /**
     142             :  * Connect to the db if the connection does not exist yet.
     143             :  *
     144             :  * @param[in,out] pg the plugin-specific state
     145             :  * @return #GNUNET_OK on success
     146             :  */
     147             : static int
     148         428 : setup_connection (struct PostgresClosure *pg)
     149             : {
     150         428 :   struct GNUNET_PQ_PreparedStatement ps[] = {
     151             :     /* used in #postgres_commit */
     152         428 :     GNUNET_PQ_make_prepare ("do_commit",
     153             :                             "COMMIT",
     154             :                             0),
     155             :     /* used in #postgres_insert_exchange */
     156         428 :     GNUNET_PQ_make_prepare ("auditor_insert_exchange",
     157             :                             "INSERT INTO auditor_exchanges "
     158             :                             "(master_pub"
     159             :                             ",exchange_url"
     160             :                             ") VALUES ($1,$2);",
     161             :                             2),
     162             :     /* used in #postgres_delete_exchange */
     163         428 :     GNUNET_PQ_make_prepare ("auditor_delete_exchange",
     164             :                             "DELETE"
     165             :                             " FROM auditor_exchanges"
     166             :                             " WHERE master_pub=$1;",
     167             :                             1),
     168             :     /* used in #postgres_list_exchanges */
     169         428 :     GNUNET_PQ_make_prepare ("auditor_list_exchanges",
     170             :                             "SELECT"
     171             :                             " master_pub"
     172             :                             ",exchange_url"
     173             :                             " FROM auditor_exchanges",
     174             :                             0),
     175             :     /* used in #postgres_insert_exchange_signkey */
     176         428 :     GNUNET_PQ_make_prepare ("auditor_insert_exchange_signkey",
     177             :                             "INSERT INTO auditor_exchange_signkeys "
     178             :                             "(master_pub"
     179             :                             ",ep_start"
     180             :                             ",ep_expire"
     181             :                             ",ep_end"
     182             :                             ",exchange_pub"
     183             :                             ",master_sig"
     184             :                             ") VALUES ($1,$2,$3,$4,$5,$6);",
     185             :                             6),
     186             :     /* Used in #postgres_insert_deposit_confirmation() */
     187         428 :     GNUNET_PQ_make_prepare ("auditor_deposit_confirmation_insert",
     188             :                             "INSERT INTO deposit_confirmations "
     189             :                             "(master_pub"
     190             :                             ",h_contract_terms"
     191             :                             ",h_wire"
     192             :                             ",exchange_timestamp"
     193             :                             ",refund_deadline"
     194             :                             ",amount_without_fee_val"
     195             :                             ",amount_without_fee_frac"
     196             :                             ",coin_pub"
     197             :                             ",merchant_pub"
     198             :                             ",exchange_sig"
     199             :                             ",exchange_pub"
     200             :                             ",master_sig" /* master_sig could be normalized... */
     201             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);",
     202             :                             12),
     203             :     /* Used in #postgres_get_deposit_confirmations() */
     204         428 :     GNUNET_PQ_make_prepare ("auditor_deposit_confirmation_select",
     205             :                             "SELECT"
     206             :                             " serial_id"
     207             :                             ",h_contract_terms"
     208             :                             ",h_wire"
     209             :                             ",exchange_timestamp"
     210             :                             ",refund_deadline"
     211             :                             ",amount_without_fee_val"
     212             :                             ",amount_without_fee_frac"
     213             :                             ",coin_pub"
     214             :                             ",merchant_pub"
     215             :                             ",exchange_sig"
     216             :                             ",exchange_pub"
     217             :                             ",master_sig" /* master_sig could be normalized... */
     218             :                             " FROM deposit_confirmations"
     219             :                             " WHERE master_pub=$1"
     220             :                             " AND serial_id>$2",
     221             :                             2),
     222             :     /* Used in #postgres_update_auditor_progress_reserve() */
     223         428 :     GNUNET_PQ_make_prepare ("auditor_progress_update_reserve",
     224             :                             "UPDATE auditor_progress_reserve SET "
     225             :                             " last_reserve_in_serial_id=$1"
     226             :                             ",last_reserve_out_serial_id=$2"
     227             :                             ",last_reserve_recoup_serial_id=$3"
     228             :                             ",last_reserve_close_serial_id=$4"
     229             :                             " WHERE master_pub=$5",
     230             :                             5),
     231             :     /* Used in #postgres_get_auditor_progress_reserve() */
     232         428 :     GNUNET_PQ_make_prepare ("auditor_progress_select_reserve",
     233             :                             "SELECT"
     234             :                             " last_reserve_in_serial_id"
     235             :                             ",last_reserve_out_serial_id"
     236             :                             ",last_reserve_recoup_serial_id"
     237             :                             ",last_reserve_close_serial_id"
     238             :                             " FROM auditor_progress_reserve"
     239             :                             " WHERE master_pub=$1;",
     240             :                             1),
     241             :     /* Used in #postgres_insert_auditor_progress_reserve() */
     242         428 :     GNUNET_PQ_make_prepare ("auditor_progress_insert_reserve",
     243             :                             "INSERT INTO auditor_progress_reserve "
     244             :                             "(master_pub"
     245             :                             ",last_reserve_in_serial_id"
     246             :                             ",last_reserve_out_serial_id"
     247             :                             ",last_reserve_recoup_serial_id"
     248             :                             ",last_reserve_close_serial_id"
     249             :                             ") VALUES ($1,$2,$3,$4,$5);",
     250             :                             5),
     251             :     /* Used in #postgres_update_auditor_progress_aggregation() */
     252         428 :     GNUNET_PQ_make_prepare ("auditor_progress_update_aggregation",
     253             :                             "UPDATE auditor_progress_aggregation SET "
     254             :                             " last_wire_out_serial_id=$1"
     255             :                             " WHERE master_pub=$2",
     256             :                             2),
     257             :     /* Used in #postgres_get_auditor_progress_aggregation() */
     258         428 :     GNUNET_PQ_make_prepare ("auditor_progress_select_aggregation",
     259             :                             "SELECT"
     260             :                             " last_wire_out_serial_id"
     261             :                             " FROM auditor_progress_aggregation"
     262             :                             " WHERE master_pub=$1;",
     263             :                             1),
     264             :     /* Used in #postgres_insert_auditor_progress_aggregation() */
     265         428 :     GNUNET_PQ_make_prepare ("auditor_progress_insert_aggregation",
     266             :                             "INSERT INTO auditor_progress_aggregation "
     267             :                             "(master_pub"
     268             :                             ",last_wire_out_serial_id"
     269             :                             ") VALUES ($1,$2);",
     270             :                             2),
     271             :     /* Used in #postgres_update_auditor_progress_deposit_confirmation() */
     272         428 :     GNUNET_PQ_make_prepare ("auditor_progress_update_deposit_confirmation",
     273             :                             "UPDATE auditor_progress_deposit_confirmation SET "
     274             :                             " last_deposit_confirmation_serial_id=$1"
     275             :                             " WHERE master_pub=$2",
     276             :                             2),
     277             :     /* Used in #postgres_get_auditor_progress_deposit_confirmation() */
     278         428 :     GNUNET_PQ_make_prepare ("auditor_progress_select_deposit_confirmation",
     279             :                             "SELECT"
     280             :                             " last_deposit_confirmation_serial_id"
     281             :                             " FROM auditor_progress_deposit_confirmation"
     282             :                             " WHERE master_pub=$1;",
     283             :                             1),
     284             :     /* Used in #postgres_insert_auditor_progress_deposit_confirmation() */
     285         428 :     GNUNET_PQ_make_prepare ("auditor_progress_insert_deposit_confirmation",
     286             :                             "INSERT INTO auditor_progress_deposit_confirmation "
     287             :                             "(master_pub"
     288             :                             ",last_deposit_confirmation_serial_id"
     289             :                             ") VALUES ($1,$2);",
     290             :                             2),
     291             :     /* Used in #postgres_update_auditor_progress_coin() */
     292         428 :     GNUNET_PQ_make_prepare ("auditor_progress_update_coin",
     293             :                             "UPDATE auditor_progress_coin SET "
     294             :                             " last_withdraw_serial_id=$1"
     295             :                             ",last_deposit_serial_id=$2"
     296             :                             ",last_melt_serial_id=$3"
     297             :                             ",last_refund_serial_id=$4"
     298             :                             ",last_recoup_serial_id=$5"
     299             :                             ",last_recoup_refresh_serial_id=$6"
     300             :                             " WHERE master_pub=$7",
     301             :                             7),
     302             :     /* Used in #postgres_get_auditor_progress_coin() */
     303         428 :     GNUNET_PQ_make_prepare ("auditor_progress_select_coin",
     304             :                             "SELECT"
     305             :                             " last_withdraw_serial_id"
     306             :                             ",last_deposit_serial_id"
     307             :                             ",last_melt_serial_id"
     308             :                             ",last_refund_serial_id"
     309             :                             ",last_recoup_serial_id"
     310             :                             ",last_recoup_refresh_serial_id"
     311             :                             " FROM auditor_progress_coin"
     312             :                             " WHERE master_pub=$1;",
     313             :                             1),
     314             :     /* Used in #postgres_insert_auditor_progress() */
     315         428 :     GNUNET_PQ_make_prepare ("auditor_progress_insert_coin",
     316             :                             "INSERT INTO auditor_progress_coin "
     317             :                             "(master_pub"
     318             :                             ",last_withdraw_serial_id"
     319             :                             ",last_deposit_serial_id"
     320             :                             ",last_melt_serial_id"
     321             :                             ",last_refund_serial_id"
     322             :                             ",last_recoup_serial_id"
     323             :                             ",last_recoup_refresh_serial_id"
     324             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7);",
     325             :                             7),
     326             :     /* Used in #postgres_insert_wire_auditor_account_progress() */
     327         428 :     GNUNET_PQ_make_prepare ("wire_auditor_account_progress_insert",
     328             :                             "INSERT INTO wire_auditor_account_progress "
     329             :                             "(master_pub"
     330             :                             ",account_name"
     331             :                             ",last_wire_reserve_in_serial_id"
     332             :                             ",last_wire_wire_out_serial_id"
     333             :                             ",wire_in_off"
     334             :                             ",wire_out_off"
     335             :                             ") VALUES ($1,$2,$3,$4,$5,$6);",
     336             :                             6),
     337             :     /* Used in #postgres_update_wire_auditor_account_progress() */
     338         428 :     GNUNET_PQ_make_prepare ("wire_auditor_account_progress_update",
     339             :                             "UPDATE wire_auditor_account_progress SET "
     340             :                             " last_wire_reserve_in_serial_id=$1"
     341             :                             ",last_wire_wire_out_serial_id=$2"
     342             :                             ",wire_in_off=$3"
     343             :                             ",wire_out_off=$4"
     344             :                             " WHERE master_pub=$5 AND account_name=$6",
     345             :                             6),
     346             :     /* Used in #postgres_get_wire_auditor_account_progress() */
     347         428 :     GNUNET_PQ_make_prepare ("wire_auditor_account_progress_select",
     348             :                             "SELECT"
     349             :                             " last_wire_reserve_in_serial_id"
     350             :                             ",last_wire_wire_out_serial_id"
     351             :                             ",wire_in_off"
     352             :                             ",wire_out_off"
     353             :                             " FROM wire_auditor_account_progress"
     354             :                             " WHERE master_pub=$1 AND account_name=$2;",
     355             :                             2),
     356             :     /* Used in #postgres_insert_wire_auditor_progress() */
     357         428 :     GNUNET_PQ_make_prepare ("wire_auditor_progress_insert",
     358             :                             "INSERT INTO wire_auditor_progress "
     359             :                             "(master_pub"
     360             :                             ",last_timestamp"
     361             :                             ",last_reserve_close_uuid"
     362             :                             ") VALUES ($1,$2,$3);",
     363             :                             3),
     364             :     /* Used in #postgres_update_wire_auditor_progress() */
     365         428 :     GNUNET_PQ_make_prepare ("wire_auditor_progress_update",
     366             :                             "UPDATE wire_auditor_progress SET "
     367             :                             " last_timestamp=$1"
     368             :                             ",last_reserve_close_uuid=$2"
     369             :                             " WHERE master_pub=$3",
     370             :                             3),
     371             :     /* Used in #postgres_get_wire_auditor_progress() */
     372         428 :     GNUNET_PQ_make_prepare ("wire_auditor_progress_select",
     373             :                             "SELECT"
     374             :                             " last_timestamp"
     375             :                             ",last_reserve_close_uuid"
     376             :                             " FROM wire_auditor_progress"
     377             :                             " WHERE master_pub=$1;",
     378             :                             1),
     379             :     /* Used in #postgres_insert_reserve_info() */
     380         428 :     GNUNET_PQ_make_prepare ("auditor_reserves_insert",
     381             :                             "INSERT INTO auditor_reserves "
     382             :                             "(reserve_pub"
     383             :                             ",master_pub"
     384             :                             ",reserve_balance_val"
     385             :                             ",reserve_balance_frac"
     386             :                             ",withdraw_fee_balance_val"
     387             :                             ",withdraw_fee_balance_frac"
     388             :                             ",expiration_date"
     389             :                             ",origin_account"
     390             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8);",
     391             :                             8),
     392             :     /* Used in #postgres_update_reserve_info() */
     393         428 :     GNUNET_PQ_make_prepare ("auditor_reserves_update",
     394             :                             "UPDATE auditor_reserves SET"
     395             :                             " reserve_balance_val=$1"
     396             :                             ",reserve_balance_frac=$2"
     397             :                             ",withdraw_fee_balance_val=$3"
     398             :                             ",withdraw_fee_balance_frac=$4"
     399             :                             ",expiration_date=$5"
     400             :                             " WHERE reserve_pub=$6 AND master_pub=$7;",
     401             :                             7),
     402             :     /* Used in #postgres_get_reserve_info() */
     403         428 :     GNUNET_PQ_make_prepare ("auditor_reserves_select",
     404             :                             "SELECT"
     405             :                             " reserve_balance_val"
     406             :                             ",reserve_balance_frac"
     407             :                             ",withdraw_fee_balance_val"
     408             :                             ",withdraw_fee_balance_frac"
     409             :                             ",expiration_date"
     410             :                             ",auditor_reserves_rowid"
     411             :                             ",origin_account"
     412             :                             " FROM auditor_reserves"
     413             :                             " WHERE reserve_pub=$1 AND master_pub=$2;",
     414             :                             2),
     415             :     /* Used in #postgres_del_reserve_info() */
     416         428 :     GNUNET_PQ_make_prepare ("auditor_reserves_delete",
     417             :                             "DELETE"
     418             :                             " FROM auditor_reserves"
     419             :                             " WHERE reserve_pub=$1 AND master_pub=$2;",
     420             :                             2),
     421             :     /* Used in #postgres_insert_reserve_summary() */
     422         428 :     GNUNET_PQ_make_prepare ("auditor_reserve_balance_insert",
     423             :                             "INSERT INTO auditor_reserve_balance"
     424             :                             "(master_pub"
     425             :                             ",reserve_balance_val"
     426             :                             ",reserve_balance_frac"
     427             :                             ",withdraw_fee_balance_val"
     428             :                             ",withdraw_fee_balance_frac"
     429             :                             ") VALUES ($1,$2,$3,$4,$5)",
     430             :                             5),
     431             :     /* Used in #postgres_update_reserve_summary() */
     432         428 :     GNUNET_PQ_make_prepare ("auditor_reserve_balance_update",
     433             :                             "UPDATE auditor_reserve_balance SET"
     434             :                             " reserve_balance_val=$1"
     435             :                             ",reserve_balance_frac=$2"
     436             :                             ",withdraw_fee_balance_val=$3"
     437             :                             ",withdraw_fee_balance_frac=$4"
     438             :                             " WHERE master_pub=$5;",
     439             :                             5),
     440             :     /* Used in #postgres_get_reserve_summary() */
     441         428 :     GNUNET_PQ_make_prepare ("auditor_reserve_balance_select",
     442             :                             "SELECT"
     443             :                             " reserve_balance_val"
     444             :                             ",reserve_balance_frac"
     445             :                             ",withdraw_fee_balance_val"
     446             :                             ",withdraw_fee_balance_frac"
     447             :                             " FROM auditor_reserve_balance"
     448             :                             " WHERE master_pub=$1;",
     449             :                             1),
     450             :     /* Used in #postgres_insert_wire_fee_summary() */
     451         428 :     GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_insert",
     452             :                             "INSERT INTO auditor_wire_fee_balance"
     453             :                             "(master_pub"
     454             :                             ",wire_fee_balance_val"
     455             :                             ",wire_fee_balance_frac"
     456             :                             ") VALUES ($1,$2,$3)",
     457             :                             3),
     458             :     /* Used in #postgres_update_wire_fee_summary() */
     459         428 :     GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_update",
     460             :                             "UPDATE auditor_wire_fee_balance SET"
     461             :                             " wire_fee_balance_val=$1"
     462             :                             ",wire_fee_balance_frac=$2"
     463             :                             " WHERE master_pub=$3;",
     464             :                             3),
     465             :     /* Used in #postgres_get_wire_fee_summary() */
     466         428 :     GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_select",
     467             :                             "SELECT"
     468             :                             " wire_fee_balance_val"
     469             :                             ",wire_fee_balance_frac"
     470             :                             " FROM auditor_wire_fee_balance"
     471             :                             " WHERE master_pub=$1;",
     472             :                             1),
     473             :     /* Used in #postgres_insert_denomination_balance() */
     474         428 :     GNUNET_PQ_make_prepare ("auditor_denomination_pending_insert",
     475             :                             "INSERT INTO auditor_denomination_pending "
     476             :                             "(denom_pub_hash"
     477             :                             ",denom_balance_val"
     478             :                             ",denom_balance_frac"
     479             :                             ",denom_loss_val"
     480             :                             ",denom_loss_frac"
     481             :                             ",num_issued"
     482             :                             ",denom_risk_val"
     483             :                             ",denom_risk_frac"
     484             :                             ",recoup_loss_val"
     485             :                             ",recoup_loss_frac"
     486             :                             ") VALUES ("
     487             :                             "$1,$2,$3,$4,$5,$6,$7,$8,$9,$10"
     488             :                             ");",
     489             :                             10),
     490             :     /* Used in #postgres_update_denomination_balance() */
     491         428 :     GNUNET_PQ_make_prepare ("auditor_denomination_pending_update",
     492             :                             "UPDATE auditor_denomination_pending SET"
     493             :                             " denom_balance_val=$1"
     494             :                             ",denom_balance_frac=$2"
     495             :                             ",denom_loss_val=$3"
     496             :                             ",denom_loss_frac=$4"
     497             :                             ",num_issued=$5"
     498             :                             ",denom_risk_val=$6"
     499             :                             ",denom_risk_frac=$7"
     500             :                             ",recoup_loss_val=$8"
     501             :                             ",recoup_loss_frac=$9"
     502             :                             " WHERE denom_pub_hash=$10",
     503             :                             10),
     504             :     /* Used in #postgres_get_denomination_balance() */
     505         428 :     GNUNET_PQ_make_prepare ("auditor_denomination_pending_select",
     506             :                             "SELECT"
     507             :                             " denom_balance_val"
     508             :                             ",denom_balance_frac"
     509             :                             ",denom_loss_val"
     510             :                             ",denom_loss_frac"
     511             :                             ",num_issued"
     512             :                             ",denom_risk_val"
     513             :                             ",denom_risk_frac"
     514             :                             ",recoup_loss_val"
     515             :                             ",recoup_loss_frac"
     516             :                             " FROM auditor_denomination_pending"
     517             :                             " WHERE denom_pub_hash=$1",
     518             :                             1),
     519             :     /* Used in #postgres_insert_balance_summary() */
     520         428 :     GNUNET_PQ_make_prepare ("auditor_balance_summary_insert",
     521             :                             "INSERT INTO auditor_balance_summary "
     522             :                             "(master_pub"
     523             :                             ",denom_balance_val"
     524             :                             ",denom_balance_frac"
     525             :                             ",deposit_fee_balance_val"
     526             :                             ",deposit_fee_balance_frac"
     527             :                             ",melt_fee_balance_val"
     528             :                             ",melt_fee_balance_frac"
     529             :                             ",refund_fee_balance_val"
     530             :                             ",refund_fee_balance_frac"
     531             :                             ",risk_val"
     532             :                             ",risk_frac"
     533             :                             ",loss_val"
     534             :                             ",loss_frac"
     535             :                             ",irregular_recoup_val"
     536             :                             ",irregular_recoup_frac"
     537             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,"
     538             :                             "          $11,$12,$13,$14,$15);",
     539             :                             15),
     540             :     /* Used in #postgres_update_balance_summary() */
     541         428 :     GNUNET_PQ_make_prepare ("auditor_balance_summary_update",
     542             :                             "UPDATE auditor_balance_summary SET"
     543             :                             " denom_balance_val=$1"
     544             :                             ",denom_balance_frac=$2"
     545             :                             ",deposit_fee_balance_val=$3"
     546             :                             ",deposit_fee_balance_frac=$4"
     547             :                             ",melt_fee_balance_val=$5"
     548             :                             ",melt_fee_balance_frac=$6"
     549             :                             ",refund_fee_balance_val=$7"
     550             :                             ",refund_fee_balance_frac=$8"
     551             :                             ",risk_val=$9"
     552             :                             ",risk_frac=$10"
     553             :                             ",loss_val=$11"
     554             :                             ",loss_frac=$12"
     555             :                             ",irregular_recoup_val=$13"
     556             :                             ",irregular_recoup_frac=$14"
     557             :                             " WHERE master_pub=$15;",
     558             :                             15),
     559             :     /* Used in #postgres_get_balance_summary() */
     560         428 :     GNUNET_PQ_make_prepare ("auditor_balance_summary_select",
     561             :                             "SELECT"
     562             :                             " denom_balance_val"
     563             :                             ",denom_balance_frac"
     564             :                             ",deposit_fee_balance_val"
     565             :                             ",deposit_fee_balance_frac"
     566             :                             ",melt_fee_balance_val"
     567             :                             ",melt_fee_balance_frac"
     568             :                             ",refund_fee_balance_val"
     569             :                             ",refund_fee_balance_frac"
     570             :                             ",risk_val"
     571             :                             ",risk_frac"
     572             :                             ",loss_val"
     573             :                             ",loss_frac"
     574             :                             ",irregular_recoup_val"
     575             :                             ",irregular_recoup_frac"
     576             :                             " FROM auditor_balance_summary"
     577             :                             " WHERE master_pub=$1;",
     578             :                             1),
     579             :     /* Used in #postgres_insert_historic_denom_revenue() */
     580         428 :     GNUNET_PQ_make_prepare ("auditor_historic_denomination_revenue_insert",
     581             :                             "INSERT INTO auditor_historic_denomination_revenue"
     582             :                             "(master_pub"
     583             :                             ",denom_pub_hash"
     584             :                             ",revenue_timestamp"
     585             :                             ",revenue_balance_val"
     586             :                             ",revenue_balance_frac"
     587             :                             ",loss_balance_val"
     588             :                             ",loss_balance_frac"
     589             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7);",
     590             :                             7),
     591             :     /* Used in #postgres_select_historic_denom_revenue() */
     592         428 :     GNUNET_PQ_make_prepare ("auditor_historic_denomination_revenue_select",
     593             :                             "SELECT"
     594             :                             " denom_pub_hash"
     595             :                             ",revenue_timestamp"
     596             :                             ",revenue_balance_val"
     597             :                             ",revenue_balance_frac"
     598             :                             ",loss_balance_val"
     599             :                             ",loss_balance_frac"
     600             :                             " FROM auditor_historic_denomination_revenue"
     601             :                             " WHERE master_pub=$1;",
     602             :                             1),
     603             :     /* Used in #postgres_insert_historic_reserve_revenue() */
     604         428 :     GNUNET_PQ_make_prepare ("auditor_historic_reserve_summary_insert",
     605             :                             "INSERT INTO auditor_historic_reserve_summary"
     606             :                             "(master_pub"
     607             :                             ",start_date"
     608             :                             ",end_date"
     609             :                             ",reserve_profits_val"
     610             :                             ",reserve_profits_frac"
     611             :                             ") VALUES ($1,$2,$3,$4,$5);",
     612             :                             5),
     613             :     /* Used in #postgres_select_historic_reserve_revenue() */
     614         428 :     GNUNET_PQ_make_prepare ("auditor_historic_reserve_summary_select",
     615             :                             "SELECT"
     616             :                             " start_date"
     617             :                             ",end_date"
     618             :                             ",reserve_profits_val"
     619             :                             ",reserve_profits_frac"
     620             :                             " FROM auditor_historic_reserve_summary"
     621             :                             " WHERE master_pub=$1;",
     622             :                             1),
     623             :     /* Used in #postgres_insert_predicted_result() */
     624         428 :     GNUNET_PQ_make_prepare ("auditor_predicted_result_insert",
     625             :                             "INSERT INTO auditor_predicted_result"
     626             :                             "(master_pub"
     627             :                             ",balance_val"
     628             :                             ",balance_frac"
     629             :                             ") VALUES ($1,$2,$3);",
     630             :                             3),
     631             :     /* Used in #postgres_update_predicted_result() */
     632         428 :     GNUNET_PQ_make_prepare ("auditor_predicted_result_update",
     633             :                             "UPDATE auditor_predicted_result SET"
     634             :                             " balance_val=$1"
     635             :                             ",balance_frac=$2"
     636             :                             " WHERE master_pub=$3;",
     637             :                             3),
     638             :     /* Used in #postgres_get_predicted_balance() */
     639         428 :     GNUNET_PQ_make_prepare ("auditor_predicted_result_select",
     640             :                             "SELECT"
     641             :                             " balance_val"
     642             :                             ",balance_frac"
     643             :                             " FROM auditor_predicted_result"
     644             :                             " WHERE master_pub=$1;",
     645             :                             1),
     646             :     GNUNET_PQ_PREPARED_STATEMENT_END
     647             :   };
     648             :   struct GNUNET_PQ_Context *db_conn;
     649             : 
     650         428 :   if (NULL != pg->conn)
     651             :   {
     652           0 :     GNUNET_PQ_reconnect_if_down (pg->conn);
     653           0 :     return GNUNET_OK;
     654             :   }
     655         428 :   db_conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
     656             :                                         "auditordb-postgres",
     657             :                                         NULL,
     658             :                                         NULL,
     659             :                                         ps);
     660         428 :   if (NULL == db_conn)
     661           0 :     return GNUNET_SYSERR;
     662         428 :   pg->conn = db_conn;
     663         428 :   return GNUNET_OK;
     664             : }
     665             : 
     666             : 
     667             : /**
     668             :  * Do a pre-flight check that we are not in an uncommitted transaction.
     669             :  * If we are, rollback the previous transaction and output a warning.
     670             :  *
     671             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     672             :  * @return #GNUNET_OK on success,
     673             :  *         #GNUNET_NO if we rolled back an earlier transaction
     674             :  *         #GNUNET_SYSERR if we have no DB connection
     675             :  */
     676             : static enum GNUNET_GenericReturnValue
     677        1262 : postgres_preflight (void *cls)
     678             : {
     679        1262 :   struct PostgresClosure *pg = cls;
     680        1262 :   struct GNUNET_PQ_ExecuteStatement es[] = {
     681        1262 :     GNUNET_PQ_make_execute ("ROLLBACK"),
     682             :     GNUNET_PQ_EXECUTE_STATEMENT_END
     683             :   };
     684             : 
     685        1262 :   if (NULL == pg->conn)
     686             :   {
     687         428 :     if (GNUNET_OK !=
     688         428 :         setup_connection (pg))
     689             :     {
     690           0 :       GNUNET_break (0);
     691           0 :       return GNUNET_SYSERR;
     692             :     }
     693             :   }
     694        1262 :   if (NULL == pg->transaction_name)
     695        1262 :     return GNUNET_OK; /* all good */
     696           0 :   if (GNUNET_OK ==
     697           0 :       GNUNET_PQ_exec_statements (pg->conn,
     698             :                                  es))
     699             :   {
     700           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     701             :                 "BUG: Preflight check rolled back transaction `%s'!\n",
     702             :                 pg->transaction_name);
     703             :   }
     704             :   else
     705             :   {
     706           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     707             :                 "BUG: Preflight check failed to rollback transaction `%s'!\n",
     708             :                 pg->transaction_name);
     709             :   }
     710           0 :   pg->transaction_name = NULL;
     711           0 :   return GNUNET_NO;
     712             : }
     713             : 
     714             : 
     715             : /**
     716             :  * Start a transaction.
     717             :  *
     718             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     719             :  * @return #GNUNET_OK on success
     720             :  */
     721             : static enum GNUNET_GenericReturnValue
     722         418 : postgres_start (void *cls)
     723             : {
     724         418 :   struct PostgresClosure *pg = cls;
     725         418 :   struct GNUNET_PQ_ExecuteStatement es[] = {
     726         418 :     GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
     727             :     GNUNET_PQ_EXECUTE_STATEMENT_END
     728             :   };
     729             : 
     730         418 :   postgres_preflight (cls);
     731         418 :   if (GNUNET_OK !=
     732         418 :       GNUNET_PQ_exec_statements (pg->conn,
     733             :                                  es))
     734             :   {
     735           0 :     TALER_LOG_ERROR ("Failed to start transaction\n");
     736           0 :     GNUNET_break (0);
     737           0 :     return GNUNET_SYSERR;
     738             :   }
     739         418 :   return GNUNET_OK;
     740             : }
     741             : 
     742             : 
     743             : /**
     744             :  * Roll back the current transaction of a database connection.
     745             :  *
     746             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     747             :  */
     748             : static void
     749          68 : postgres_rollback (void *cls)
     750             : {
     751          68 :   struct PostgresClosure *pg = cls;
     752          68 :   struct GNUNET_PQ_ExecuteStatement es[] = {
     753          68 :     GNUNET_PQ_make_execute ("ROLLBACK"),
     754             :     GNUNET_PQ_EXECUTE_STATEMENT_END
     755             :   };
     756             : 
     757          68 :   GNUNET_break (GNUNET_OK ==
     758             :                 GNUNET_PQ_exec_statements (pg->conn,
     759             :                                            es));
     760          68 : }
     761             : 
     762             : 
     763             : /**
     764             :  * Commit the current transaction of a database connection.
     765             :  *
     766             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     767             :  * @return transaction status code
     768             :  */
     769             : enum GNUNET_DB_QueryStatus
     770         351 : postgres_commit (void *cls)
     771             : {
     772         351 :   struct PostgresClosure *pg = cls;
     773         351 :   struct GNUNET_PQ_QueryParam params[] = {
     774             :     GNUNET_PQ_query_param_end
     775             :   };
     776             : 
     777         351 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
     778             :                                              "do_commit",
     779             :                                              params);
     780             : }
     781             : 
     782             : 
     783             : /**
     784             :  * Function called to perform "garbage collection" on the
     785             :  * database, expiring records we no longer require.
     786             :  *
     787             :  * @param cls closure
     788             :  * @return #GNUNET_OK on success,
     789             :  *         #GNUNET_SYSERR on DB errors
     790             :  */
     791             : static int
     792           0 : postgres_gc (void *cls)
     793             : {
     794           0 :   struct PostgresClosure *pg = cls;
     795             :   struct GNUNET_TIME_Absolute now;
     796           0 :   struct GNUNET_PQ_QueryParam params_time[] = {
     797           0 :     TALER_PQ_query_param_absolute_time (&now),
     798             :     GNUNET_PQ_query_param_end
     799             :   };
     800             :   struct GNUNET_PQ_Context *conn;
     801             :   enum GNUNET_DB_QueryStatus qs;
     802           0 :   struct GNUNET_PQ_PreparedStatement ps[] = {
     803             : #if 0
     804             :     GNUNET_PQ_make_prepare ("gc_auditor",
     805             :                             "TODO: #4960",
     806             :                             0),
     807             : #endif
     808             :     GNUNET_PQ_PREPARED_STATEMENT_END
     809             :   };
     810             : 
     811           0 :   now = GNUNET_TIME_absolute_get ();
     812           0 :   conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
     813             :                                      "auditordb-postgres",
     814             :                                      NULL,
     815             :                                      NULL,
     816             :                                      ps);
     817           0 :   if (NULL == conn)
     818           0 :     return GNUNET_SYSERR;
     819           0 :   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     820             :               "TODO: Auditor GC not implemented (#4960)\n");
     821           0 :   qs = GNUNET_PQ_eval_prepared_non_select (conn,
     822             :                                            "gc_auditor",
     823             :                                            params_time);
     824           0 :   GNUNET_PQ_disconnect (conn);
     825           0 :   if (0 > qs)
     826             :   {
     827           0 :     GNUNET_break (0);
     828           0 :     return GNUNET_SYSERR;
     829             :   }
     830           0 :   return GNUNET_OK;
     831             : }
     832             : 
     833             : 
     834             : /**
     835             :  * Insert information about an exchange this auditor will be auditing.
     836             :  *
     837             :  * @param cls the @e cls of this struct with the plugin-specific state
     838             :  * @param master_pub master public key of the exchange
     839             :  * @param exchange_url public (base) URL of the API of the exchange
     840             :  * @return query result status
     841             :  */
     842             : static enum GNUNET_DB_QueryStatus
     843          12 : postgres_insert_exchange (void *cls,
     844             :                           const struct TALER_MasterPublicKeyP *master_pub,
     845             :                           const char *exchange_url)
     846             : {
     847          12 :   struct PostgresClosure *pg = cls;
     848          12 :   struct GNUNET_PQ_QueryParam params[] = {
     849          12 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
     850          12 :     GNUNET_PQ_query_param_string (exchange_url),
     851             :     GNUNET_PQ_query_param_end
     852             :   };
     853             : 
     854          12 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
     855             :                                              "auditor_insert_exchange",
     856             :                                              params);
     857             : }
     858             : 
     859             : 
     860             : /**
     861             :  * Delete an exchange from the list of exchanges this auditor is auditing.
     862             :  * Warning: this will cascade and delete all knowledge of this auditor related
     863             :  * to this exchange!
     864             :  *
     865             :  * @param cls the @e cls of this struct with the plugin-specific state
     866             :  * @param master_pub master public key of the exchange
     867             :  * @return query result status
     868             :  */
     869             : static enum GNUNET_DB_QueryStatus
     870           1 : postgres_delete_exchange (void *cls,
     871             :                           const struct TALER_MasterPublicKeyP *master_pub)
     872             : {
     873           1 :   struct PostgresClosure *pg = cls;
     874           1 :   struct GNUNET_PQ_QueryParam params[] = {
     875           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
     876             :     GNUNET_PQ_query_param_end
     877             :   };
     878             : 
     879           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
     880             :                                              "auditor_delete_exchange",
     881             :                                              params);
     882             : }
     883             : 
     884             : 
     885             : /**
     886             :  * Closure for #exchange_info_cb().
     887             :  */
     888             : struct ExchangeInfoContext
     889             : {
     890             : 
     891             :   /**
     892             :    * Function to call for each exchange.
     893             :    */
     894             :   TALER_AUDITORDB_ExchangeCallback cb;
     895             : 
     896             :   /**
     897             :    * Closure for @e cb
     898             :    */
     899             :   void *cb_cls;
     900             : 
     901             :   /**
     902             :    * Query status to return.
     903             :    */
     904             :   enum GNUNET_DB_QueryStatus qs;
     905             : };
     906             : 
     907             : 
     908             : /**
     909             :  * Helper function for #postgres_list_exchanges().
     910             :  * To be called with the results of a SELECT statement
     911             :  * that has returned @a num_results results.
     912             :  *
     913             :  * @param cls closure of type `struct ExchangeInfoContext *`
     914             :  * @param result the postgres result
     915             :  * @param num_results the number of results in @a result
     916             :  */
     917             : static void
     918         416 : exchange_info_cb (void *cls,
     919             :                   PGresult *result,
     920             :                   unsigned int num_results)
     921             : {
     922         416 :   struct ExchangeInfoContext *eic = cls;
     923             : 
     924         832 :   for (unsigned int i = 0; i < num_results; i++)
     925             :   {
     926             :     struct TALER_MasterPublicKeyP master_pub;
     927             :     char *exchange_url;
     928         416 :     struct GNUNET_PQ_ResultSpec rs[] = {
     929         416 :       GNUNET_PQ_result_spec_auto_from_type ("master_pub", &master_pub),
     930         416 :       GNUNET_PQ_result_spec_string ("exchange_url", &exchange_url),
     931             :       GNUNET_PQ_result_spec_end
     932             :     };
     933             : 
     934         416 :     if (GNUNET_OK !=
     935         416 :         GNUNET_PQ_extract_result (result,
     936             :                                   rs,
     937             :                                   i))
     938             :     {
     939           0 :       GNUNET_break (0);
     940           0 :       eic->qs = GNUNET_DB_STATUS_HARD_ERROR;
     941           0 :       return;
     942             :     }
     943         416 :     eic->qs = i + 1;
     944         416 :     eic->cb (eic->cb_cls,
     945             :              &master_pub,
     946             :              exchange_url);
     947         416 :     GNUNET_free (exchange_url);
     948             :   }
     949             : }
     950             : 
     951             : 
     952             : /**
     953             :  * Obtain information about exchanges this auditor is auditing.
     954             :  *
     955             :  * @param cls the @e cls of this struct with the plugin-specific state
     956             :  * @param cb function to call with the results
     957             :  * @param cb_cls closure for @a cb
     958             :  * @return query result status
     959             :  */
     960             : static enum GNUNET_DB_QueryStatus
     961         416 : postgres_list_exchanges (void *cls,
     962             :                          TALER_AUDITORDB_ExchangeCallback cb,
     963             :                          void *cb_cls)
     964             : {
     965         416 :   struct PostgresClosure *pg = cls;
     966         416 :   struct GNUNET_PQ_QueryParam params[] = {
     967             :     GNUNET_PQ_query_param_end
     968             :   };
     969         416 :   struct ExchangeInfoContext eic = {
     970             :     .cb = cb,
     971             :     .cb_cls = cb_cls
     972             :   };
     973             :   enum GNUNET_DB_QueryStatus qs;
     974             : 
     975         416 :   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
     976             :                                              "auditor_list_exchanges",
     977             :                                              params,
     978             :                                              &exchange_info_cb,
     979             :                                              &eic);
     980         416 :   if (qs > 0)
     981         416 :     return eic.qs;
     982           0 :   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
     983           0 :   return qs;
     984             : }
     985             : 
     986             : 
     987             : /**
     988             :  * Insert information about a signing key of the exchange.
     989             :  *
     990             :  * @param cls the @e cls of this struct with the plugin-specific state
     991             :  * @param sk signing key information to store
     992             :  * @return query result status
     993             :  */
     994             : static enum GNUNET_DB_QueryStatus
     995           1 : postgres_insert_exchange_signkey (
     996             :   void *cls,
     997             :   const struct TALER_AUDITORDB_ExchangeSigningKey *sk)
     998             : {
     999           1 :   struct PostgresClosure *pg = cls;
    1000           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1001           1 :     GNUNET_PQ_query_param_auto_from_type (&sk->master_public_key),
    1002           1 :     TALER_PQ_query_param_absolute_time (&sk->ep_start),
    1003           1 :     TALER_PQ_query_param_absolute_time (&sk->ep_expire),
    1004           1 :     TALER_PQ_query_param_absolute_time (&sk->ep_end),
    1005           1 :     GNUNET_PQ_query_param_auto_from_type (&sk->exchange_pub),
    1006           1 :     GNUNET_PQ_query_param_auto_from_type (&sk->master_sig),
    1007             :     GNUNET_PQ_query_param_end
    1008             :   };
    1009             : 
    1010           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1011             :                                              "auditor_insert_exchange_signkey",
    1012             :                                              params);
    1013             : }
    1014             : 
    1015             : 
    1016             : /**
    1017             :  * Insert information about a deposit confirmation into the database.
    1018             :  *
    1019             :  * @param cls the @e cls of this struct with the plugin-specific state
    1020             :  * @param dc deposit confirmation information to store
    1021             :  * @return query result status
    1022             :  */
    1023             : static enum GNUNET_DB_QueryStatus
    1024           1 : postgres_insert_deposit_confirmation (
    1025             :   void *cls,
    1026             :   const struct TALER_AUDITORDB_DepositConfirmation *dc)
    1027             : {
    1028           1 :   struct PostgresClosure *pg = cls;
    1029           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1030           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->master_public_key),
    1031           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->h_contract_terms),
    1032           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->h_wire),
    1033           1 :     TALER_PQ_query_param_absolute_time (&dc->exchange_timestamp),
    1034           1 :     TALER_PQ_query_param_absolute_time (&dc->refund_deadline),
    1035           1 :     TALER_PQ_query_param_amount (&dc->amount_without_fee),
    1036           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->coin_pub),
    1037           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->merchant),
    1038           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->exchange_sig),
    1039           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->exchange_pub),
    1040           1 :     GNUNET_PQ_query_param_auto_from_type (&dc->master_sig),
    1041             :     GNUNET_PQ_query_param_end
    1042             :   };
    1043             : 
    1044           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1045             :                                              "auditor_deposit_confirmation_insert",
    1046             :                                              params);
    1047             : }
    1048             : 
    1049             : 
    1050             : /**
    1051             :  * Closure for #deposit_confirmation_cb().
    1052             :  */
    1053             : struct DepositConfirmationContext
    1054             : {
    1055             : 
    1056             :   /**
    1057             :    * Master public key that is being used.
    1058             :    */
    1059             :   const struct TALER_MasterPublicKeyP *master_pub;
    1060             : 
    1061             :   /**
    1062             :    * Function to call for each deposit confirmation.
    1063             :    */
    1064             :   TALER_AUDITORDB_DepositConfirmationCallback cb;
    1065             : 
    1066             :   /**
    1067             :    * Closure for @e cb
    1068             :    */
    1069             :   void *cb_cls;
    1070             : 
    1071             :   /**
    1072             :    * Plugin context.
    1073             :    */
    1074             :   struct PostgresClosure *pg;
    1075             : 
    1076             :   /**
    1077             :    * Query status to return.
    1078             :    */
    1079             :   enum GNUNET_DB_QueryStatus qs;
    1080             : };
    1081             : 
    1082             : 
    1083             : /**
    1084             :  * Helper function for #postgres_get_deposit_confirmations().
    1085             :  * To be called with the results of a SELECT statement
    1086             :  * that has returned @a num_results results.
    1087             :  *
    1088             :  * @param cls closure of type `struct DepositConfirmationContext *`
    1089             :  * @param result the postgres result
    1090             :  * @param num_results the number of results in @a result
    1091             :  */
    1092             : static void
    1093          83 : deposit_confirmation_cb (void *cls,
    1094             :                          PGresult *result,
    1095             :                          unsigned int num_results)
    1096             : {
    1097          83 :   struct DepositConfirmationContext *dcc = cls;
    1098          83 :   struct PostgresClosure *pg = dcc->pg;
    1099             : 
    1100         201 :   for (unsigned int i = 0; i < num_results; i++)
    1101             :   {
    1102             :     uint64_t serial_id;
    1103         118 :     struct TALER_AUDITORDB_DepositConfirmation dc = {
    1104         118 :       .master_public_key = *dcc->master_pub
    1105             :     };
    1106         118 :     struct GNUNET_PQ_ResultSpec rs[] = {
    1107         118 :       GNUNET_PQ_result_spec_uint64 ("serial_id",
    1108             :                                     &serial_id),
    1109         118 :       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
    1110             :                                             &dc.h_contract_terms),
    1111         118 :       GNUNET_PQ_result_spec_auto_from_type ("h_wire",
    1112             :                                             &dc.h_wire),
    1113         118 :       GNUNET_PQ_result_spec_absolute_time ("exchange_timestamp",
    1114             :                                            &dc.exchange_timestamp),
    1115         118 :       GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
    1116             :                                            &dc.refund_deadline),
    1117         118 :       TALER_PQ_RESULT_SPEC_AMOUNT ("amount_without_fee",
    1118             :                                    &dc.amount_without_fee),
    1119         118 :       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
    1120             :                                             &dc.coin_pub),
    1121         118 :       GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
    1122             :                                             &dc.merchant),
    1123         118 :       GNUNET_PQ_result_spec_auto_from_type ("exchange_sig",
    1124             :                                             &dc.exchange_sig),
    1125         118 :       GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
    1126             :                                             &dc.exchange_pub),
    1127         118 :       GNUNET_PQ_result_spec_auto_from_type ("master_sig",
    1128             :                                             &dc.master_sig),
    1129             :       GNUNET_PQ_result_spec_end
    1130             :     };
    1131             : 
    1132         118 :     if (GNUNET_OK !=
    1133         118 :         GNUNET_PQ_extract_result (result,
    1134             :                                   rs,
    1135             :                                   i))
    1136             :     {
    1137           0 :       GNUNET_break (0);
    1138           0 :       dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    1139           0 :       return;
    1140             :     }
    1141         118 :     dcc->qs = i + 1;
    1142         118 :     if (GNUNET_OK !=
    1143         118 :         dcc->cb (dcc->cb_cls,
    1144             :                  serial_id,
    1145             :                  &dc))
    1146           0 :       break;
    1147             :   }
    1148             : }
    1149             : 
    1150             : 
    1151             : /**
    1152             :  * Get information about deposit confirmations from the database.
    1153             :  *
    1154             :  * @param cls the @e cls of this struct with the plugin-specific state
    1155             :  * @param master_public_key for which exchange do we want to get deposit confirmations
    1156             :  * @param start_id row/serial ID where to start the iteration (0 from
    1157             :  *                  the start, exclusive, i.e. serial_ids must start from 1)
    1158             :  * @param cb function to call with results
    1159             :  * @param cb_cls closure for @a cb
    1160             :  * @return query result status
    1161             :  */
    1162             : static enum GNUNET_DB_QueryStatus
    1163          83 : postgres_get_deposit_confirmations (
    1164             :   void *cls,
    1165             :   const struct TALER_MasterPublicKeyP *master_public_key,
    1166             :   uint64_t start_id,
    1167             :   TALER_AUDITORDB_DepositConfirmationCallback cb,
    1168             :   void *cb_cls)
    1169             : {
    1170          83 :   struct PostgresClosure *pg = cls;
    1171          83 :   struct GNUNET_PQ_QueryParam params[] = {
    1172          83 :     GNUNET_PQ_query_param_auto_from_type (master_public_key),
    1173          83 :     GNUNET_PQ_query_param_uint64 (&start_id),
    1174             :     GNUNET_PQ_query_param_end
    1175             :   };
    1176          83 :   struct DepositConfirmationContext dcc = {
    1177             :     .master_pub = master_public_key,
    1178             :     .cb = cb,
    1179             :     .cb_cls = cb_cls,
    1180             :     .pg = pg
    1181             :   };
    1182             :   enum GNUNET_DB_QueryStatus qs;
    1183             : 
    1184          83 :   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    1185             :                                              "auditor_deposit_confirmation_select",
    1186             :                                              params,
    1187             :                                              &deposit_confirmation_cb,
    1188             :                                              &dcc);
    1189          83 :   if (qs > 0)
    1190          44 :     return dcc.qs;
    1191          39 :   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
    1192          39 :   return qs;
    1193             : }
    1194             : 
    1195             : 
    1196             : /**
    1197             :  * Insert information about the auditor's progress with an exchange's
    1198             :  * data.
    1199             :  *
    1200             :  * @param cls the @e cls of this struct with the plugin-specific state
    1201             :  * @param master_pub master key of the exchange
    1202             :  * @param ppr where is the auditor in processing
    1203             :  * @return transaction status code
    1204             :  */
    1205             : static enum GNUNET_DB_QueryStatus
    1206          41 : postgres_insert_auditor_progress_reserve (
    1207             :   void *cls,
    1208             :   const struct TALER_MasterPublicKeyP *master_pub,
    1209             :   const struct TALER_AUDITORDB_ProgressPointReserve *ppr)
    1210             : {
    1211          41 :   struct PostgresClosure *pg = cls;
    1212          41 :   struct GNUNET_PQ_QueryParam params[] = {
    1213          41 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1214          41 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_in_serial_id),
    1215          41 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_out_serial_id),
    1216          41 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_recoup_serial_id),
    1217          41 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_close_serial_id),
    1218             :     GNUNET_PQ_query_param_end
    1219             :   };
    1220             : 
    1221          41 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1222             :                                              "auditor_progress_insert_reserve",
    1223             :                                              params);
    1224             : }
    1225             : 
    1226             : 
    1227             : /**
    1228             :  * Update information about the progress of the auditor.  There
    1229             :  * must be an existing record for the exchange.
    1230             :  *
    1231             :  * @param cls the @e cls of this struct with the plugin-specific state
    1232             :  * @param master_pub master key of the exchange
    1233             :  * @param ppr where is the auditor in processing
    1234             :  * @return transaction status code
    1235             :  */
    1236             : static enum GNUNET_DB_QueryStatus
    1237          42 : postgres_update_auditor_progress_reserve (
    1238             :   void *cls,
    1239             :   const struct TALER_MasterPublicKeyP *master_pub,
    1240             :   const struct TALER_AUDITORDB_ProgressPointReserve *ppr)
    1241             : {
    1242          42 :   struct PostgresClosure *pg = cls;
    1243          42 :   struct GNUNET_PQ_QueryParam params[] = {
    1244          42 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_in_serial_id),
    1245          42 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_out_serial_id),
    1246          42 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_recoup_serial_id),
    1247          42 :     GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_close_serial_id),
    1248          42 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1249             :     GNUNET_PQ_query_param_end
    1250             :   };
    1251             : 
    1252          42 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1253             :                                              "auditor_progress_update_reserve",
    1254             :                                              params);
    1255             : }
    1256             : 
    1257             : 
    1258             : /**
    1259             :  * Get information about the progress of the auditor.
    1260             :  *
    1261             :  * @param cls the @e cls of this struct with the plugin-specific state
    1262             :  * @param master_pub master key of the exchange
    1263             :  * @param[out] ppr set to where the auditor is in processing
    1264             :  * @return transaction status code
    1265             :  */
    1266             : static enum GNUNET_DB_QueryStatus
    1267          83 : postgres_get_auditor_progress_reserve (
    1268             :   void *cls,
    1269             :   const struct TALER_MasterPublicKeyP *master_pub,
    1270             :   struct TALER_AUDITORDB_ProgressPointReserve *ppr)
    1271             : {
    1272          83 :   struct PostgresClosure *pg = cls;
    1273          83 :   struct GNUNET_PQ_QueryParam params[] = {
    1274          83 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1275             :     GNUNET_PQ_query_param_end
    1276             :   };
    1277          83 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1278          83 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_in_serial_id",
    1279             :                                   &ppr->last_reserve_in_serial_id),
    1280          83 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_out_serial_id",
    1281             :                                   &ppr->last_reserve_out_serial_id),
    1282          83 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_recoup_serial_id",
    1283             :                                   &ppr->last_reserve_recoup_serial_id),
    1284          83 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_close_serial_id",
    1285             :                                   &ppr->last_reserve_close_serial_id),
    1286             :     GNUNET_PQ_result_spec_end
    1287             :   };
    1288             : 
    1289          83 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    1290             :                                                    "auditor_progress_select_reserve",
    1291             :                                                    params,
    1292             :                                                    rs);
    1293             : }
    1294             : 
    1295             : 
    1296             : /**
    1297             :  * Insert information about the auditor's progress with an exchange's
    1298             :  * data.
    1299             :  *
    1300             :  * @param cls the @e cls of this struct with the plugin-specific state
    1301             :  * @param master_pub master key of the exchange
    1302             :  * @param ppa where is the auditor in processing
    1303             :  * @return transaction status code
    1304             :  */
    1305             : static enum GNUNET_DB_QueryStatus
    1306          17 : postgres_insert_auditor_progress_aggregation (
    1307             :   void *cls,
    1308             :   const struct TALER_MasterPublicKeyP *master_pub,
    1309             :   const struct TALER_AUDITORDB_ProgressPointAggregation *ppa)
    1310             : {
    1311          17 :   struct PostgresClosure *pg = cls;
    1312          17 :   struct GNUNET_PQ_QueryParam params[] = {
    1313          17 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1314          17 :     GNUNET_PQ_query_param_uint64 (&ppa->last_wire_out_serial_id),
    1315             :     GNUNET_PQ_query_param_end
    1316             :   };
    1317             : 
    1318          17 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1319             :                                              "auditor_progress_insert_aggregation",
    1320             :                                              params);
    1321             : }
    1322             : 
    1323             : 
    1324             : /**
    1325             :  * Update information about the progress of the auditor.  There
    1326             :  * must be an existing record for the exchange.
    1327             :  *
    1328             :  * @param cls the @e cls of this struct with the plugin-specific state
    1329             :  * @param master_pub master key of the exchange
    1330             :  * @param ppa where is the auditor in processing
    1331             :  * @return transaction status code
    1332             :  */
    1333             : static enum GNUNET_DB_QueryStatus
    1334           0 : postgres_update_auditor_progress_aggregation (
    1335             :   void *cls,
    1336             :   const struct TALER_MasterPublicKeyP *master_pub,
    1337             :   const struct TALER_AUDITORDB_ProgressPointAggregation *ppa)
    1338             : {
    1339           0 :   struct PostgresClosure *pg = cls;
    1340           0 :   struct GNUNET_PQ_QueryParam params[] = {
    1341           0 :     GNUNET_PQ_query_param_uint64 (&ppa->last_wire_out_serial_id),
    1342           0 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1343             :     GNUNET_PQ_query_param_end
    1344             :   };
    1345             : 
    1346           0 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1347             :                                              "auditor_progress_update_aggregation",
    1348             :                                              params);
    1349             : }
    1350             : 
    1351             : 
    1352             : /**
    1353             :  * Get information about the progress of the auditor.
    1354             :  *
    1355             :  * @param cls the @e cls of this struct with the plugin-specific state
    1356             :  * @param master_pub master key of the exchange
    1357             :  * @param[out] ppa set to where the auditor is in processing
    1358             :  * @return transaction status code
    1359             :  */
    1360             : static enum GNUNET_DB_QueryStatus
    1361          83 : postgres_get_auditor_progress_aggregation (
    1362             :   void *cls,
    1363             :   const struct TALER_MasterPublicKeyP *master_pub,
    1364             :   struct TALER_AUDITORDB_ProgressPointAggregation *ppa)
    1365             : {
    1366          83 :   struct PostgresClosure *pg = cls;
    1367          83 :   struct GNUNET_PQ_QueryParam params[] = {
    1368          83 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1369             :     GNUNET_PQ_query_param_end
    1370             :   };
    1371          83 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1372          83 :     GNUNET_PQ_result_spec_uint64 ("last_wire_out_serial_id",
    1373             :                                   &ppa->last_wire_out_serial_id),
    1374             :     GNUNET_PQ_result_spec_end
    1375             :   };
    1376             : 
    1377          83 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    1378             :                                                    "auditor_progress_select_aggregation",
    1379             :                                                    params,
    1380             :                                                    rs);
    1381             : }
    1382             : 
    1383             : 
    1384             : /**
    1385             :  * Insert information about the auditor's progress with an exchange's
    1386             :  * data.
    1387             :  *
    1388             :  * @param cls the @e cls of this struct with the plugin-specific state
    1389             :  * @param master_pub master key of the exchange
    1390             :  * @param ppdc where is the auditor in processing
    1391             :  * @return transaction status code
    1392             :  */
    1393             : static enum GNUNET_DB_QueryStatus
    1394          41 : postgres_insert_auditor_progress_deposit_confirmation (
    1395             :   void *cls,
    1396             :   const struct TALER_MasterPublicKeyP *master_pub,
    1397             :   const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc)
    1398             : {
    1399          41 :   struct PostgresClosure *pg = cls;
    1400          41 :   struct GNUNET_PQ_QueryParam params[] = {
    1401          41 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1402          41 :     GNUNET_PQ_query_param_uint64 (&ppdc->last_deposit_confirmation_serial_id),
    1403             :     GNUNET_PQ_query_param_end
    1404             :   };
    1405             : 
    1406          41 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1407             :                                              "auditor_progress_insert_deposit_confirmation",
    1408             :                                              params);
    1409             : }
    1410             : 
    1411             : 
    1412             : /**
    1413             :  * Update information about the progress of the auditor.  There
    1414             :  * must be an existing record for the exchange.
    1415             :  *
    1416             :  * @param cls the @e cls of this struct with the plugin-specific state
    1417             :  * @param master_pub master key of the exchange
    1418             :  * @param ppdc where is the auditor in processing
    1419             :  * @return transaction status code
    1420             :  */
    1421             : static enum GNUNET_DB_QueryStatus
    1422          42 : postgres_update_auditor_progress_deposit_confirmation (
    1423             :   void *cls,
    1424             :   const struct TALER_MasterPublicKeyP *master_pub,
    1425             :   const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc)
    1426             : {
    1427          42 :   struct PostgresClosure *pg = cls;
    1428          42 :   struct GNUNET_PQ_QueryParam params[] = {
    1429          42 :     GNUNET_PQ_query_param_uint64 (&ppdc->last_deposit_confirmation_serial_id),
    1430          42 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1431             :     GNUNET_PQ_query_param_end
    1432             :   };
    1433             : 
    1434          42 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1435             :                                              "auditor_progress_update_deposit_confirmation",
    1436             :                                              params);
    1437             : }
    1438             : 
    1439             : 
    1440             : /**
    1441             :  * Get information about the progress of the auditor.
    1442             :  *
    1443             :  * @param cls the @e cls of this struct with the plugin-specific state
    1444             :  * @param master_pub master key of the exchange
    1445             :  * @param[out] ppdc set to where the auditor is in processing
    1446             :  * @return transaction status code
    1447             :  */
    1448             : static enum GNUNET_DB_QueryStatus
    1449          83 : postgres_get_auditor_progress_deposit_confirmation (
    1450             :   void *cls,
    1451             :   const struct TALER_MasterPublicKeyP *master_pub,
    1452             :   struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc)
    1453             : {
    1454          83 :   struct PostgresClosure *pg = cls;
    1455          83 :   struct GNUNET_PQ_QueryParam params[] = {
    1456          83 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1457             :     GNUNET_PQ_query_param_end
    1458             :   };
    1459          83 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1460          83 :     GNUNET_PQ_result_spec_uint64 ("last_deposit_confirmation_serial_id",
    1461             :                                   &ppdc->last_deposit_confirmation_serial_id),
    1462             :     GNUNET_PQ_result_spec_end
    1463             :   };
    1464             : 
    1465          83 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    1466             :                                                    "auditor_progress_select_deposit_confirmation",
    1467             :                                                    params,
    1468             :                                                    rs);
    1469             : }
    1470             : 
    1471             : 
    1472             : /**
    1473             :  * Insert information about the auditor's progress with an exchange's
    1474             :  * data.
    1475             :  *
    1476             :  * @param cls the @e cls of this struct with the plugin-specific state
    1477             :  * @param master_pub master key of the exchange
    1478             :  * @param ppc where is the auditor in processing
    1479             :  * @return transaction status code
    1480             :  */
    1481             : static enum GNUNET_DB_QueryStatus
    1482          42 : postgres_insert_auditor_progress_coin (
    1483             :   void *cls,
    1484             :   const struct TALER_MasterPublicKeyP *master_pub,
    1485             :   const struct TALER_AUDITORDB_ProgressPointCoin *ppc)
    1486             : {
    1487          42 :   struct PostgresClosure *pg = cls;
    1488          42 :   struct GNUNET_PQ_QueryParam params[] = {
    1489          42 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1490          42 :     GNUNET_PQ_query_param_uint64 (&ppc->last_withdraw_serial_id),
    1491          42 :     GNUNET_PQ_query_param_uint64 (&ppc->last_deposit_serial_id),
    1492          42 :     GNUNET_PQ_query_param_uint64 (&ppc->last_melt_serial_id),
    1493          42 :     GNUNET_PQ_query_param_uint64 (&ppc->last_refund_serial_id),
    1494          42 :     GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_serial_id),
    1495          42 :     GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_refresh_serial_id),
    1496             :     GNUNET_PQ_query_param_end
    1497             :   };
    1498             : 
    1499          42 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1500             :                                              "auditor_progress_insert_coin",
    1501             :                                              params);
    1502             : }
    1503             : 
    1504             : 
    1505             : /**
    1506             :  * Update information about the progress of the auditor.  There
    1507             :  * must be an existing record for the exchange.
    1508             :  *
    1509             :  * @param cls the @e cls of this struct with the plugin-specific state
    1510             :  * @param master_pub master key of the exchange
    1511             :  * @param ppc where is the auditor in processing
    1512             :  * @return transaction status code
    1513             :  */
    1514             : static enum GNUNET_DB_QueryStatus
    1515          43 : postgres_update_auditor_progress_coin (
    1516             :   void *cls,
    1517             :   const struct TALER_MasterPublicKeyP *master_pub,
    1518             :   const struct TALER_AUDITORDB_ProgressPointCoin *ppc)
    1519             : {
    1520          43 :   struct PostgresClosure *pg = cls;
    1521          43 :   struct GNUNET_PQ_QueryParam params[] = {
    1522          43 :     GNUNET_PQ_query_param_uint64 (&ppc->last_withdraw_serial_id),
    1523          43 :     GNUNET_PQ_query_param_uint64 (&ppc->last_deposit_serial_id),
    1524          43 :     GNUNET_PQ_query_param_uint64 (&ppc->last_melt_serial_id),
    1525          43 :     GNUNET_PQ_query_param_uint64 (&ppc->last_refund_serial_id),
    1526          43 :     GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_serial_id),
    1527          43 :     GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_refresh_serial_id),
    1528          43 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1529             :     GNUNET_PQ_query_param_end
    1530             :   };
    1531             : 
    1532          43 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1533             :                                              "auditor_progress_update_coin",
    1534             :                                              params);
    1535             : }
    1536             : 
    1537             : 
    1538             : /**
    1539             :  * Get information about the progress of the auditor.
    1540             :  *
    1541             :  * @param cls the @e cls of this struct with the plugin-specific state
    1542             :  * @param master_pub master key of the exchange
    1543             :  * @param[out] ppc set to where the auditor is in processing
    1544             :  * @return transaction status code
    1545             :  */
    1546             : static enum GNUNET_DB_QueryStatus
    1547          84 : postgres_get_auditor_progress_coin (
    1548             :   void *cls,
    1549             :   const struct TALER_MasterPublicKeyP *master_pub,
    1550             :   struct TALER_AUDITORDB_ProgressPointCoin *ppc)
    1551             : {
    1552          84 :   struct PostgresClosure *pg = cls;
    1553          84 :   struct GNUNET_PQ_QueryParam params[] = {
    1554          84 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1555             :     GNUNET_PQ_query_param_end
    1556             :   };
    1557          84 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1558          84 :     GNUNET_PQ_result_spec_uint64 ("last_withdraw_serial_id",
    1559             :                                   &ppc->last_withdraw_serial_id),
    1560          84 :     GNUNET_PQ_result_spec_uint64 ("last_deposit_serial_id",
    1561             :                                   &ppc->last_deposit_serial_id),
    1562          84 :     GNUNET_PQ_result_spec_uint64 ("last_melt_serial_id",
    1563             :                                   &ppc->last_melt_serial_id),
    1564          84 :     GNUNET_PQ_result_spec_uint64 ("last_refund_serial_id",
    1565             :                                   &ppc->last_refund_serial_id),
    1566          84 :     GNUNET_PQ_result_spec_uint64 ("last_recoup_serial_id",
    1567             :                                   &ppc->last_recoup_serial_id),
    1568          84 :     GNUNET_PQ_result_spec_uint64 ("last_recoup_refresh_serial_id",
    1569             :                                   &ppc->last_recoup_refresh_serial_id),
    1570             :     GNUNET_PQ_result_spec_end
    1571             :   };
    1572             : 
    1573          84 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    1574             :                                                    "auditor_progress_select_coin",
    1575             :                                                    params,
    1576             :                                                    rs);
    1577             : }
    1578             : 
    1579             : 
    1580             : /**
    1581             :  * Insert information about the auditor's progress with an exchange's
    1582             :  * data.
    1583             :  *
    1584             :  * @param cls the @e cls of this struct with the plugin-specific state
    1585             :  * @param master_pub master key of the exchange
    1586             :  * @param account_name name of the wire account we are auditing
    1587             :  * @param pp how far are we in the auditor's tables
    1588             :  * @param in_wire_off how far are we in the incoming wire transfers
    1589             :  * @param out_wire_off how far are we in the outgoing wire transfers
    1590             :  * @return transaction status code
    1591             :  */
    1592             : static enum GNUNET_DB_QueryStatus
    1593          41 : postgres_insert_wire_auditor_account_progress (
    1594             :   void *cls,
    1595             :   const struct TALER_MasterPublicKeyP *master_pub,
    1596             :   const char *account_name,
    1597             :   const struct TALER_AUDITORDB_WireAccountProgressPoint *pp,
    1598             :   uint64_t in_wire_off,
    1599             :   uint64_t out_wire_off)
    1600             : {
    1601          41 :   struct PostgresClosure *pg = cls;
    1602          41 :   struct GNUNET_PQ_QueryParam params[] = {
    1603          41 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1604          41 :     GNUNET_PQ_query_param_string (account_name),
    1605          41 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
    1606          41 :     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
    1607          41 :     GNUNET_PQ_query_param_uint64 (&in_wire_off),
    1608          41 :     GNUNET_PQ_query_param_uint64 (&out_wire_off),
    1609             :     GNUNET_PQ_query_param_end
    1610             :   };
    1611             : 
    1612          41 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1613             :                                              "wire_auditor_account_progress_insert",
    1614             :                                              params);
    1615             : }
    1616             : 
    1617             : 
    1618             : /**
    1619             :  * Update information about the progress of the auditor.  There
    1620             :  * must be an existing record for the exchange.
    1621             :  *
    1622             :  * @param cls the @e cls of this struct with the plugin-specific state
    1623             :  * @param master_pub master key of the exchange
    1624             :  * @param account_name name of the wire account we are auditing
    1625             :  * @param pp where is the auditor in processing
    1626             :  * @param in_wire_off how far are we in the incoming wire transaction history
    1627             :  * @param out_wire_off how far are we in the outgoing wire transaction history
    1628             :  * @return transaction status code
    1629             :  */
    1630             : static enum GNUNET_DB_QueryStatus
    1631          42 : postgres_update_wire_auditor_account_progress (
    1632             :   void *cls,
    1633             :   const struct TALER_MasterPublicKeyP *master_pub,
    1634             :   const char *account_name,
    1635             :   const struct TALER_AUDITORDB_WireAccountProgressPoint *pp,
    1636             :   uint64_t in_wire_off,
    1637             :   uint64_t out_wire_off)
    1638             : {
    1639          42 :   struct PostgresClosure *pg = cls;
    1640          42 :   struct GNUNET_PQ_QueryParam params[] = {
    1641          42 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
    1642          42 :     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
    1643          42 :     GNUNET_PQ_query_param_uint64 (&in_wire_off),
    1644          42 :     GNUNET_PQ_query_param_uint64 (&out_wire_off),
    1645          42 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1646          42 :     GNUNET_PQ_query_param_string (account_name),
    1647             :     GNUNET_PQ_query_param_end
    1648             :   };
    1649             : 
    1650          42 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1651             :                                              "wire_auditor_account_progress_update",
    1652             :                                              params);
    1653             : }
    1654             : 
    1655             : 
    1656             : /**
    1657             :  * Get information about the progress of the auditor.
    1658             :  *
    1659             :  * @param cls the @e cls of this struct with the plugin-specific state
    1660             :  * @param master_pub master key of the exchange
    1661             :  * @param account_name name of the wire account we are auditing
    1662             :  * @param[out] pp where is the auditor in processing
    1663             :  * @param[out] in_wire_off how far are we in the incoming wire transaction history
    1664             :  * @param[out] out_wire_off how far are we in the outgoing wire transaction history
    1665             :  * @return transaction status code
    1666             :  */
    1667             : static enum GNUNET_DB_QueryStatus
    1668          83 : postgres_get_wire_auditor_account_progress (
    1669             :   void *cls,
    1670             :   const struct TALER_MasterPublicKeyP *master_pub,
    1671             :   const char *account_name,
    1672             :   struct TALER_AUDITORDB_WireAccountProgressPoint *pp,
    1673             :   uint64_t *in_wire_off,
    1674             :   uint64_t *out_wire_off)
    1675             : {
    1676          83 :   struct PostgresClosure *pg = cls;
    1677          83 :   struct GNUNET_PQ_QueryParam params[] = {
    1678          83 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1679          83 :     GNUNET_PQ_query_param_string (account_name),
    1680             :     GNUNET_PQ_query_param_end
    1681             :   };
    1682          83 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1683          83 :     GNUNET_PQ_result_spec_uint64 ("last_wire_reserve_in_serial_id",
    1684             :                                   &pp->last_reserve_in_serial_id),
    1685          83 :     GNUNET_PQ_result_spec_uint64 ("last_wire_wire_out_serial_id",
    1686             :                                   &pp->last_wire_out_serial_id),
    1687          83 :     GNUNET_PQ_result_spec_uint64 ("wire_in_off",
    1688             :                                   in_wire_off),
    1689          83 :     GNUNET_PQ_result_spec_uint64 ("wire_out_off",
    1690             :                                   out_wire_off),
    1691             :     GNUNET_PQ_result_spec_end
    1692             :   };
    1693             : 
    1694          83 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    1695             :                                                    "wire_auditor_account_progress_select",
    1696             :                                                    params,
    1697             :                                                    rs);
    1698             : }
    1699             : 
    1700             : 
    1701             : /**
    1702             :  * Insert information about the auditor's progress with an exchange's
    1703             :  * data.
    1704             :  *
    1705             :  * @param cls the @e cls of this struct with the plugin-specific state
    1706             :  * @param master_pub master key of the exchange
    1707             :  * @param pp where is the auditor in processing
    1708             :  * @return transaction status code
    1709             :  */
    1710             : static enum GNUNET_DB_QueryStatus
    1711          41 : postgres_insert_wire_auditor_progress (
    1712             :   void *cls,
    1713             :   const struct TALER_MasterPublicKeyP *master_pub,
    1714             :   const struct TALER_AUDITORDB_WireProgressPoint *pp)
    1715             : {
    1716          41 :   struct PostgresClosure *pg = cls;
    1717          41 :   struct GNUNET_PQ_QueryParam params[] = {
    1718          41 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1719          41 :     TALER_PQ_query_param_absolute_time (&pp->last_timestamp),
    1720          41 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_close_uuid),
    1721             :     GNUNET_PQ_query_param_end
    1722             :   };
    1723             : 
    1724          41 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1725             :                                              "wire_auditor_progress_insert",
    1726             :                                              params);
    1727             : }
    1728             : 
    1729             : 
    1730             : /**
    1731             :  * Update information about the progress of the auditor.  There
    1732             :  * must be an existing record for the exchange.
    1733             :  *
    1734             :  * @param cls the @e cls of this struct with the plugin-specific state
    1735             :  * @param master_pub master key of the exchange
    1736             :  * @param pp where is the auditor in processing
    1737             :  * @return transaction status code
    1738             :  */
    1739             : static enum GNUNET_DB_QueryStatus
    1740          42 : postgres_update_wire_auditor_progress (
    1741             :   void *cls,
    1742             :   const struct TALER_MasterPublicKeyP *master_pub,
    1743             :   const struct TALER_AUDITORDB_WireProgressPoint *pp)
    1744             : {
    1745          42 :   struct PostgresClosure *pg = cls;
    1746          42 :   struct GNUNET_PQ_QueryParam params[] = {
    1747          42 :     TALER_PQ_query_param_absolute_time (&pp->last_timestamp),
    1748          42 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_close_uuid),
    1749          42 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1750             :     GNUNET_PQ_query_param_end
    1751             :   };
    1752             : 
    1753          42 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1754             :                                              "wire_auditor_progress_update",
    1755             :                                              params);
    1756             : }
    1757             : 
    1758             : 
    1759             : /**
    1760             :  * Get information about the progress of the auditor.
    1761             :  *
    1762             :  * @param cls the @e cls of this struct with the plugin-specific state
    1763             :  * @param master_pub master key of the exchange
    1764             :  * @param[out] pp set to where the auditor is in processing
    1765             :  * @return transaction status code
    1766             :  */
    1767             : static enum GNUNET_DB_QueryStatus
    1768          83 : postgres_get_wire_auditor_progress (
    1769             :   void *cls,
    1770             :   const struct TALER_MasterPublicKeyP *master_pub,
    1771             :   struct TALER_AUDITORDB_WireProgressPoint *pp)
    1772             : {
    1773          83 :   struct PostgresClosure *pg = cls;
    1774          83 :   struct GNUNET_PQ_QueryParam params[] = {
    1775          83 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1776             :     GNUNET_PQ_query_param_end
    1777             :   };
    1778          83 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1779          83 :     TALER_PQ_result_spec_absolute_time ("last_timestamp",
    1780             :                                         &pp->last_timestamp),
    1781          83 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_close_uuid",
    1782             :                                   &pp->last_reserve_close_uuid),
    1783             :     GNUNET_PQ_result_spec_end
    1784             :   };
    1785             : 
    1786          83 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    1787             :                                                    "wire_auditor_progress_select",
    1788             :                                                    params,
    1789             :                                                    rs);
    1790             : }
    1791             : 
    1792             : 
    1793             : /**
    1794             :  * Insert information about a reserve.  There must not be an
    1795             :  * existing record for the reserve.
    1796             :  *
    1797             :  * @param cls the @e cls of this struct with the plugin-specific state
    1798             :  * @param reserve_pub public key of the reserve
    1799             :  * @param master_pub master public key of the exchange
    1800             :  * @param reserve_balance amount stored in the reserve
    1801             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1802             :  *                             due to withdrawals from this reserve
    1803             :  * @param expiration_date expiration date of the reserve
    1804             :  * @param origin_account where did the money in the reserve originally come from
    1805             :  * @return transaction status code
    1806             :  */
    1807             : static enum GNUNET_DB_QueryStatus
    1808          84 : postgres_insert_reserve_info (void *cls,
    1809             :                               const struct TALER_ReservePublicKeyP *reserve_pub,
    1810             :                               const struct TALER_MasterPublicKeyP *master_pub,
    1811             :                               const struct TALER_Amount *reserve_balance,
    1812             :                               const struct TALER_Amount *withdraw_fee_balance,
    1813             :                               struct GNUNET_TIME_Absolute expiration_date,
    1814             :                               const char *origin_account)
    1815             : {
    1816          84 :   struct PostgresClosure *pg = cls;
    1817          84 :   struct GNUNET_PQ_QueryParam params[] = {
    1818          84 :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1819          84 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1820          84 :     TALER_PQ_query_param_amount (reserve_balance),
    1821          84 :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    1822          84 :     TALER_PQ_query_param_absolute_time (&expiration_date),
    1823          84 :     GNUNET_PQ_query_param_string (origin_account),
    1824             :     GNUNET_PQ_query_param_end
    1825             :   };
    1826             : 
    1827          84 :   GNUNET_assert (GNUNET_YES ==
    1828             :                  TALER_amount_cmp_currency (reserve_balance,
    1829             :                                             withdraw_fee_balance));
    1830             : 
    1831          84 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1832             :                                              "auditor_reserves_insert",
    1833             :                                              params);
    1834             : }
    1835             : 
    1836             : 
    1837             : /**
    1838             :  * Update information about a reserve.  Destructively updates an
    1839             :  * existing record, which must already exist.
    1840             :  *
    1841             :  * @param cls the @e cls of this struct with the plugin-specific state
    1842             :  * @param reserve_pub public key of the reserve
    1843             :  * @param master_pub master public key of the exchange
    1844             :  * @param reserve_balance amount stored in the reserve
    1845             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1846             :  *                             due to withdrawals from this reserve
    1847             :  * @param expiration_date expiration date of the reserve
    1848             :  * @return transaction status code
    1849             :  */
    1850             : static enum GNUNET_DB_QueryStatus
    1851           1 : postgres_update_reserve_info (void *cls,
    1852             :                               const struct TALER_ReservePublicKeyP *reserve_pub,
    1853             :                               const struct TALER_MasterPublicKeyP *master_pub,
    1854             :                               const struct TALER_Amount *reserve_balance,
    1855             :                               const struct TALER_Amount *withdraw_fee_balance,
    1856             :                               struct GNUNET_TIME_Absolute expiration_date)
    1857             : {
    1858           1 :   struct PostgresClosure *pg = cls;
    1859           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1860           1 :     TALER_PQ_query_param_amount (reserve_balance),
    1861           1 :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    1862           1 :     TALER_PQ_query_param_absolute_time (&expiration_date),
    1863           1 :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1864           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1865             :     GNUNET_PQ_query_param_end
    1866             :   };
    1867             : 
    1868           1 :   GNUNET_assert (GNUNET_YES ==
    1869             :                  TALER_amount_cmp_currency (reserve_balance,
    1870             :                                             withdraw_fee_balance));
    1871             : 
    1872           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1873             :                                              "auditor_reserves_update",
    1874             :                                              params);
    1875             : }
    1876             : 
    1877             : 
    1878             : /**
    1879             :  * Delete information about a reserve.
    1880             :  *
    1881             :  * @param cls the @e cls of this struct with the plugin-specific state
    1882             :  * @param reserve_pub public key of the reserve
    1883             :  * @param master_pub master public key of the exchange
    1884             :  * @return transaction status code
    1885             :  */
    1886             : static enum GNUNET_DB_QueryStatus
    1887           1 : postgres_del_reserve_info (void *cls,
    1888             :                            const struct TALER_ReservePublicKeyP *reserve_pub,
    1889             :                            const struct TALER_MasterPublicKeyP *master_pub)
    1890             : {
    1891           1 :   struct PostgresClosure *pg = cls;
    1892           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1893           1 :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1894           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1895             :     GNUNET_PQ_query_param_end
    1896             :   };
    1897             : 
    1898           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1899             :                                              "auditor_reserves_delete",
    1900             :                                              params);
    1901             : }
    1902             : 
    1903             : 
    1904             : /**
    1905             :  * Get information about a reserve.
    1906             :  *
    1907             :  * @param cls the @e cls of this struct with the plugin-specific state
    1908             :  * @param reserve_pub public key of the reserve
    1909             :  * @param master_pub master public key of the exchange
    1910             :  * @param[out] rowid which row did we get the information from
    1911             :  * @param[out] reserve_balance amount stored in the reserve
    1912             :  * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees
    1913             :  *                             due to withdrawals from this reserve
    1914             :  * @param[out] expiration_date expiration date of the reserve
    1915             :  * @param[out] sender_account from where did the money in the reserve originally come from
    1916             :  * @return transaction status code
    1917             :  */
    1918             : static enum GNUNET_DB_QueryStatus
    1919          84 : postgres_get_reserve_info (void *cls,
    1920             :                            const struct TALER_ReservePublicKeyP *reserve_pub,
    1921             :                            const struct TALER_MasterPublicKeyP *master_pub,
    1922             :                            uint64_t *rowid,
    1923             :                            struct TALER_Amount *reserve_balance,
    1924             :                            struct TALER_Amount *withdraw_fee_balance,
    1925             :                            struct GNUNET_TIME_Absolute *expiration_date,
    1926             :                            char **sender_account)
    1927             : {
    1928          84 :   struct PostgresClosure *pg = cls;
    1929          84 :   struct GNUNET_PQ_QueryParam params[] = {
    1930          84 :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1931          84 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1932             :     GNUNET_PQ_query_param_end
    1933             :   };
    1934          84 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1935          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_balance", reserve_balance),
    1936          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("withdraw_fee_balance", withdraw_fee_balance),
    1937          84 :     TALER_PQ_result_spec_absolute_time ("expiration_date", expiration_date),
    1938          84 :     GNUNET_PQ_result_spec_uint64 ("auditor_reserves_rowid", rowid),
    1939          84 :     GNUNET_PQ_result_spec_string ("origin_account", sender_account),
    1940             :     GNUNET_PQ_result_spec_end
    1941             :   };
    1942             : 
    1943          84 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    1944             :                                                    "auditor_reserves_select",
    1945             :                                                    params,
    1946             :                                                    rs);
    1947             : }
    1948             : 
    1949             : 
    1950             : /**
    1951             :  * Insert information about all reserves.  There must not be an
    1952             :  * existing record for the @a master_pub.
    1953             :  *
    1954             :  * @param cls the @e cls of this struct with the plugin-specific state
    1955             :  * @param master_pub master public key of the exchange
    1956             :  * @param reserve_balance amount stored in the reserve
    1957             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1958             :  *                             due to withdrawals from this reserve
    1959             :  * @return transaction status code
    1960             :  */
    1961             : static enum GNUNET_DB_QueryStatus
    1962          42 : postgres_insert_reserve_summary (
    1963             :   void *cls,
    1964             :   const struct TALER_MasterPublicKeyP *master_pub,
    1965             :   const struct TALER_Amount *reserve_balance,
    1966             :   const struct TALER_Amount *withdraw_fee_balance)
    1967             : {
    1968          42 :   struct PostgresClosure *pg = cls;
    1969          42 :   struct GNUNET_PQ_QueryParam params[] = {
    1970          42 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1971          42 :     TALER_PQ_query_param_amount (reserve_balance),
    1972          42 :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    1973             :     GNUNET_PQ_query_param_end
    1974             :   };
    1975             : 
    1976          42 :   GNUNET_assert (GNUNET_YES ==
    1977             :                  TALER_amount_cmp_currency (reserve_balance,
    1978             :                                             withdraw_fee_balance));
    1979             : 
    1980          42 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    1981             :                                              "auditor_reserve_balance_insert",
    1982             :                                              params);
    1983             : }
    1984             : 
    1985             : 
    1986             : /**
    1987             :  * Update information about all reserves.  Destructively updates an
    1988             :  * existing record, which must already exist.
    1989             :  *
    1990             :  * @param cls the @e cls of this struct with the plugin-specific state
    1991             :  * @param master_pub master public key of the exchange
    1992             :  * @param reserve_balance amount stored in the reserve
    1993             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1994             :  *                             due to withdrawals from this reserve
    1995             :  * @return transaction status code
    1996             :  */
    1997             : static enum GNUNET_DB_QueryStatus
    1998          43 : postgres_update_reserve_summary (
    1999             :   void *cls,
    2000             :   const struct TALER_MasterPublicKeyP *master_pub,
    2001             :   const struct TALER_Amount *reserve_balance,
    2002             :   const struct TALER_Amount *withdraw_fee_balance)
    2003             : {
    2004          43 :   struct PostgresClosure *pg = cls;
    2005          43 :   struct GNUNET_PQ_QueryParam params[] = {
    2006          43 :     TALER_PQ_query_param_amount (reserve_balance),
    2007          43 :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    2008          43 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2009             :     GNUNET_PQ_query_param_end
    2010             :   };
    2011             : 
    2012          43 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2013             :                                              "auditor_reserve_balance_update",
    2014             :                                              params);
    2015             : }
    2016             : 
    2017             : 
    2018             : /**
    2019             :  * Get summary information about all reserves.
    2020             :  *
    2021             :  * @param cls the @e cls of this struct with the plugin-specific state
    2022             :  * @param master_pub master public key of the exchange
    2023             :  * @param[out] reserve_balance amount stored in the reserve
    2024             :  * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees
    2025             :  *                             due to withdrawals from this reserve
    2026             :  * @return transaction status code
    2027             :  */
    2028             : static enum GNUNET_DB_QueryStatus
    2029          84 : postgres_get_reserve_summary (void *cls,
    2030             :                               const struct TALER_MasterPublicKeyP *master_pub,
    2031             :                               struct TALER_Amount *reserve_balance,
    2032             :                               struct TALER_Amount *withdraw_fee_balance)
    2033             : {
    2034          84 :   struct PostgresClosure *pg = cls;
    2035          84 :   struct GNUNET_PQ_QueryParam params[] = {
    2036          84 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2037             :     GNUNET_PQ_query_param_end
    2038             :   };
    2039          84 :   struct GNUNET_PQ_ResultSpec rs[] = {
    2040          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_balance", reserve_balance),
    2041          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("withdraw_fee_balance", withdraw_fee_balance),
    2042             : 
    2043             :     GNUNET_PQ_result_spec_end
    2044             :   };
    2045             : 
    2046          84 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    2047             :                                                    "auditor_reserve_balance_select",
    2048             :                                                    params,
    2049             :                                                    rs);
    2050             : }
    2051             : 
    2052             : 
    2053             : /**
    2054             :  * Insert information about exchange's wire fee balance. There must not be an
    2055             :  * existing record for the same @a master_pub.
    2056             :  *
    2057             :  * @param cls the @e cls of this struct with the plugin-specific state
    2058             :  * @param master_pub master public key of the exchange
    2059             :  * @param wire_fee_balance amount the exchange gained in wire fees
    2060             :  * @return transaction status code
    2061             :  */
    2062             : static enum GNUNET_DB_QueryStatus
    2063          18 : postgres_insert_wire_fee_summary (
    2064             :   void *cls,
    2065             :   const struct TALER_MasterPublicKeyP *master_pub,
    2066             :   const struct TALER_Amount *wire_fee_balance)
    2067             : {
    2068          18 :   struct PostgresClosure *pg = cls;
    2069          18 :   struct GNUNET_PQ_QueryParam params[] = {
    2070          18 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2071          18 :     TALER_PQ_query_param_amount (wire_fee_balance),
    2072             :     GNUNET_PQ_query_param_end
    2073             :   };
    2074             : 
    2075          18 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2076             :                                              "auditor_wire_fee_balance_insert",
    2077             :                                              params);
    2078             : }
    2079             : 
    2080             : 
    2081             : /**
    2082             :  * Insert information about exchange's wire fee balance.  Destructively updates an
    2083             :  * existing record, which must already exist.
    2084             :  *
    2085             :  * @param cls the @e cls of this struct with the plugin-specific state
    2086             :  * @param master_pub master public key of the exchange
    2087             :  * @param wire_fee_balance amount the exchange gained in wire fees
    2088             :  * @return transaction status code
    2089             :  */
    2090             : static enum GNUNET_DB_QueryStatus
    2091           1 : postgres_update_wire_fee_summary (
    2092             :   void *cls,
    2093             :   const struct TALER_MasterPublicKeyP *master_pub,
    2094             :   const struct TALER_Amount *wire_fee_balance)
    2095             : {
    2096           1 :   struct PostgresClosure *pg = cls;
    2097           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2098           1 :     TALER_PQ_query_param_amount (wire_fee_balance),
    2099           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2100             :     GNUNET_PQ_query_param_end
    2101             :   };
    2102             : 
    2103           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2104             :                                              "auditor_wire_fee_balance_update",
    2105             :                                              params);
    2106             : }
    2107             : 
    2108             : 
    2109             : /**
    2110             :  * Get summary information about an exchanges wire fee balance.
    2111             :  *
    2112             :  * @param cls the @e cls of this struct with the plugin-specific state
    2113             :  * @param master_pub master public key of the exchange
    2114             :  * @param[out] wire_fee_balance set amount the exchange gained in wire fees
    2115             :  * @return transaction status code
    2116             :  */
    2117             : static enum GNUNET_DB_QueryStatus
    2118          84 : postgres_get_wire_fee_summary (void *cls,
    2119             :                                const struct TALER_MasterPublicKeyP *master_pub,
    2120             :                                struct TALER_Amount *wire_fee_balance)
    2121             : {
    2122          84 :   struct PostgresClosure *pg = cls;
    2123          84 :   struct GNUNET_PQ_QueryParam params[] = {
    2124          84 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2125             :     GNUNET_PQ_query_param_end
    2126             :   };
    2127          84 :   struct GNUNET_PQ_ResultSpec rs[] = {
    2128          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee_balance",
    2129             :                                  wire_fee_balance),
    2130             :     GNUNET_PQ_result_spec_end
    2131             :   };
    2132             : 
    2133          84 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    2134             :                                                    "auditor_wire_fee_balance_select",
    2135             :                                                    params,
    2136             :                                                    rs);
    2137             : }
    2138             : 
    2139             : 
    2140             : /**
    2141             :  * Insert information about a denomination key's balances.  There
    2142             :  * must not be an existing record for the denomination key.
    2143             :  *
    2144             :  * @param cls the @e cls of this struct with the plugin-specific state
    2145             :  * @param denom_pub_hash hash of the denomination public key
    2146             :  * @param denom_balance value of coins outstanding with this denomination key
    2147             :  * @param denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance)
    2148             :  * @param denom_risk value of coins issued with this denomination key
    2149             :  * @param recoup_loss losses from recoup (if this denomination was revoked)
    2150             :  * @param num_issued how many coins of this denomination did the exchange blind-sign
    2151             :  * @return transaction status code
    2152             :  */
    2153             : static enum GNUNET_DB_QueryStatus
    2154         289 : postgres_insert_denomination_balance (
    2155             :   void *cls,
    2156             :   const struct GNUNET_HashCode *denom_pub_hash,
    2157             :   const struct TALER_Amount *denom_balance,
    2158             :   const struct TALER_Amount *denom_loss,
    2159             :   const struct TALER_Amount *denom_risk,
    2160             :   const struct TALER_Amount *recoup_loss,
    2161             :   uint64_t num_issued)
    2162             : {
    2163         289 :   struct PostgresClosure *pg = cls;
    2164         289 :   struct GNUNET_PQ_QueryParam params[] = {
    2165         289 :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    2166         289 :     TALER_PQ_query_param_amount (denom_balance),
    2167         289 :     TALER_PQ_query_param_amount (denom_loss),
    2168         289 :     GNUNET_PQ_query_param_uint64 (&num_issued),
    2169         289 :     TALER_PQ_query_param_amount (denom_risk),
    2170         289 :     TALER_PQ_query_param_amount (recoup_loss),
    2171             :     GNUNET_PQ_query_param_end
    2172             :   };
    2173             : 
    2174         289 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2175             :                                              "auditor_denomination_pending_insert",
    2176             :                                              params);
    2177             : }
    2178             : 
    2179             : 
    2180             : /**
    2181             :  * Update information about a denomination key's balances.  There
    2182             :  * must be an existing record for the denomination key.
    2183             :  *
    2184             :  * @param cls the @e cls of this struct with the plugin-specific state
    2185             :  * @param denom_pub_hash hash of the denomination public key
    2186             :  * @param denom_balance value of coins outstanding with this denomination key
    2187             :  * @param denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance)
    2188             : * @param denom_risk value of coins issued with this denomination key
    2189             :  * @param recoup_loss losses from recoup (if this denomination was revoked)
    2190             :  * @param num_issued how many coins of this denomination did the exchange blind-sign
    2191             :  * @return transaction status code
    2192             :  */
    2193             : static enum GNUNET_DB_QueryStatus
    2194           2 : postgres_update_denomination_balance (
    2195             :   void *cls,
    2196             :   const struct GNUNET_HashCode *denom_pub_hash,
    2197             :   const struct TALER_Amount *denom_balance,
    2198             :   const struct TALER_Amount *denom_loss,
    2199             :   const struct TALER_Amount *denom_risk,
    2200             :   const struct TALER_Amount *recoup_loss,
    2201             :   uint64_t num_issued)
    2202             : {
    2203           2 :   struct PostgresClosure *pg = cls;
    2204           2 :   struct GNUNET_PQ_QueryParam params[] = {
    2205           2 :     TALER_PQ_query_param_amount (denom_balance),
    2206           2 :     TALER_PQ_query_param_amount (denom_loss),
    2207           2 :     GNUNET_PQ_query_param_uint64 (&num_issued),
    2208           2 :     TALER_PQ_query_param_amount (denom_risk),
    2209           2 :     TALER_PQ_query_param_amount (recoup_loss),
    2210           2 :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    2211             :     GNUNET_PQ_query_param_end
    2212             :   };
    2213             : 
    2214           2 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2215             :                                              "auditor_denomination_pending_update",
    2216             :                                              params);
    2217             : }
    2218             : 
    2219             : 
    2220             : /**
    2221             :  * Get information about a denomination key's balances.
    2222             :  *
    2223             :  * @param cls the @e cls of this struct with the plugin-specific state
    2224             :  * @param denom_pub_hash hash of the denomination public key
    2225             :  * @param[out] denom_balance value of coins outstanding with this denomination key
    2226             :  * @param[out] denom_risk value of coins issued with this denomination key
    2227             :  * @param[out] denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance)
    2228             :  * @param[out] recoup_loss losses from recoup (if this denomination was revoked)
    2229             :  * @param[out] num_issued how many coins of this denomination did the exchange blind-sign
    2230             :  * @return transaction status code
    2231             :  */
    2232             : static enum GNUNET_DB_QueryStatus
    2233         290 : postgres_get_denomination_balance (void *cls,
    2234             :                                    const struct GNUNET_HashCode *denom_pub_hash,
    2235             :                                    struct TALER_Amount *denom_balance,
    2236             :                                    struct TALER_Amount *denom_loss,
    2237             :                                    struct TALER_Amount *denom_risk,
    2238             :                                    struct TALER_Amount *recoup_loss,
    2239             :                                    uint64_t *num_issued)
    2240             : {
    2241         290 :   struct PostgresClosure *pg = cls;
    2242         290 :   struct GNUNET_PQ_QueryParam params[] = {
    2243         290 :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    2244             :     GNUNET_PQ_query_param_end
    2245             :   };
    2246         290 :   struct GNUNET_PQ_ResultSpec rs[] = {
    2247         290 :     TALER_PQ_RESULT_SPEC_AMOUNT ("denom_balance", denom_balance),
    2248         290 :     TALER_PQ_RESULT_SPEC_AMOUNT ("denom_loss", denom_loss),
    2249         290 :     TALER_PQ_RESULT_SPEC_AMOUNT ("denom_risk", denom_risk),
    2250         290 :     TALER_PQ_RESULT_SPEC_AMOUNT ("recoup_loss", recoup_loss),
    2251         290 :     GNUNET_PQ_result_spec_uint64 ("num_issued", num_issued),
    2252             :     GNUNET_PQ_result_spec_end
    2253             :   };
    2254             : 
    2255         290 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    2256             :                                                    "auditor_denomination_pending_select",
    2257             :                                                    params,
    2258             :                                                    rs);
    2259             : }
    2260             : 
    2261             : 
    2262             : /**
    2263             :  * Insert information about an exchange's denomination balances.  There
    2264             :  * must not be an existing record for the exchange.
    2265             :  *
    2266             :  * @param cls the @e cls of this struct with the plugin-specific state
    2267             :  * @param master_pub master key of the exchange
    2268             :  * @param denom_balance value of coins outstanding with this denomination key
    2269             :  * @param deposit_fee_balance total deposit fees collected for this DK
    2270             :  * @param melt_fee_balance total melt fees collected for this DK
    2271             :  * @param refund_fee_balance total refund fees collected for this DK
    2272             :  * @param risk maximum risk exposure of the exchange
    2273             :  * @param loss materialized @a risk from recoup
    2274             :  * @param irregular_recoup recoups on non-revoked coins
    2275             :  * @return transaction status code
    2276             :  */
    2277             : static enum GNUNET_DB_QueryStatus
    2278          42 : postgres_insert_balance_summary (
    2279             :   void *cls,
    2280             :   const struct TALER_MasterPublicKeyP *master_pub,
    2281             :   const struct TALER_Amount *denom_balance,
    2282             :   const struct TALER_Amount *deposit_fee_balance,
    2283             :   const struct TALER_Amount *melt_fee_balance,
    2284             :   const struct TALER_Amount *refund_fee_balance,
    2285             :   const struct TALER_Amount *risk,
    2286             :   const struct TALER_Amount *loss,
    2287             :   const struct TALER_Amount *irregular_recoup)
    2288             : {
    2289          42 :   struct PostgresClosure *pg = cls;
    2290          42 :   struct GNUNET_PQ_QueryParam params[] = {
    2291          42 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2292          42 :     TALER_PQ_query_param_amount (denom_balance),
    2293          42 :     TALER_PQ_query_param_amount (deposit_fee_balance),
    2294          42 :     TALER_PQ_query_param_amount (melt_fee_balance),
    2295          42 :     TALER_PQ_query_param_amount (refund_fee_balance),
    2296          42 :     TALER_PQ_query_param_amount (risk),
    2297          42 :     TALER_PQ_query_param_amount (loss),
    2298          42 :     TALER_PQ_query_param_amount (irregular_recoup),
    2299             :     GNUNET_PQ_query_param_end
    2300             :   };
    2301             : 
    2302          42 :   GNUNET_assert (GNUNET_YES ==
    2303             :                  TALER_amount_cmp_currency (denom_balance,
    2304             :                                             deposit_fee_balance));
    2305          42 :   GNUNET_assert (GNUNET_YES ==
    2306             :                  TALER_amount_cmp_currency (denom_balance,
    2307             :                                             melt_fee_balance));
    2308             : 
    2309          42 :   GNUNET_assert (GNUNET_YES ==
    2310             :                  TALER_amount_cmp_currency (denom_balance,
    2311             :                                             refund_fee_balance));
    2312             : 
    2313          42 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2314             :                                              "auditor_balance_summary_insert",
    2315             :                                              params);
    2316             : }
    2317             : 
    2318             : 
    2319             : /**
    2320             :  * Update information about an exchange's denomination balances.  There
    2321             :  * must be an existing record for the exchange.
    2322             :  *
    2323             :  * @param cls the @e cls of this struct with the plugin-specific state
    2324             :  * @param master_pub master key of the exchange
    2325             :  * @param denom_balance value of coins outstanding with this denomination key
    2326             :  * @param deposit_fee_balance total deposit fees collected for this DK
    2327             :  * @param melt_fee_balance total melt fees collected for this DK
    2328             :  * @param refund_fee_balance total refund fees collected for this DK
    2329             :  * @param risk maximum risk exposure of the exchange
    2330             :  * @param loss materialized @a risk from recoup
    2331             :  * @param irregular_recoup recoups made on non-revoked coins
    2332             :  * @return transaction status code
    2333             :  */
    2334             : static enum GNUNET_DB_QueryStatus
    2335          43 : postgres_update_balance_summary (
    2336             :   void *cls,
    2337             :   const struct TALER_MasterPublicKeyP *master_pub,
    2338             :   const struct TALER_Amount *denom_balance,
    2339             :   const struct TALER_Amount *deposit_fee_balance,
    2340             :   const struct TALER_Amount *melt_fee_balance,
    2341             :   const struct TALER_Amount *refund_fee_balance,
    2342             :   const struct TALER_Amount *risk,
    2343             :   const struct TALER_Amount *loss,
    2344             :   const struct TALER_Amount *irregular_recoup)
    2345             : {
    2346          43 :   struct PostgresClosure *pg = cls;
    2347          43 :   struct GNUNET_PQ_QueryParam params[] = {
    2348          43 :     TALER_PQ_query_param_amount (denom_balance),
    2349          43 :     TALER_PQ_query_param_amount (deposit_fee_balance),
    2350          43 :     TALER_PQ_query_param_amount (melt_fee_balance),
    2351          43 :     TALER_PQ_query_param_amount (refund_fee_balance),
    2352          43 :     TALER_PQ_query_param_amount (risk),
    2353          43 :     TALER_PQ_query_param_amount (loss),
    2354          43 :     TALER_PQ_query_param_amount (irregular_recoup),
    2355          43 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2356             :     GNUNET_PQ_query_param_end
    2357             :   };
    2358             : 
    2359          43 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2360             :                                              "auditor_balance_summary_update",
    2361             :                                              params);
    2362             : }
    2363             : 
    2364             : 
    2365             : /**
    2366             :  * Get information about an exchange's denomination balances.
    2367             :  *
    2368             :  * @param cls the @e cls of this struct with the plugin-specific state
    2369             :  * @param master_pub master key of the exchange
    2370             :  * @param[out] denom_balance value of coins outstanding with this denomination key
    2371             :  * @param[out] deposit_fee_balance total deposit fees collected for this DK
    2372             :  * @param[out] melt_fee_balance total melt fees collected for this DK
    2373             :  * @param[out] refund_fee_balance total refund fees collected for this DK
    2374             :  * @param[out] risk maximum risk exposure of the exchange
    2375             :  * @param[out] loss losses from recoup (on revoked denominations)
    2376             :  * @param[out] irregular_recoup recoups on NOT revoked denominations
    2377             :  * @return transaction status code
    2378             :  */
    2379             : static enum GNUNET_DB_QueryStatus
    2380          84 : postgres_get_balance_summary (void *cls,
    2381             :                               const struct TALER_MasterPublicKeyP *master_pub,
    2382             :                               struct TALER_Amount *denom_balance,
    2383             :                               struct TALER_Amount *deposit_fee_balance,
    2384             :                               struct TALER_Amount *melt_fee_balance,
    2385             :                               struct TALER_Amount *refund_fee_balance,
    2386             :                               struct TALER_Amount *risk,
    2387             :                               struct TALER_Amount *loss,
    2388             :                               struct TALER_Amount *irregular_recoup)
    2389             : {
    2390          84 :   struct PostgresClosure *pg = cls;
    2391          84 :   struct GNUNET_PQ_QueryParam params[] = {
    2392          84 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2393             :     GNUNET_PQ_query_param_end
    2394             :   };
    2395          84 :   struct GNUNET_PQ_ResultSpec rs[] = {
    2396          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("denom_balance", denom_balance),
    2397          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("deposit_fee_balance", deposit_fee_balance),
    2398          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("melt_fee_balance", melt_fee_balance),
    2399          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("refund_fee_balance", refund_fee_balance),
    2400          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("risk", risk),
    2401          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("loss", loss),
    2402          84 :     TALER_PQ_RESULT_SPEC_AMOUNT ("irregular_recoup", irregular_recoup),
    2403             :     GNUNET_PQ_result_spec_end
    2404             :   };
    2405             : 
    2406          84 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    2407             :                                                    "auditor_balance_summary_select",
    2408             :                                                    params,
    2409             :                                                    rs);
    2410             : }
    2411             : 
    2412             : 
    2413             : /**
    2414             :  * Insert information about an exchange's historic
    2415             :  * revenue about a denomination key.
    2416             :  *
    2417             :  * @param cls the @e cls of this struct with the plugin-specific state
    2418             :  * @param master_pub master key of the exchange
    2419             :  * @param denom_pub_hash hash of the denomination key
    2420             :  * @param revenue_timestamp when did this profit get realized
    2421             :  * @param revenue_balance what was the total profit made from
    2422             :  *                        deposit fees, melting fees, refresh fees
    2423             :  *                        and coins that were never returned?
    2424             :  * @param loss_balance total losses suffered by the exchange at the time
    2425             :  * @return transaction status code
    2426             :  */
    2427             : static enum GNUNET_DB_QueryStatus
    2428           2 : postgres_insert_historic_denom_revenue (
    2429             :   void *cls,
    2430             :   const struct TALER_MasterPublicKeyP *master_pub,
    2431             :   const struct GNUNET_HashCode *denom_pub_hash,
    2432             :   struct GNUNET_TIME_Absolute revenue_timestamp,
    2433             :   const struct TALER_Amount *revenue_balance,
    2434             :   const struct TALER_Amount *loss_balance)
    2435             : {
    2436           2 :   struct PostgresClosure *pg = cls;
    2437           2 :   struct GNUNET_PQ_QueryParam params[] = {
    2438           2 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2439           2 :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    2440           2 :     TALER_PQ_query_param_absolute_time (&revenue_timestamp),
    2441           2 :     TALER_PQ_query_param_amount (revenue_balance),
    2442           2 :     TALER_PQ_query_param_amount (loss_balance),
    2443             :     GNUNET_PQ_query_param_end
    2444             :   };
    2445             : 
    2446           2 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2447             :                                              "auditor_historic_denomination_revenue_insert",
    2448             :                                              params);
    2449             : }
    2450             : 
    2451             : 
    2452             : /**
    2453             :  * Closure for #historic_denom_revenue_cb().
    2454             :  */
    2455             : struct HistoricDenomRevenueContext
    2456             : {
    2457             :   /**
    2458             :    * Function to call for each result.
    2459             :    */
    2460             :   TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb;
    2461             : 
    2462             :   /**
    2463             :    * Closure for @e cb.
    2464             :    */
    2465             :   void *cb_cls;
    2466             : 
    2467             :   /**
    2468             :    * Plugin context.
    2469             :    */
    2470             :   struct PostgresClosure *pg;
    2471             : 
    2472             :   /**
    2473             :    * Number of results processed.
    2474             :    */
    2475             :   enum GNUNET_DB_QueryStatus qs;
    2476             : };
    2477             : 
    2478             : 
    2479             : /**
    2480             :  * Helper function for #postgres_select_historic_denom_revenue().
    2481             :  * To be called with the results of a SELECT statement
    2482             :  * that has returned @a num_results results.
    2483             :  *
    2484             :  * @param cls closure of type `struct HistoricRevenueContext *`
    2485             :  * @param result the postgres result
    2486             :  * @param num_results the number of results in @a result
    2487             :  */
    2488             : static void
    2489           1 : historic_denom_revenue_cb (void *cls,
    2490             :                            PGresult *result,
    2491             :                            unsigned int num_results)
    2492             : {
    2493           1 :   struct HistoricDenomRevenueContext *hrc = cls;
    2494           1 :   struct PostgresClosure *pg = hrc->pg;
    2495             : 
    2496           3 :   for (unsigned int i = 0; i < num_results; i++)
    2497             :   {
    2498             :     struct GNUNET_HashCode denom_pub_hash;
    2499             :     struct GNUNET_TIME_Absolute revenue_timestamp;
    2500             :     struct TALER_Amount revenue_balance;
    2501             :     struct TALER_Amount loss;
    2502           2 :     struct GNUNET_PQ_ResultSpec rs[] = {
    2503           2 :       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &denom_pub_hash),
    2504           2 :       TALER_PQ_result_spec_absolute_time ("revenue_timestamp",
    2505             :                                           &revenue_timestamp),
    2506           2 :       TALER_PQ_RESULT_SPEC_AMOUNT ("revenue_balance", &revenue_balance),
    2507           2 :       TALER_PQ_RESULT_SPEC_AMOUNT ("loss_balance", &loss),
    2508             :       GNUNET_PQ_result_spec_end
    2509             :     };
    2510             : 
    2511           2 :     if (GNUNET_OK !=
    2512           2 :         GNUNET_PQ_extract_result (result,
    2513             :                                   rs,
    2514             :                                   i))
    2515             :     {
    2516           0 :       GNUNET_break (0);
    2517           0 :       hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    2518           0 :       return;
    2519             :     }
    2520             : 
    2521           2 :     hrc->qs = i + 1;
    2522           2 :     if (GNUNET_OK !=
    2523           2 :         hrc->cb (hrc->cb_cls,
    2524             :                  &denom_pub_hash,
    2525             :                  revenue_timestamp,
    2526             :                  &revenue_balance,
    2527             :                  &loss))
    2528           0 :       break;
    2529             :   }
    2530             : }
    2531             : 
    2532             : 
    2533             : /**
    2534             :  * Obtain all of the historic denomination key revenue
    2535             :  * of the given @a master_pub.
    2536             :  *
    2537             :  * @param cls the @e cls of this struct with the plugin-specific state
    2538             :  * @param master_pub master key of the exchange
    2539             :  * @param cb function to call with the results
    2540             :  * @param cb_cls closure for @a cb
    2541             :  * @return transaction status code
    2542             :  */
    2543             : static enum GNUNET_DB_QueryStatus
    2544           1 : postgres_select_historic_denom_revenue (
    2545             :   void *cls,
    2546             :   const struct TALER_MasterPublicKeyP *master_pub,
    2547             :   TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb,
    2548             :   void *cb_cls)
    2549             : {
    2550           1 :   struct PostgresClosure *pg = cls;
    2551           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2552           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2553             :     GNUNET_PQ_query_param_end
    2554             :   };
    2555           1 :   struct HistoricDenomRevenueContext hrc = {
    2556             :     .cb = cb,
    2557             :     .cb_cls = cb_cls,
    2558             :     .pg = pg
    2559             :   };
    2560             :   enum GNUNET_DB_QueryStatus qs;
    2561             : 
    2562           1 :   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    2563             :                                              "auditor_historic_denomination_revenue_select",
    2564             :                                              params,
    2565             :                                              &historic_denom_revenue_cb,
    2566             :                                              &hrc);
    2567           1 :   if (qs <= 0)
    2568           0 :     return qs;
    2569           1 :   return hrc.qs;
    2570             : }
    2571             : 
    2572             : 
    2573             : /**
    2574             :  * Insert information about an exchange's historic revenue from reserves.
    2575             :  *
    2576             :  * @param cls the @e cls of this struct with the plugin-specific state
    2577             :  * @param master_pub master key of the exchange
    2578             :  * @param start_time beginning of aggregated time interval
    2579             :  * @param end_time end of aggregated time interval
    2580             :  * @param reserve_profits total profits made
    2581             :  * @return transaction status code
    2582             :  */
    2583             : static enum GNUNET_DB_QueryStatus
    2584           2 : postgres_insert_historic_reserve_revenue (
    2585             :   void *cls,
    2586             :   const struct TALER_MasterPublicKeyP *master_pub,
    2587             :   struct GNUNET_TIME_Absolute start_time,
    2588             :   struct GNUNET_TIME_Absolute end_time,
    2589             :   const struct TALER_Amount *reserve_profits)
    2590             : {
    2591           2 :   struct PostgresClosure *pg = cls;
    2592           2 :   struct GNUNET_PQ_QueryParam params[] = {
    2593           2 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2594           2 :     TALER_PQ_query_param_absolute_time (&start_time),
    2595           2 :     TALER_PQ_query_param_absolute_time (&end_time),
    2596           2 :     TALER_PQ_query_param_amount (reserve_profits),
    2597             :     GNUNET_PQ_query_param_end
    2598             :   };
    2599             : 
    2600           2 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2601             :                                              "auditor_historic_reserve_summary_insert",
    2602             :                                              params);
    2603             : }
    2604             : 
    2605             : 
    2606             : /**
    2607             :  * Closure for #historic_reserve_revenue_cb().
    2608             :  */
    2609             : struct HistoricReserveRevenueContext
    2610             : {
    2611             :   /**
    2612             :    * Function to call for each result.
    2613             :    */
    2614             :   TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb;
    2615             : 
    2616             :   /**
    2617             :    * Closure for @e cb.
    2618             :    */
    2619             :   void *cb_cls;
    2620             : 
    2621             :   /**
    2622             :    * Plugin context.
    2623             :    */
    2624             :   struct PostgresClosure *pg;
    2625             : 
    2626             :   /**
    2627             :    * Number of results processed.
    2628             :    */
    2629             :   enum GNUNET_DB_QueryStatus qs;
    2630             : };
    2631             : 
    2632             : 
    2633             : /**
    2634             :  * Helper function for #postgres_select_historic_reserve_revenue().
    2635             :  * To be called with the results of a SELECT statement
    2636             :  * that has returned @a num_results results.
    2637             :  *
    2638             :  * @param cls closure of type `struct HistoricRevenueContext *`
    2639             :  * @param result the postgres result
    2640             :  * @param num_results the number of results in @a result
    2641             :  */
    2642             : static void
    2643           1 : historic_reserve_revenue_cb (void *cls,
    2644             :                              PGresult *result,
    2645             :                              unsigned int num_results)
    2646             : {
    2647           1 :   struct HistoricReserveRevenueContext *hrc = cls;
    2648           1 :   struct PostgresClosure *pg = hrc->pg;
    2649             : 
    2650           3 :   for (unsigned int i = 0; i < num_results; i++)
    2651             :   {
    2652             :     struct GNUNET_TIME_Absolute start_date;
    2653             :     struct GNUNET_TIME_Absolute end_date;
    2654             :     struct TALER_Amount reserve_profits;
    2655           2 :     struct GNUNET_PQ_ResultSpec rs[] = {
    2656           2 :       TALER_PQ_result_spec_absolute_time ("start_date", &start_date),
    2657           2 :       TALER_PQ_result_spec_absolute_time ("end_date", &end_date),
    2658           2 :       TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_profits", &reserve_profits),
    2659             :       GNUNET_PQ_result_spec_end
    2660             :     };
    2661             : 
    2662           2 :     if (GNUNET_OK !=
    2663           2 :         GNUNET_PQ_extract_result (result,
    2664             :                                   rs,
    2665             :                                   i))
    2666             :     {
    2667           0 :       GNUNET_break (0);
    2668           0 :       hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    2669           0 :       return;
    2670             :     }
    2671           2 :     hrc->qs = i + 1;
    2672           2 :     if (GNUNET_OK !=
    2673           2 :         hrc->cb (hrc->cb_cls,
    2674             :                  start_date,
    2675             :                  end_date,
    2676             :                  &reserve_profits))
    2677           0 :       break;
    2678             :   }
    2679             : }
    2680             : 
    2681             : 
    2682             : /**
    2683             :  * Return information about an exchange's historic revenue from reserves.
    2684             :  *
    2685             :  * @param cls the @e cls of this struct with the plugin-specific state
    2686             :  * @param master_pub master key of the exchange
    2687             :  * @param cb function to call with results
    2688             :  * @param cb_cls closure for @a cb
    2689             :  * @return transaction status code
    2690             :  */
    2691             : static enum GNUNET_DB_QueryStatus
    2692           1 : postgres_select_historic_reserve_revenue (
    2693             :   void *cls,
    2694             :   const struct TALER_MasterPublicKeyP *master_pub,
    2695             :   TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb,
    2696             :   void *cb_cls)
    2697             : {
    2698           1 :   struct PostgresClosure *pg = cls;
    2699           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2700           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2701             :     GNUNET_PQ_query_param_end
    2702             :   };
    2703             :   enum GNUNET_DB_QueryStatus qs;
    2704           1 :   struct HistoricReserveRevenueContext hrc = {
    2705             :     .cb = cb,
    2706             :     .cb_cls = cb_cls,
    2707             :     .pg = pg
    2708             :   };
    2709             : 
    2710           1 :   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    2711             :                                              "auditor_historic_reserve_summary_select",
    2712             :                                              params,
    2713             :                                              &historic_reserve_revenue_cb,
    2714             :                                              &hrc);
    2715           1 :   if (0 >= qs)
    2716           0 :     return qs;
    2717           1 :   return hrc.qs;
    2718             : }
    2719             : 
    2720             : 
    2721             : /**
    2722             :  * Insert information about the predicted exchange's bank
    2723             :  * account balance.
    2724             :  *
    2725             :  * @param cls the @e cls of this struct with the plugin-specific state
    2726             :  * @param master_pub master key of the exchange
    2727             :  * @param balance what the bank account balance of the exchange should show
    2728             :  * @return transaction status code
    2729             :  */
    2730             : static enum GNUNET_DB_QueryStatus
    2731           1 : postgres_insert_predicted_result (
    2732             :   void *cls,
    2733             :   const struct TALER_MasterPublicKeyP *master_pub,
    2734             :   const struct TALER_Amount *balance)
    2735             : {
    2736           1 :   struct PostgresClosure *pg = cls;
    2737           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2738           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2739           1 :     TALER_PQ_query_param_amount (balance),
    2740             :     GNUNET_PQ_query_param_end
    2741             :   };
    2742             : 
    2743           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2744             :                                              "auditor_predicted_result_insert",
    2745             :                                              params);
    2746             : }
    2747             : 
    2748             : 
    2749             : /**
    2750             :  * Update information about an exchange's predicted balance.  There
    2751             :  * must be an existing record for the exchange.
    2752             :  *
    2753             :  * @param cls the @e cls of this struct with the plugin-specific state
    2754             :  * @param master_pub master key of the exchange
    2755             :  * @param balance what the bank account balance of the exchange should show
    2756             :  * @return transaction status code
    2757             :  */
    2758             : static enum GNUNET_DB_QueryStatus
    2759           1 : postgres_update_predicted_result (
    2760             :   void *cls,
    2761             :   const struct TALER_MasterPublicKeyP *master_pub,
    2762             :   const struct TALER_Amount *balance)
    2763             : {
    2764           1 :   struct PostgresClosure *pg = cls;
    2765           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2766           1 :     TALER_PQ_query_param_amount (balance),
    2767           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2768             :     GNUNET_PQ_query_param_end
    2769             :   };
    2770             : 
    2771           1 :   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
    2772             :                                              "auditor_predicted_result_update",
    2773             :                                              params);
    2774             : }
    2775             : 
    2776             : 
    2777             : /**
    2778             :  * Get an exchange's predicted balance.
    2779             :  *
    2780             :  * @param cls the @e cls of this struct with the plugin-specific state
    2781             :  * @param master_pub master key of the exchange
    2782             :  * @param[out] balance expected bank account balance of the exchange
    2783             :  * @return transaction status code
    2784             :  */
    2785             : static enum GNUNET_DB_QueryStatus
    2786           1 : postgres_get_predicted_balance (void *cls,
    2787             :                                 const struct TALER_MasterPublicKeyP *master_pub,
    2788             :                                 struct TALER_Amount *balance)
    2789             : {
    2790           1 :   struct PostgresClosure *pg = cls;
    2791           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2792           1 :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2793             :     GNUNET_PQ_query_param_end
    2794             :   };
    2795           1 :   struct GNUNET_PQ_ResultSpec rs[] = {
    2796           1 :     TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
    2797             :                                  balance),
    2798             :     GNUNET_PQ_result_spec_end
    2799             :   };
    2800             : 
    2801           1 :   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    2802             :                                                    "auditor_predicted_result_select",
    2803             :                                                    params,
    2804             :                                                    rs);
    2805             : }
    2806             : 
    2807             : 
    2808             : /**
    2809             :  * Initialize Postgres database subsystem.
    2810             :  *
    2811             :  * @param cls a configuration instance
    2812             :  * @return NULL on error, otherwise a `struct TALER_AUDITORDB_Plugin`
    2813             :  */
    2814             : void *
    2815         482 : libtaler_plugin_auditordb_postgres_init (void *cls)
    2816             : {
    2817         482 :   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    2818             :   struct PostgresClosure *pg;
    2819             :   struct TALER_AUDITORDB_Plugin *plugin;
    2820             : 
    2821         482 :   pg = GNUNET_new (struct PostgresClosure);
    2822         482 :   pg->cfg = cfg;
    2823         482 :   if (GNUNET_OK !=
    2824         482 :       TALER_config_get_currency (cfg,
    2825             :                                  &pg->currency))
    2826             :   {
    2827           0 :     GNUNET_free (pg);
    2828           0 :     return NULL;
    2829             :   }
    2830         482 :   plugin = GNUNET_new (struct TALER_AUDITORDB_Plugin);
    2831         482 :   plugin->cls = pg;
    2832         482 :   plugin->preflight = &postgres_preflight;
    2833         482 :   plugin->drop_tables = &postgres_drop_tables;
    2834         482 :   plugin->create_tables = &postgres_create_tables;
    2835         482 :   plugin->start = &postgres_start;
    2836         482 :   plugin->commit = &postgres_commit;
    2837         482 :   plugin->rollback = &postgres_rollback;
    2838         482 :   plugin->gc = &postgres_gc;
    2839             : 
    2840         482 :   plugin->insert_exchange = &postgres_insert_exchange;
    2841         482 :   plugin->delete_exchange = &postgres_delete_exchange;
    2842         482 :   plugin->list_exchanges = &postgres_list_exchanges;
    2843         482 :   plugin->insert_exchange_signkey = &postgres_insert_exchange_signkey;
    2844         482 :   plugin->insert_deposit_confirmation = &postgres_insert_deposit_confirmation;
    2845         482 :   plugin->get_deposit_confirmations = &postgres_get_deposit_confirmations;
    2846             : 
    2847         482 :   plugin->get_auditor_progress_reserve = &postgres_get_auditor_progress_reserve;
    2848         482 :   plugin->update_auditor_progress_reserve =
    2849             :     &postgres_update_auditor_progress_reserve;
    2850         482 :   plugin->insert_auditor_progress_reserve =
    2851             :     &postgres_insert_auditor_progress_reserve;
    2852         482 :   plugin->get_auditor_progress_aggregation =
    2853             :     &postgres_get_auditor_progress_aggregation;
    2854         482 :   plugin->update_auditor_progress_aggregation =
    2855             :     &postgres_update_auditor_progress_aggregation;
    2856         482 :   plugin->insert_auditor_progress_aggregation =
    2857             :     &postgres_insert_auditor_progress_aggregation;
    2858         482 :   plugin->get_auditor_progress_deposit_confirmation =
    2859             :     &postgres_get_auditor_progress_deposit_confirmation;
    2860         482 :   plugin->update_auditor_progress_deposit_confirmation =
    2861             :     &postgres_update_auditor_progress_deposit_confirmation;
    2862         482 :   plugin->insert_auditor_progress_deposit_confirmation =
    2863             :     &postgres_insert_auditor_progress_deposit_confirmation;
    2864         482 :   plugin->get_auditor_progress_coin = &postgres_get_auditor_progress_coin;
    2865         482 :   plugin->update_auditor_progress_coin = &postgres_update_auditor_progress_coin;
    2866         482 :   plugin->insert_auditor_progress_coin = &postgres_insert_auditor_progress_coin;
    2867             : 
    2868         482 :   plugin->get_wire_auditor_account_progress =
    2869             :     &postgres_get_wire_auditor_account_progress;
    2870         482 :   plugin->update_wire_auditor_account_progress =
    2871             :     &postgres_update_wire_auditor_account_progress;
    2872         482 :   plugin->insert_wire_auditor_account_progress =
    2873             :     &postgres_insert_wire_auditor_account_progress;
    2874         482 :   plugin->get_wire_auditor_progress = &postgres_get_wire_auditor_progress;
    2875         482 :   plugin->update_wire_auditor_progress = &postgres_update_wire_auditor_progress;
    2876         482 :   plugin->insert_wire_auditor_progress = &postgres_insert_wire_auditor_progress;
    2877             : 
    2878         482 :   plugin->del_reserve_info = &postgres_del_reserve_info;
    2879         482 :   plugin->get_reserve_info = &postgres_get_reserve_info;
    2880         482 :   plugin->update_reserve_info = &postgres_update_reserve_info;
    2881         482 :   plugin->insert_reserve_info = &postgres_insert_reserve_info;
    2882             : 
    2883         482 :   plugin->get_reserve_summary = &postgres_get_reserve_summary;
    2884         482 :   plugin->update_reserve_summary = &postgres_update_reserve_summary;
    2885         482 :   plugin->insert_reserve_summary = &postgres_insert_reserve_summary;
    2886             : 
    2887         482 :   plugin->get_wire_fee_summary = &postgres_get_wire_fee_summary;
    2888         482 :   plugin->update_wire_fee_summary = &postgres_update_wire_fee_summary;
    2889         482 :   plugin->insert_wire_fee_summary = &postgres_insert_wire_fee_summary;
    2890             : 
    2891         482 :   plugin->get_denomination_balance = &postgres_get_denomination_balance;
    2892         482 :   plugin->update_denomination_balance = &postgres_update_denomination_balance;
    2893         482 :   plugin->insert_denomination_balance = &postgres_insert_denomination_balance;
    2894             : 
    2895         482 :   plugin->get_balance_summary = &postgres_get_balance_summary;
    2896         482 :   plugin->update_balance_summary = &postgres_update_balance_summary;
    2897         482 :   plugin->insert_balance_summary = &postgres_insert_balance_summary;
    2898             : 
    2899         482 :   plugin->select_historic_denom_revenue =
    2900             :     &postgres_select_historic_denom_revenue;
    2901         482 :   plugin->insert_historic_denom_revenue =
    2902             :     &postgres_insert_historic_denom_revenue;
    2903             : 
    2904         482 :   plugin->select_historic_reserve_revenue =
    2905             :     &postgres_select_historic_reserve_revenue;
    2906         482 :   plugin->insert_historic_reserve_revenue =
    2907             :     &postgres_insert_historic_reserve_revenue;
    2908             : 
    2909         482 :   plugin->get_predicted_balance = &postgres_get_predicted_balance;
    2910         482 :   plugin->update_predicted_result = &postgres_update_predicted_result;
    2911         482 :   plugin->insert_predicted_result = &postgres_insert_predicted_result;
    2912             : 
    2913         482 :   return plugin;
    2914             : }
    2915             : 
    2916             : 
    2917             : /**
    2918             :  * Shutdown Postgres database subsystem.
    2919             :  *
    2920             :  * @param cls a `struct TALER_AUDITORDB_Plugin`
    2921             :  * @return NULL (always)
    2922             :  */
    2923             : void *
    2924         482 : libtaler_plugin_auditordb_postgres_done (void *cls)
    2925             : {
    2926         482 :   struct TALER_AUDITORDB_Plugin *plugin = cls;
    2927         482 :   struct PostgresClosure *pg = plugin->cls;
    2928             : 
    2929         482 :   if (NULL != pg->conn)
    2930         428 :     GNUNET_PQ_disconnect (pg->conn);
    2931         482 :   GNUNET_free (pg->currency);
    2932         482 :   GNUNET_free (pg);
    2933         482 :   GNUNET_free (plugin);
    2934         482 :   return NULL;
    2935             : }
    2936             : 
    2937             : 
    2938             : /* end of plugin_auditordb_postgres.c */

Generated by: LCOV version 1.14