exchange

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

pg_get_withdraw.c (6364B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2023, 2025 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify it under the
      6    terms of the GNU General Public License as published by the Free Software
      7    Foundation; either version 3, or (at your option) any later version.
      8 
      9    TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13    You should have received a copy of the GNU General Public License along with
     14    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 /**
     17  * @file exchangedb/pg_get_withdraw.c
     18  * @brief Implementation of the get_withdraw function for Postgres
     19  * @author Özgür Kesim
     20  */
     21 #include "taler/platform.h"
     22 #include "taler/taler_error_codes.h"
     23 #include "taler/taler_dbevents.h"
     24 #include "taler/taler_pq_lib.h"
     25 #include "pg_get_withdraw.h"
     26 #include "pg_helper.h"
     27 
     28 
     29 enum GNUNET_DB_QueryStatus
     30 TEH_PG_get_withdraw (
     31   void *cls,
     32   const struct TALER_HashBlindedPlanchetsP *wch,
     33   struct TALER_EXCHANGEDB_Withdraw *wd)
     34 {
     35   enum GNUNET_DB_QueryStatus ret;
     36   struct PostgresClosure *pg = cls;
     37   struct GNUNET_PQ_QueryParam params[] = {
     38     GNUNET_PQ_query_param_auto_from_type (wch),
     39     GNUNET_PQ_query_param_end
     40   };
     41   struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL;
     42   uint64_t *my_denom_serials = NULL;
     43   struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL;
     44   size_t num_sigs = 0;
     45   size_t num_coins = 0;
     46   size_t num_cs_r_values = 0;
     47   bool no_noreveal_index;
     48   bool no_max_age;
     49   bool no_selected_h;
     50   bool no_blinding_seed;
     51   bool no_cs_r_values;
     52   bool no_cs_r_choices;
     53 
     54   struct GNUNET_PQ_ResultSpec rs[] = {
     55     GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
     56                                           &wd->planchets_h),
     57     GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
     58                                           &wd->reserve_sig),
     59     GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
     60                                           &wd->reserve_pub),
     61     GNUNET_PQ_result_spec_allow_null (
     62       GNUNET_PQ_result_spec_uint16 ("max_age",
     63                                     &wd->max_age),
     64       &no_max_age),
     65     TALER_PQ_result_spec_amount ("amount_with_fee",
     66                                  pg->currency,
     67                                  &wd->amount_with_fee),
     68     GNUNET_PQ_result_spec_allow_null (
     69       GNUNET_PQ_result_spec_uint16 ("noreveal_index",
     70                                     &wd->noreveal_index),
     71       &no_noreveal_index),
     72     GNUNET_PQ_result_spec_allow_null (
     73       GNUNET_PQ_result_spec_auto_from_type ("selected_h",
     74                                             &wd->selected_h),
     75       &no_selected_h),
     76     GNUNET_PQ_result_spec_allow_null (
     77       GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
     78                                             &wd->blinding_seed),
     79       &no_blinding_seed),
     80     GNUNET_PQ_result_spec_allow_null (
     81       TALER_PQ_result_spec_array_cs_r_pub (
     82         pg->conn,
     83         "cs_r_values",
     84         &num_cs_r_values,
     85         &my_cs_r_values),
     86       &no_cs_r_values),
     87     GNUNET_PQ_result_spec_allow_null (
     88       GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
     89                                     &wd->cs_r_choices),
     90       &no_cs_r_choices),
     91     TALER_PQ_result_spec_array_blinded_denom_sig (
     92       pg->conn,
     93       "denom_sigs",
     94       &num_sigs,
     95       &my_denom_sigs),
     96     GNUNET_PQ_result_spec_array_uint64 (
     97       pg->conn,
     98       "denom_serials",
     99       &num_coins,
    100       &my_denom_serials),
    101     GNUNET_PQ_result_spec_end
    102   };
    103 
    104   PREPARE (pg,
    105            "get_withdraw",
    106            "SELECT"
    107            " planchets_h"
    108            ",blinding_seed"
    109            ",reserve_sig"
    110            ",reserve_pub"
    111            ",max_age"
    112            ",amount_with_fee"
    113            ",noreveal_index"
    114            ",selected_h"
    115            ",blinding_seed"
    116            ",cs_r_values"
    117            ",cs_r_choices"
    118            ",denom_sigs"
    119            ",denom_serials"
    120            " FROM withdraw"
    121            " WHERE planchets_h=$1;");
    122   ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    123                                                   "get_withdraw",
    124                                                   params,
    125                                                   rs);
    126   if (0 > ret)
    127   {
    128     GNUNET_break (0);
    129     GNUNET_PQ_cleanup_result (rs);
    130     return ret;
    131   }
    132   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret)
    133   {
    134     GNUNET_PQ_cleanup_result (rs);
    135     return ret;
    136   }
    137 
    138   if ((no_max_age != no_noreveal_index) ||
    139       (no_max_age != no_selected_h))
    140   {
    141     GNUNET_break (0);
    142     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    143                 "got inconsistent state for max_age, noreveal_index and planchets_h in DB: "
    144                 "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n",
    145                 no_max_age ? "true" : "false",
    146                 no_noreveal_index ? "true" : "false",
    147                 no_selected_h ? "true" : "false");
    148     GNUNET_PQ_cleanup_result (rs);
    149     return GNUNET_DB_STATUS_HARD_ERROR;
    150   }
    151   if (no_blinding_seed != no_cs_r_values)
    152   {
    153     GNUNET_break (0);
    154     GNUNET_PQ_cleanup_result (rs);
    155     return GNUNET_DB_STATUS_HARD_ERROR;
    156   }
    157   if (no_cs_r_choices != no_cs_r_values)
    158   {
    159     GNUNET_break (0);
    160     GNUNET_PQ_cleanup_result (rs);
    161     return GNUNET_DB_STATUS_HARD_ERROR;
    162   }
    163   if (num_coins != num_sigs)
    164   {
    165     GNUNET_break (0);
    166     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    167                 "got inconsistent number of entries in withdraw from DB: "
    168                 "num_coins=%ld, num_sigs=%ld\n",
    169                 num_coins,
    170                 num_sigs);
    171     GNUNET_PQ_cleanup_result (rs);
    172     return GNUNET_DB_STATUS_HARD_ERROR;
    173   }
    174   wd->age_proof_required = ! no_max_age;
    175   if (no_cs_r_values)
    176   {
    177     wd->cs_r_values = NULL;
    178     wd->num_cs_r_values = 0;
    179     wd->cs_r_choices = 0;
    180   }
    181   wd->denom_sigs = my_denom_sigs;
    182   wd->num_coins = num_coins;
    183   wd->denom_serials = my_denom_serials;
    184   wd->cs_r_values = my_cs_r_values;
    185   wd->num_cs_r_values = num_cs_r_values;
    186   /* ensure cleanup_result does not trash data we care about */
    187   my_denom_sigs = NULL;
    188   my_denom_serials = NULL;
    189   my_cs_r_values = NULL;
    190   num_sigs = 0;
    191   num_coins = 0;
    192   num_cs_r_values = 0;
    193   GNUNET_PQ_cleanup_result (rs);
    194   return ret;
    195 }