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


      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_ReservePublicKeyP *reserve_pub,
     30   const struct TALER_HashBlindedPlanchetsP *wch,
     31   struct TALER_EXCHANGEDB_Withdraw *wd)
     32 {
     33   enum GNUNET_DB_QueryStatus ret;
     34   struct GNUNET_PQ_QueryParam params[] = {
     35     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
     36     GNUNET_PQ_query_param_auto_from_type (wch),
     37     GNUNET_PQ_query_param_end
     38   };
     39   struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL;
     40   uint64_t *my_denom_serials = NULL;
     41   struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL;
     42   size_t num_sigs = 0;
     43   size_t num_coins = 0;
     44   size_t num_cs_r_values = 0;
     45   bool no_noreveal_index;
     46   bool no_max_age;
     47   bool no_selected_h;
     48   bool no_blinding_seed;
     49   bool no_cs_r_values;
     50   bool no_cs_r_choices;
     51 
     52   struct GNUNET_PQ_ResultSpec rs[] = {
     53     GNUNET_PQ_result_spec_uint64 ("withdraw_id",
     54                                   &wd->withdraw_id),
     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            " withdraw_id"
    108            ",planchets_h"
    109            ",blinding_seed"
    110            ",reserve_sig"
    111            ",reserve_pub"
    112            ",max_age"
    113            ",amount_with_fee"
    114            ",noreveal_index"
    115            ",selected_h"
    116            ",blinding_seed"
    117            ",cs_r_values"
    118            ",cs_r_choices"
    119            ",denom_sigs"
    120            ",denom_serials"
    121            " FROM withdraw"
    122            " WHERE reserve_pub=$1"
    123            "   AND planchets_h=$2;");
    124   ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    125                                                   "get_withdraw",
    126                                                   params,
    127                                                   rs);
    128   if (0 > ret)
    129   {
    130     GNUNET_break (0);
    131     GNUNET_PQ_cleanup_result (rs);
    132     return ret;
    133   }
    134   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret)
    135   {
    136     GNUNET_PQ_cleanup_result (rs);
    137     return ret;
    138   }
    139 
    140   if ((no_max_age != no_noreveal_index) ||
    141       (no_max_age != no_selected_h))
    142   {
    143     GNUNET_break (0);
    144     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    145                 "got inconsistent state for max_age, noreveal_index and planchets_h in DB: "
    146                 "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n",
    147                 no_max_age ? "true" : "false",
    148                 no_noreveal_index ? "true" : "false",
    149                 no_selected_h ? "true" : "false");
    150     GNUNET_PQ_cleanup_result (rs);
    151     return GNUNET_DB_STATUS_HARD_ERROR;
    152   }
    153   if (no_blinding_seed != 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 (no_cs_r_choices != no_cs_r_values)
    160   {
    161     GNUNET_break (0);
    162     GNUNET_PQ_cleanup_result (rs);
    163     return GNUNET_DB_STATUS_HARD_ERROR;
    164   }
    165   if (num_coins != num_sigs)
    166   {
    167     GNUNET_break (0);
    168     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    169                 "got inconsistent number of entries in withdraw from DB: "
    170                 "num_coins=%ld, num_sigs=%ld\n",
    171                 num_coins,
    172                 num_sigs);
    173     GNUNET_PQ_cleanup_result (rs);
    174     return GNUNET_DB_STATUS_HARD_ERROR;
    175   }
    176   wd->age_proof_required = ! no_max_age;
    177   if (no_cs_r_values)
    178   {
    179     wd->cs_r_values = NULL;
    180     wd->num_cs_r_values = 0;
    181     wd->cs_r_choices = 0;
    182   }
    183   wd->denom_sigs = my_denom_sigs;
    184   wd->num_coins = num_coins;
    185   wd->denom_serials = my_denom_serials;
    186   wd->cs_r_values = my_cs_r_values;
    187   wd->num_cs_r_values = num_cs_r_values;
    188   /* ensure cleanup_result does not trash data we care about */
    189   my_denom_sigs = NULL;
    190   my_denom_serials = NULL;
    191   my_cs_r_values = NULL;
    192   num_sigs = 0;
    193   num_coins = 0;
    194   num_cs_r_values = 0;
    195   GNUNET_PQ_cleanup_result (rs);
    196   return ret;
    197 }