exchange

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

get_withdraw.c (6410B)


      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/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 "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_uint64 ("withdraw_id",
     52                                   &wd->withdraw_id),
     53     GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
     54                                           &wd->planchets_h),
     55     GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
     56                                           &wd->reserve_sig),
     57     GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
     58                                           &wd->reserve_pub),
     59     GNUNET_PQ_result_spec_allow_null (
     60       GNUNET_PQ_result_spec_uint16 ("max_age",
     61                                     &wd->max_age),
     62       &no_max_age),
     63     TALER_PQ_result_spec_amount ("amount_with_fee",
     64                                  pg->currency,
     65                                  &wd->amount_with_fee),
     66     GNUNET_PQ_result_spec_allow_null (
     67       GNUNET_PQ_result_spec_uint16 ("noreveal_index",
     68                                     &wd->noreveal_index),
     69       &no_noreveal_index),
     70     GNUNET_PQ_result_spec_allow_null (
     71       GNUNET_PQ_result_spec_auto_from_type ("selected_h",
     72                                             &wd->selected_h),
     73       &no_selected_h),
     74     GNUNET_PQ_result_spec_allow_null (
     75       GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
     76                                             &wd->blinding_seed),
     77       &no_blinding_seed),
     78     GNUNET_PQ_result_spec_allow_null (
     79       TALER_PQ_result_spec_array_cs_r_pub (
     80         pg->conn,
     81         "cs_r_values",
     82         &num_cs_r_values,
     83         &my_cs_r_values),
     84       &no_cs_r_values),
     85     GNUNET_PQ_result_spec_allow_null (
     86       GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
     87                                     &wd->cs_r_choices),
     88       &no_cs_r_choices),
     89     TALER_PQ_result_spec_array_blinded_denom_sig (
     90       pg->conn,
     91       "denom_sigs",
     92       &num_sigs,
     93       &my_denom_sigs),
     94     GNUNET_PQ_result_spec_array_uint64 (
     95       pg->conn,
     96       "denom_serials",
     97       &num_coins,
     98       &my_denom_serials),
     99     GNUNET_PQ_result_spec_end
    100   };
    101 
    102   PREPARE (pg,
    103            "get_withdraw",
    104            "SELECT"
    105            " withdraw_id"
    106            ",planchets_h"
    107            ",blinding_seed"
    108            ",reserve_sig"
    109            ",reserve_pub"
    110            ",max_age"
    111            ",amount_with_fee"
    112            ",noreveal_index"
    113            ",selected_h"
    114            ",blinding_seed"
    115            ",cs_r_values"
    116            ",cs_r_choices"
    117            ",denom_sigs"
    118            ",denom_serials"
    119            " FROM withdraw"
    120            " WHERE planchets_h=$1;");
    121   ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    122                                                   "get_withdraw",
    123                                                   params,
    124                                                   rs);
    125   if (0 > ret)
    126   {
    127     GNUNET_break (0);
    128     GNUNET_PQ_cleanup_result (rs);
    129     return ret;
    130   }
    131   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret)
    132   {
    133     GNUNET_PQ_cleanup_result (rs);
    134     return ret;
    135   }
    136 
    137   if ((no_max_age != no_noreveal_index) ||
    138       (no_max_age != no_selected_h))
    139   {
    140     GNUNET_break (0);
    141     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    142                 "got inconsistent state for max_age, noreveal_index and planchets_h in DB: "
    143                 "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n",
    144                 no_max_age ? "true" : "false",
    145                 no_noreveal_index ? "true" : "false",
    146                 no_selected_h ? "true" : "false");
    147     GNUNET_PQ_cleanup_result (rs);
    148     return GNUNET_DB_STATUS_HARD_ERROR;
    149   }
    150   if (no_blinding_seed != no_cs_r_values)
    151   {
    152     GNUNET_break (0);
    153     GNUNET_PQ_cleanup_result (rs);
    154     return GNUNET_DB_STATUS_HARD_ERROR;
    155   }
    156   if (no_cs_r_choices != no_cs_r_values)
    157   {
    158     GNUNET_break (0);
    159     GNUNET_PQ_cleanup_result (rs);
    160     return GNUNET_DB_STATUS_HARD_ERROR;
    161   }
    162   if (num_coins != num_sigs)
    163   {
    164     GNUNET_break (0);
    165     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    166                 "got inconsistent number of entries in withdraw from DB: "
    167                 "num_coins=%ld, num_sigs=%ld\n",
    168                 num_coins,
    169                 num_sigs);
    170     GNUNET_PQ_cleanup_result (rs);
    171     return GNUNET_DB_STATUS_HARD_ERROR;
    172   }
    173   wd->age_proof_required = ! no_max_age;
    174   if (no_cs_r_values)
    175   {
    176     wd->cs_r_values = NULL;
    177     wd->num_cs_r_values = 0;
    178     wd->cs_r_choices = 0;
    179   }
    180   wd->denom_sigs = my_denom_sigs;
    181   wd->num_coins = num_coins;
    182   wd->denom_serials = my_denom_serials;
    183   wd->cs_r_values = my_cs_r_values;
    184   wd->num_cs_r_values = num_cs_r_values;
    185   /* ensure cleanup_result does not trash data we care about */
    186   my_denom_sigs = NULL;
    187   my_denom_serials = NULL;
    188   my_cs_r_values = NULL;
    189   num_sigs = 0;
    190   num_coins = 0;
    191   num_cs_r_values = 0;
    192   GNUNET_PQ_cleanup_result (rs);
    193   return ret;
    194 }