exchange

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

pg_do_refresh.c (5516B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 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_do_refresh.c
     18  * @brief Implementation of the do_refresh 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_exchangedb_plugin.h"
     25 #include "taler/taler_pq_lib.h"
     26 #include "pg_do_refresh.h"
     27 #include "pg_helper.h"
     28 
     29 
     30 enum GNUNET_DB_QueryStatus
     31 TEH_PG_do_refresh (
     32   void *cls,
     33   struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh,
     34   const struct GNUNET_TIME_Timestamp *timestamp,
     35   bool *found,
     36   uint32_t *noreveal_index,
     37   bool *zombie_required,
     38   bool *nonce_reuse,
     39   bool *balance_ok,
     40   struct TALER_Amount *coin_balance)
     41 {
     42   struct PostgresClosure *pg = cls;
     43   struct GNUNET_PQ_QueryParam params[] = {
     44     GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
     45     GNUNET_PQ_query_param_timestamp (timestamp),
     46     GNUNET_PQ_query_param_auto_from_type (&refresh->refresh_seed), /* 3 */
     47     (refresh->is_v27_refresh)
     48         ? GNUNET_PQ_query_param_null ()
     49         : GNUNET_PQ_query_param_array_auto_from_type (refresh->num_coins,
     50                                                       refresh->transfer_pubs,
     51                                                       pg->conn),
     52     GNUNET_PQ_query_param_auto_from_type (&refresh->planchets_h),
     53     TALER_PQ_query_param_amount (pg->conn, /* 6 */
     54                                  &refresh->amount_with_fee),
     55     (refresh->no_blinding_seed)
     56         ? GNUNET_PQ_query_param_null ()
     57         : GNUNET_PQ_query_param_auto_from_type (&refresh->blinding_seed),
     58     (0 < refresh->num_cs_r_values)
     59         ? TALER_PQ_query_param_array_cs_r_pub (refresh->num_cs_r_values,
     60                                                refresh->cs_r_values,
     61                                                pg->conn)
     62         : GNUNET_PQ_query_param_null (),
     63     (0 < refresh->num_cs_r_values)
     64         ? GNUNET_PQ_query_param_uint64 (&refresh->cs_r_choices) /* 9 */
     65         : GNUNET_PQ_query_param_null (),
     66     GNUNET_PQ_query_param_auto_from_type (&refresh->selected_h),
     67     TALER_PQ_query_param_array_blinded_denom_sig (refresh->num_coins,
     68                                                   refresh->denom_sigs,
     69                                                   pg->conn),
     70     GNUNET_PQ_query_param_array_uint64 (refresh->num_coins, /* 12 */
     71                                         refresh->denom_serials,
     72                                         pg->conn),
     73     GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
     74     GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig),
     75     GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index), /* 15 */
     76     GNUNET_PQ_query_param_bool (*zombie_required),
     77     GNUNET_PQ_query_param_end
     78   };
     79   bool coin_found;
     80   bool no_noreveal_index;
     81   bool no_coin_balance;
     82   struct GNUNET_PQ_ResultSpec rs[] = {
     83     GNUNET_PQ_result_spec_bool ("coin_found",
     84                                 &coin_found),
     85     GNUNET_PQ_result_spec_bool ("balance_ok",
     86                                 balance_ok),
     87     GNUNET_PQ_result_spec_bool ("zombie_required",
     88                                 zombie_required),
     89     GNUNET_PQ_result_spec_bool ("nonce_reuse",
     90                                 nonce_reuse),
     91     GNUNET_PQ_result_spec_bool ("found",
     92                                 found),
     93     GNUNET_PQ_result_spec_allow_null (
     94       GNUNET_PQ_result_spec_uint32 ("noreveal_index",
     95                                     noreveal_index),
     96       &no_noreveal_index),
     97     GNUNET_PQ_result_spec_allow_null (
     98       TALER_PQ_RESULT_SPEC_AMOUNT ("coin_balance",
     99                                    coin_balance),
    100       &no_coin_balance),
    101     GNUNET_PQ_result_spec_end
    102   };
    103   enum GNUNET_DB_QueryStatus qs;
    104 
    105   PREPARE (pg,
    106            "call_refresh",
    107            "SELECT "
    108            " out_coin_found AS coin_found"
    109            ",out_balance_ok AS balance_ok"
    110            ",out_zombie_bad AS zombie_required"
    111            ",out_nonce_reuse AS nonce_reuse"
    112            ",out_idempotent AS found"
    113            ",out_noreveal_index AS noreveal_index"
    114            ",out_coin_balance AS coin_balance"
    115            " FROM exchange_do_refresh"
    116            " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);");
    117   qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    118                                                  "call_refresh",
    119                                                  params,
    120                                                  rs);
    121   GNUNET_PQ_cleanup_query_params_closures (params);
    122   if (0 > qs)
    123   {
    124     GNUNET_break (0);
    125     return qs;
    126   }
    127   if (! coin_found)
    128   {
    129     return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
    130   }
    131   if (*found && no_noreveal_index)
    132   {
    133     GNUNET_break (0);
    134     return GNUNET_DB_STATUS_HARD_ERROR;
    135   }
    136   if (! balance_ok && no_coin_balance)
    137   {
    138     GNUNET_break (0);
    139     return GNUNET_DB_STATUS_HARD_ERROR;
    140   }
    141   return qs;
    142 }