exchange

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

pg_get_deposit_confirmations.c (7417B)


      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 pg_get_deposit_confirmations.c
     19  * @brief Low-level (statement-level) Postgres database access for the exchange
     20  * @author Christian Grothoff
     21  */
     22 #include "taler/platform.h"
     23 #include "taler/taler_error_codes.h"
     24 #include "taler/taler_dbevents.h"
     25 #include "taler/taler_pq_lib.h"
     26 #include "pg_get_deposit_confirmations.h"
     27 #include "pg_helper.h"
     28 
     29 
     30 /**
     31  * Closure for #deposit_confirmation_cb().
     32  */
     33 struct DepositConfirmationContext
     34 {
     35 
     36   /**
     37    * Function to call for each deposit confirmation.
     38    */
     39   TALER_AUDITORDB_DepositConfirmationCallback cb;
     40 
     41   /**
     42    * Closure for @e cb
     43    */
     44   void *cb_cls;
     45 
     46   /**
     47    * Plugin context.
     48    */
     49   struct PostgresClosure *pg;
     50 
     51   /**
     52    * Query status to return.
     53    */
     54   enum GNUNET_DB_QueryStatus qs;
     55 };
     56 
     57 
     58 /**
     59  * Helper function for #TAH_PG_get_deposit_confirmations().
     60  * To be called with the results of a SELECT statement
     61  * that has returned @a num_results results.
     62  *
     63  * @param cls closure of type `struct DepositConfirmationContext *`
     64  * @param result the postgres result
     65  * @param num_results the number of results in @a result
     66  */
     67 static void
     68 deposit_confirmation_cb (void *cls,
     69                          PGresult *result,
     70                          unsigned int num_results)
     71 {
     72   struct DepositConfirmationContext *dcc = cls;
     73   struct PostgresClosure *pg = dcc->pg;
     74 
     75   for (unsigned int i = 0; i < num_results; i++)
     76   {
     77     struct TALER_AUDITORDB_DepositConfirmation dc = { 0 };
     78     struct TALER_CoinSpendPublicKeyP *coin_pubs = NULL;
     79     struct TALER_CoinSpendSignatureP *coin_sigs = NULL;
     80     size_t num_pubs = 0;
     81     size_t num_sigs = 0;
     82     struct GNUNET_PQ_ResultSpec rs[] = {
     83       GNUNET_PQ_result_spec_uint64 ("row_id",
     84                                     &dc.row_id),
     85       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
     86                                             &dc.h_contract_terms),
     87       GNUNET_PQ_result_spec_auto_from_type ("h_policy",
     88                                             &dc.h_policy),
     89       GNUNET_PQ_result_spec_auto_from_type ("h_wire",
     90                                             &dc.h_wire),
     91       GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
     92                                        &dc.exchange_timestamp),
     93       GNUNET_PQ_result_spec_timestamp ("refund_deadline",
     94                                        &dc.refund_deadline),
     95       GNUNET_PQ_result_spec_timestamp ("wire_deadline",
     96                                        &dc.wire_deadline),
     97       TALER_PQ_RESULT_SPEC_AMOUNT ("total_without_fee",
     98                                    &dc.total_without_fee),
     99       GNUNET_PQ_result_spec_auto_array_from_type (pg->conn,
    100                                                   "coin_pubs",
    101                                                   &num_pubs,
    102                                                   coin_pubs),
    103       GNUNET_PQ_result_spec_auto_array_from_type (pg->conn,
    104                                                   "coin_sigs",
    105                                                   &num_sigs,
    106                                                   coin_sigs),
    107       GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
    108                                             &dc.merchant),
    109       GNUNET_PQ_result_spec_auto_from_type ("exchange_sig",
    110                                             &dc.exchange_sig),
    111       GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
    112                                             &dc.exchange_pub),
    113       GNUNET_PQ_result_spec_auto_from_type ("master_sig",
    114                                             &dc.master_sig),
    115       GNUNET_PQ_result_spec_bool ("suppressed",
    116                                   &dc.suppressed),
    117       GNUNET_PQ_result_spec_end
    118     };
    119     enum GNUNET_GenericReturnValue rval;
    120 
    121     if (GNUNET_OK !=
    122         GNUNET_PQ_extract_result (result,
    123                                   rs,
    124                                   i))
    125     {
    126       GNUNET_break (0);
    127       dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    128       return;
    129     }
    130     if (num_sigs != num_pubs)
    131     {
    132       GNUNET_break (0);
    133       dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    134       GNUNET_PQ_cleanup_result (rs);
    135       return;
    136     }
    137     dcc->qs = i + 1;
    138     dc.coin_pubs = coin_pubs;
    139     dc.coin_sigs = coin_sigs;
    140     dc.num_coins = num_sigs;
    141     rval = dcc->cb (dcc->cb_cls,
    142                     &dc);
    143     GNUNET_PQ_cleanup_result (rs);
    144     if (GNUNET_OK != rval)
    145       break;
    146   }
    147 }
    148 
    149 
    150 enum GNUNET_DB_QueryStatus
    151 TAH_PG_get_deposit_confirmations (
    152   void *cls,
    153   int64_t limit,
    154   uint64_t offset,
    155   bool return_suppressed,
    156   TALER_AUDITORDB_DepositConfirmationCallback cb,
    157   void *cb_cls)
    158 {
    159   struct PostgresClosure *pg = cls;
    160   uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
    161   struct GNUNET_PQ_QueryParam params[] = {
    162     GNUNET_PQ_query_param_uint64 (&offset),
    163     GNUNET_PQ_query_param_bool (return_suppressed),
    164     GNUNET_PQ_query_param_uint64 (&plimit),
    165     GNUNET_PQ_query_param_end
    166   };
    167   struct DepositConfirmationContext dcc = {
    168     .cb = cb,
    169     .cb_cls = cb_cls,
    170     .pg = pg
    171   };
    172   enum GNUNET_DB_QueryStatus qs;
    173 
    174   PREPARE (pg,
    175            "auditor_deposit_confirmation_select_desc",
    176            "SELECT"
    177            " row_id"
    178            ",h_contract_terms"
    179            ",h_policy"
    180            ",h_wire"
    181            ",exchange_timestamp"
    182            ",wire_deadline"
    183            ",refund_deadline"
    184            ",total_without_fee"
    185            ",coin_pubs"
    186            ",coin_sigs"
    187            ",merchant_pub"
    188            ",exchange_sig"
    189            ",exchange_pub"
    190            ",master_sig"
    191            ",suppressed"
    192            " FROM auditor_deposit_confirmations"
    193            " WHERE (row_id < $1)"
    194            " AND ($2 OR NOT suppressed)"
    195            " ORDER BY row_id DESC"
    196            " LIMIT $3"
    197            );
    198   PREPARE (pg,
    199            "auditor_deposit_confirmation_select_asc",
    200            "SELECT"
    201            " row_id"
    202            ",h_contract_terms"
    203            ",h_policy"
    204            ",h_wire"
    205            ",exchange_timestamp"
    206            ",wire_deadline"
    207            ",refund_deadline"
    208            ",total_without_fee"
    209            ",coin_pubs"
    210            ",coin_sigs"
    211            ",merchant_pub"
    212            ",exchange_sig"
    213            ",exchange_pub"
    214            ",master_sig"
    215            ",suppressed"
    216            " FROM auditor_deposit_confirmations"
    217            " WHERE (row_id > $1)"
    218            " AND ($2 OR NOT suppressed)"
    219            " ORDER BY row_id ASC"
    220            " LIMIT $3"
    221            );
    222   qs = GNUNET_PQ_eval_prepared_multi_select (
    223     pg->conn,
    224     (limit > 0)
    225     ? "auditor_deposit_confirmation_select_asc"
    226     : "auditor_deposit_confirmation_select_desc",
    227     params,
    228     &deposit_confirmation_cb,
    229     &dcc);
    230   if (qs > 0)
    231     return dcc.qs;
    232   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
    233   return qs;
    234 }