exchange

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

get_deposit_confirmations.c (7376B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2022-2023 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify it under the
      6    terms of the GNU General Public License as published by the Free Software
      7    Foundation; either version 3, or (at your option) any later version.
      8 
      9    TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13    You should have received a copy of the GNU General Public License along with
     14    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 
     17 /**
     18  * @file get_deposit_confirmations.c
     19  * @brief Low-level (statement-level) Postgres database access for the exchange
     20  * @author Christian Grothoff
     21  */
     22 #include "taler/taler_pq_lib.h"
     23 #include "auditor-database/get_deposit_confirmations.h"
     24 #include "pg_helper.h"
     25 
     26 
     27 /**
     28  * Closure for #deposit_confirmation_cb().
     29  */
     30 struct DepositConfirmationContext
     31 {
     32 
     33   /**
     34    * Function to call for each deposit confirmation.
     35    */
     36   TALER_AUDITORDB_DepositConfirmationCallback cb;
     37 
     38   /**
     39    * Closure for @e cb
     40    */
     41   void *cb_cls;
     42 
     43   /**
     44    * Plugin context.
     45    */
     46   struct TALER_AUDITORDB_PostgresContext *pg;
     47 
     48   /**
     49    * Query status to return.
     50    */
     51   enum GNUNET_DB_QueryStatus qs;
     52 };
     53 
     54 
     55 /**
     56  * Helper function for #TALER_AUDITORDB_get_deposit_confirmations().
     57  * To be called with the results of a SELECT statement
     58  * that has returned @a num_results results.
     59  *
     60  * @param cls closure of type `struct DepositConfirmationContext *`
     61  * @param result the postgres result
     62  * @param num_results the number of results in @a result
     63  */
     64 static void
     65 deposit_confirmation_cb (void *cls,
     66                          PGresult *result,
     67                          unsigned int num_results)
     68 {
     69   struct DepositConfirmationContext *dcc = cls;
     70   struct TALER_AUDITORDB_PostgresContext *pg = dcc->pg;
     71 
     72   for (unsigned int i = 0; i < num_results; i++)
     73   {
     74     struct TALER_AUDITORDB_DepositConfirmation dc = { 0 };
     75     struct TALER_CoinSpendPublicKeyP *coin_pubs = NULL;
     76     struct TALER_CoinSpendSignatureP *coin_sigs = NULL;
     77     size_t num_pubs = 0;
     78     size_t num_sigs = 0;
     79     struct GNUNET_PQ_ResultSpec rs[] = {
     80       GNUNET_PQ_result_spec_uint64 ("row_id",
     81                                     &dc.row_id),
     82       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
     83                                             &dc.h_contract_terms),
     84       GNUNET_PQ_result_spec_auto_from_type ("h_policy",
     85                                             &dc.h_policy),
     86       GNUNET_PQ_result_spec_auto_from_type ("h_wire",
     87                                             &dc.h_wire),
     88       GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
     89                                        &dc.exchange_timestamp),
     90       GNUNET_PQ_result_spec_timestamp ("refund_deadline",
     91                                        &dc.refund_deadline),
     92       GNUNET_PQ_result_spec_timestamp ("wire_deadline",
     93                                        &dc.wire_deadline),
     94       TALER_PQ_RESULT_SPEC_AMOUNT ("total_without_fee",
     95                                    &dc.total_without_fee),
     96       GNUNET_PQ_result_spec_auto_array_from_type (pg->conn,
     97                                                   "coin_pubs",
     98                                                   &num_pubs,
     99                                                   coin_pubs),
    100       GNUNET_PQ_result_spec_auto_array_from_type (pg->conn,
    101                                                   "coin_sigs",
    102                                                   &num_sigs,
    103                                                   coin_sigs),
    104       GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
    105                                             &dc.merchant),
    106       GNUNET_PQ_result_spec_auto_from_type ("exchange_sig",
    107                                             &dc.exchange_sig),
    108       GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
    109                                             &dc.exchange_pub),
    110       GNUNET_PQ_result_spec_auto_from_type ("master_sig",
    111                                             &dc.master_sig),
    112       GNUNET_PQ_result_spec_bool ("suppressed",
    113                                   &dc.suppressed),
    114       GNUNET_PQ_result_spec_end
    115     };
    116     enum GNUNET_GenericReturnValue rval;
    117 
    118     if (GNUNET_OK !=
    119         GNUNET_PQ_extract_result (result,
    120                                   rs,
    121                                   i))
    122     {
    123       GNUNET_break (0);
    124       dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    125       return;
    126     }
    127     if (num_sigs != num_pubs)
    128     {
    129       GNUNET_break (0);
    130       dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    131       GNUNET_PQ_cleanup_result (rs);
    132       return;
    133     }
    134     dcc->qs = i + 1;
    135     dc.coin_pubs = coin_pubs;
    136     dc.coin_sigs = coin_sigs;
    137     dc.num_coins = num_sigs;
    138     rval = dcc->cb (dcc->cb_cls,
    139                     &dc);
    140     GNUNET_PQ_cleanup_result (rs);
    141     if (GNUNET_OK != rval)
    142       break;
    143   }
    144 }
    145 
    146 
    147 enum GNUNET_DB_QueryStatus
    148 TALER_AUDITORDB_get_deposit_confirmations (
    149   struct TALER_AUDITORDB_PostgresContext *pg,
    150   int64_t limit,
    151   uint64_t offset,
    152   bool return_suppressed,
    153   TALER_AUDITORDB_DepositConfirmationCallback cb,
    154   void *cb_cls)
    155 {
    156   uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
    157   struct GNUNET_PQ_QueryParam params[] = {
    158     GNUNET_PQ_query_param_uint64 (&offset),
    159     GNUNET_PQ_query_param_bool (return_suppressed),
    160     GNUNET_PQ_query_param_uint64 (&plimit),
    161     GNUNET_PQ_query_param_end
    162   };
    163   struct DepositConfirmationContext dcc = {
    164     .cb = cb,
    165     .cb_cls = cb_cls,
    166     .pg = pg
    167   };
    168   enum GNUNET_DB_QueryStatus qs;
    169 
    170   PREPARE (pg,
    171            "auditor_deposit_confirmation_select_desc",
    172            "SELECT"
    173            " row_id"
    174            ",h_contract_terms"
    175            ",h_policy"
    176            ",h_wire"
    177            ",exchange_timestamp"
    178            ",wire_deadline"
    179            ",refund_deadline"
    180            ",total_without_fee"
    181            ",coin_pubs"
    182            ",coin_sigs"
    183            ",merchant_pub"
    184            ",exchange_sig"
    185            ",exchange_pub"
    186            ",master_sig"
    187            ",suppressed"
    188            " FROM auditor_deposit_confirmations"
    189            " WHERE (row_id < $1)"
    190            " AND ($2 OR NOT suppressed)"
    191            " ORDER BY row_id DESC"
    192            " LIMIT $3"
    193            );
    194   PREPARE (pg,
    195            "auditor_deposit_confirmation_select_asc",
    196            "SELECT"
    197            " row_id"
    198            ",h_contract_terms"
    199            ",h_policy"
    200            ",h_wire"
    201            ",exchange_timestamp"
    202            ",wire_deadline"
    203            ",refund_deadline"
    204            ",total_without_fee"
    205            ",coin_pubs"
    206            ",coin_sigs"
    207            ",merchant_pub"
    208            ",exchange_sig"
    209            ",exchange_pub"
    210            ",master_sig"
    211            ",suppressed"
    212            " FROM auditor_deposit_confirmations"
    213            " WHERE (row_id > $1)"
    214            " AND ($2 OR NOT suppressed)"
    215            " ORDER BY row_id ASC"
    216            " LIMIT $3"
    217            );
    218   qs = GNUNET_PQ_eval_prepared_multi_select (
    219     pg->conn,
    220     (limit > 0)
    221     ? "auditor_deposit_confirmation_select_asc"
    222     : "auditor_deposit_confirmation_select_desc",
    223     params,
    224     &deposit_confirmation_cb,
    225     &dcc);
    226   if (qs > 0)
    227     return dcc.qs;
    228   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
    229   return qs;
    230 }