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 (6291B)


      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/taler_pq_lib.h"
     22 #include "taler/exchange-database/get_withdraw.h"
     23 #include "helper.h"
     24 
     25 
     26 enum GNUNET_DB_QueryStatus
     27 TALER_EXCHANGEDB_get_withdraw (
     28   struct TALER_EXCHANGEDB_PostgresContext *pg,
     29   const struct TALER_HashBlindedPlanchetsP *wch,
     30   struct TALER_EXCHANGEDB_Withdraw *wd)
     31 {
     32   enum GNUNET_DB_QueryStatus ret;
     33   struct GNUNET_PQ_QueryParam params[] = {
     34     GNUNET_PQ_query_param_auto_from_type (wch),
     35     GNUNET_PQ_query_param_end
     36   };
     37   struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL;
     38   uint64_t *my_denom_serials = NULL;
     39   struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL;
     40   size_t num_sigs = 0;
     41   size_t num_coins = 0;
     42   size_t num_cs_r_values = 0;
     43   bool no_noreveal_index;
     44   bool no_max_age;
     45   bool no_selected_h;
     46   bool no_blinding_seed;
     47   bool no_cs_r_values;
     48   bool no_cs_r_choices;
     49 
     50   struct GNUNET_PQ_ResultSpec rs[] = {
     51     GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
     52                                           &wd->planchets_h),
     53     GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
     54                                           &wd->reserve_sig),
     55     GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
     56                                           &wd->reserve_pub),
     57     GNUNET_PQ_result_spec_allow_null (
     58       GNUNET_PQ_result_spec_uint16 ("max_age",
     59                                     &wd->max_age),
     60       &no_max_age),
     61     TALER_PQ_result_spec_amount ("amount_with_fee",
     62                                  pg->currency,
     63                                  &wd->amount_with_fee),
     64     GNUNET_PQ_result_spec_allow_null (
     65       GNUNET_PQ_result_spec_uint16 ("noreveal_index",
     66                                     &wd->noreveal_index),
     67       &no_noreveal_index),
     68     GNUNET_PQ_result_spec_allow_null (
     69       GNUNET_PQ_result_spec_auto_from_type ("selected_h",
     70                                             &wd->selected_h),
     71       &no_selected_h),
     72     GNUNET_PQ_result_spec_allow_null (
     73       GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
     74                                             &wd->blinding_seed),
     75       &no_blinding_seed),
     76     GNUNET_PQ_result_spec_allow_null (
     77       TALER_PQ_result_spec_array_cs_r_pub (
     78         pg->conn,
     79         "cs_r_values",
     80         &num_cs_r_values,
     81         &my_cs_r_values),
     82       &no_cs_r_values),
     83     GNUNET_PQ_result_spec_allow_null (
     84       GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
     85                                     &wd->cs_r_choices),
     86       &no_cs_r_choices),
     87     TALER_PQ_result_spec_array_blinded_denom_sig (
     88       pg->conn,
     89       "denom_sigs",
     90       &num_sigs,
     91       &my_denom_sigs),
     92     GNUNET_PQ_result_spec_array_uint64 (
     93       pg->conn,
     94       "denom_serials",
     95       &num_coins,
     96       &my_denom_serials),
     97     GNUNET_PQ_result_spec_end
     98   };
     99 
    100   PREPARE (pg,
    101            "get_withdraw",
    102            "SELECT"
    103            " planchets_h"
    104            ",blinding_seed"
    105            ",reserve_sig"
    106            ",reserve_pub"
    107            ",max_age"
    108            ",amount_with_fee"
    109            ",noreveal_index"
    110            ",selected_h"
    111            ",blinding_seed"
    112            ",cs_r_values"
    113            ",cs_r_choices"
    114            ",denom_sigs"
    115            ",denom_serials"
    116            " FROM withdraw"
    117            " WHERE planchets_h=$1;");
    118   ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    119                                                   "get_withdraw",
    120                                                   params,
    121                                                   rs);
    122   if (0 > ret)
    123   {
    124     GNUNET_break (0);
    125     GNUNET_PQ_cleanup_result (rs);
    126     return ret;
    127   }
    128   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret)
    129   {
    130     GNUNET_PQ_cleanup_result (rs);
    131     return ret;
    132   }
    133 
    134   if ((no_max_age != no_noreveal_index) ||
    135       (no_max_age != no_selected_h))
    136   {
    137     GNUNET_break (0);
    138     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    139                 "got inconsistent state for max_age, noreveal_index and planchets_h in DB: "
    140                 "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n",
    141                 no_max_age ? "true" : "false",
    142                 no_noreveal_index ? "true" : "false",
    143                 no_selected_h ? "true" : "false");
    144     GNUNET_PQ_cleanup_result (rs);
    145     return GNUNET_DB_STATUS_HARD_ERROR;
    146   }
    147   if (no_blinding_seed != no_cs_r_values)
    148   {
    149     GNUNET_break (0);
    150     GNUNET_PQ_cleanup_result (rs);
    151     return GNUNET_DB_STATUS_HARD_ERROR;
    152   }
    153   if (no_cs_r_choices != no_cs_r_values)
    154   {
    155     GNUNET_break (0);
    156     GNUNET_PQ_cleanup_result (rs);
    157     return GNUNET_DB_STATUS_HARD_ERROR;
    158   }
    159   if (num_coins != num_sigs)
    160   {
    161     GNUNET_break (0);
    162     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    163                 "got inconsistent number of entries in withdraw from DB: "
    164                 "num_coins=%ld, num_sigs=%ld\n",
    165                 num_coins,
    166                 num_sigs);
    167     GNUNET_PQ_cleanup_result (rs);
    168     return GNUNET_DB_STATUS_HARD_ERROR;
    169   }
    170   wd->age_proof_required = ! no_max_age;
    171   if (no_cs_r_values)
    172   {
    173     wd->cs_r_values = NULL;
    174     wd->num_cs_r_values = 0;
    175     wd->cs_r_choices = 0;
    176   }
    177   wd->denom_sigs = my_denom_sigs;
    178   wd->num_coins = num_coins;
    179   wd->denom_serials = my_denom_serials;
    180   wd->cs_r_values = my_cs_r_values;
    181   wd->num_cs_r_values = num_cs_r_values;
    182   /* ensure cleanup_result does not trash data we care about */
    183   my_denom_sigs = NULL;
    184   my_denom_serials = NULL;
    185   my_cs_r_values = NULL;
    186   num_sigs = 0;
    187   num_coins = 0;
    188   num_cs_r_values = 0;
    189   GNUNET_PQ_cleanup_result (rs);
    190   return ret;
    191 }