exchange

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

pg_get_refresh_reveal.c (6634B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2022 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_refresh_reveal.c
     18  * @brief Implementation of the get_refresh_reveal function for Postgres
     19  * @author Christian Grothoff
     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_refresh_reveal.h"
     26 #include "pg_helper.h"
     27 
     28 
     29 /**
     30  * Context where we aggregate data from the database.
     31  * Closure for #add_revealed_coins().
     32  */
     33 struct GetRevealContext
     34 {
     35   /**
     36    * Array of revealed coins we obtained from the DB.
     37    */
     38   struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs;
     39 
     40   /**
     41    * Length of the @a rrcs array.
     42    */
     43   unsigned int rrcs_len;
     44 
     45   /**
     46    * Set to an error code if we ran into trouble.
     47    */
     48   enum GNUNET_DB_QueryStatus qs;
     49 };
     50 
     51 
     52 /**
     53  * Function to be called with the results of a SELECT statement
     54  * that has returned @a num_results results.
     55  *
     56  * @param cls closure of type `struct GetRevealContext`
     57  * @param result the postgres result
     58  * @param num_results the number of results in @a result
     59  */
     60 static void
     61 add_revealed_coins (void *cls,
     62                     PGresult *result,
     63                     unsigned int num_results)
     64 {
     65   struct GetRevealContext *grctx = cls;
     66 
     67   if (0 == num_results)
     68     return;
     69   grctx->rrcs = GNUNET_new_array (num_results,
     70                                   struct TALER_EXCHANGEDB_RefreshRevealedCoin);
     71   grctx->rrcs_len = num_results;
     72   for (unsigned int i = 0; i < num_results; i++)
     73   {
     74     uint32_t off;
     75     struct GNUNET_PQ_ResultSpec rso[] = {
     76       GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
     77                                     &off),
     78       GNUNET_PQ_result_spec_end
     79     };
     80 
     81     if (GNUNET_OK !=
     82         GNUNET_PQ_extract_result (result,
     83                                   rso,
     84                                   i))
     85     {
     86       GNUNET_break (0);
     87       grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
     88       return;
     89     }
     90     if (off >= num_results)
     91     {
     92       GNUNET_break (0);
     93       grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
     94       return;
     95     }
     96     {
     97       struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx->rrcs[off];
     98       struct GNUNET_PQ_ResultSpec rsi[] = {
     99         /* NOTE: freshcoin_index selected and discarded here... */
    100         GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
    101                                               &rrc->h_denom_pub),
    102         GNUNET_PQ_result_spec_auto_from_type ("link_sig",
    103                                               &rrc->orig_coin_link_sig),
    104         GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
    105                                               &rrc->coin_envelope_hash),
    106         TALER_PQ_result_spec_blinded_planchet ("coin_ev",
    107                                                &rrc->blinded_planchet),
    108         TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
    109                                                        &rrc->exchange_vals),
    110         TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
    111                                                 &rrc->coin_sig),
    112         GNUNET_PQ_result_spec_end
    113       };
    114 
    115       if (NULL !=
    116           rrc->blinded_planchet.blinded_message)
    117       {
    118         /* duplicate offset, not allowed */
    119         GNUNET_break (0);
    120         grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
    121         return;
    122       }
    123       if (GNUNET_OK !=
    124           GNUNET_PQ_extract_result (result,
    125                                     rsi,
    126                                     i))
    127       {
    128         GNUNET_break (0);
    129         grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
    130         return;
    131       }
    132     }
    133   }
    134 }
    135 
    136 
    137 enum GNUNET_DB_QueryStatus
    138 TEH_PG_get_refresh_reveal (void *cls,
    139                            const struct TALER_RefreshCommitmentP *rc,
    140                            TALER_EXCHANGEDB_RefreshCallback cb,
    141                            void *cb_cls)
    142 {
    143   struct PostgresClosure *pg = cls;
    144   struct GetRevealContext grctx;
    145   enum GNUNET_DB_QueryStatus qs;
    146   struct GNUNET_PQ_QueryParam params[] = {
    147     GNUNET_PQ_query_param_auto_from_type (rc),
    148     GNUNET_PQ_query_param_end
    149   };
    150 
    151   memset (&grctx,
    152           0,
    153           sizeof (grctx));
    154 
    155   /* Obtain information about the coins created in a refresh
    156      operation, used in #postgres_get_refresh_reveal() */
    157   PREPARE (pg,
    158            "get_refresh_revealed_coins",
    159            "SELECT "
    160            " rrc.freshcoin_index"
    161            ",denom.denom_pub_hash"
    162            ",rrc.h_coin_ev"
    163            ",rrc.link_sig"
    164            ",rrc.coin_ev"
    165            ",rrc.ewv"
    166            ",rrc.ev_sig"
    167            " FROM refresh_commitments"
    168            "    JOIN refresh_revealed_coins rrc"
    169            "      USING (melt_serial_id)"
    170            "    JOIN denominations denom "
    171            "      USING (denominations_serial)"
    172            " WHERE rc=$1;");
    173   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    174                                              "get_refresh_revealed_coins",
    175                                              params,
    176                                              &add_revealed_coins,
    177                                              &grctx);
    178   switch (qs)
    179   {
    180   case GNUNET_DB_STATUS_HARD_ERROR:
    181   case GNUNET_DB_STATUS_SOFT_ERROR:
    182   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
    183     goto cleanup;
    184   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
    185   default: /* can have more than one result */
    186     break;
    187   }
    188   switch (grctx.qs)
    189   {
    190   case GNUNET_DB_STATUS_HARD_ERROR:
    191   case GNUNET_DB_STATUS_SOFT_ERROR:
    192     goto cleanup;
    193   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
    194   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* should be impossible */
    195     break;
    196   }
    197 
    198   /* Pass result back to application */
    199   cb (cb_cls,
    200       grctx.rrcs_len,
    201       grctx.rrcs);
    202 cleanup:
    203   for (unsigned int i = 0; i < grctx.rrcs_len; i++)
    204   {
    205     struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
    206 
    207     TALER_blinded_denom_sig_free (&rrc->coin_sig);
    208     TALER_blinded_planchet_free (&rrc->blinded_planchet);
    209     TALER_denom_ewv_free (&rrc->exchange_vals);
    210   }
    211   GNUNET_free (grctx.rrcs);
    212   return qs;
    213 }