pg_get_refresh.c (7638B)
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.c 18 * @brief Implementation of the get_refresh function for Postgres 19 * @author get_refresh 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.h" 26 #include "pg_helper.h" 27 28 29 enum GNUNET_DB_QueryStatus 30 TEH_PG_get_refresh (void *cls, 31 const struct TALER_RefreshCommitmentP *rc, 32 struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh) 33 { 34 struct PostgresClosure *pg = cls; 35 struct GNUNET_PQ_QueryParam params[] = { 36 GNUNET_PQ_query_param_auto_from_type (rc), 37 GNUNET_PQ_query_param_end 38 }; 39 bool no_cs_r_values; 40 bool no_cs_r_choices; 41 bool no_transfer_pubs; 42 size_t num_denom_sigs; 43 size_t num_transfer_pubs; 44 struct TALER_BlindedDenominationSignature *denom_sigs = NULL; 45 struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values = NULL; 46 struct TALER_TransferPublicKeyP *transfer_pubs = NULL; 47 uint64_t *denom_serials = NULL; 48 struct GNUNET_PQ_ResultSpec rs[] = { 49 TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", 50 &refresh->amount_with_fee), 51 GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", 52 &refresh->coin.coin_pub), 53 GNUNET_PQ_result_spec_allow_null ( 54 GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", 55 &refresh->coin.h_age_commitment), 56 &refresh->coin.no_age_commitment), 57 GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", 58 &refresh->coin_sig), 59 GNUNET_PQ_result_spec_auto_from_type ("refresh_seed", 60 &refresh->refresh_seed), 61 GNUNET_PQ_result_spec_uint32 ("noreveal_index", 62 &refresh->noreveal_index), 63 GNUNET_PQ_result_spec_allow_null ( 64 GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", 65 &refresh->blinding_seed), 66 &refresh->no_blinding_seed), 67 GNUNET_PQ_result_spec_allow_null ( 68 TALER_PQ_result_spec_array_cs_r_pub (pg->conn, 69 "cs_r_values", 70 &refresh->num_cs_r_values, 71 &cs_r_values), 72 &no_cs_r_values), 73 GNUNET_PQ_result_spec_allow_null ( 74 GNUNET_PQ_result_spec_uint64 ("cs_r_choices", 75 &refresh->cs_r_choices), 76 &no_cs_r_choices), 77 GNUNET_PQ_result_spec_auto_from_type ("planchets_h", 78 &refresh->planchets_h), 79 GNUNET_PQ_result_spec_auto_from_type ("selected_h", 80 &refresh->selected_h), 81 GNUNET_PQ_result_spec_allow_null ( 82 GNUNET_PQ_result_spec_array_fixed_size (pg->conn, 83 "transfer_pubs", 84 sizeof(*transfer_pubs), 85 &num_transfer_pubs, 86 (void **) &transfer_pubs), 87 &no_transfer_pubs), 88 GNUNET_PQ_result_spec_array_uint64 (pg->conn, 89 "denom_serials", 90 &refresh->num_coins, 91 &denom_serials), 92 TALER_PQ_result_spec_array_blinded_denom_sig (pg->conn, 93 "denom_sigs", 94 &num_denom_sigs, 95 &denom_sigs), 96 GNUNET_PQ_result_spec_bool ("revealed", 97 &refresh->revealed), 98 GNUNET_PQ_result_spec_end 99 }; 100 enum GNUNET_DB_QueryStatus qs; 101 102 memset (&refresh->coin.denom_sig, 103 0, 104 sizeof (refresh->coin.denom_sig)); 105 PREPARE (pg, 106 "get_refresh", 107 "SELECT" 108 " amount_with_fee" 109 ",old_coin_pub" 110 ",kc.age_commitment_hash AS age_commitment_hash" 111 ",old_coin_sig" 112 ",refresh_seed" 113 ",noreveal_index" 114 ",blinding_seed" 115 ",cs_r_values" 116 ",cs_r_choices" 117 ",planchets_h" 118 ",transfer_pubs" 119 ",selected_h" 120 ",denom_serials" 121 ",denom_sigs" 122 ",revealed" 123 " FROM refresh" 124 " JOIN known_coins kc" 125 " ON (old_coin_pub = kc.coin_pub)" 126 " WHERE rc = $1;" 127 ); 128 qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, 129 "get_refresh", 130 params, 131 rs); 132 GNUNET_PQ_cleanup_query_params_closures (params); 133 if (0 > qs) 134 { 135 GNUNET_break (0); 136 GNUNET_PQ_cleanup_result (rs); 137 return qs; 138 } 139 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 140 { 141 GNUNET_PQ_cleanup_result (rs); 142 return qs; 143 } 144 if (refresh->num_coins != num_denom_sigs) 145 { 146 GNUNET_break (0); 147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 148 "got inconsistent number of entries in refresh from DB: " 149 "num_coins=%ld, num_denom_sigs=%ld\n", 150 refresh->num_coins, 151 num_denom_sigs); 152 GNUNET_PQ_cleanup_result (rs); 153 return GNUNET_DB_STATUS_HARD_ERROR; 154 } 155 if (no_transfer_pubs) 156 { 157 refresh->is_v27_refresh = true; 158 refresh->transfer_pubs = NULL; 159 } 160 else 161 { 162 if (num_transfer_pubs != refresh->num_coins) 163 { 164 GNUNET_break (0); 165 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 166 "got inconsistent number of transfer_pubs in refresh from DB: " 167 "num_coins=%ld, num_transfer_pubs=%ld\n", 168 refresh->num_coins, 169 num_transfer_pubs); 170 GNUNET_PQ_cleanup_result (rs); 171 return GNUNET_DB_STATUS_HARD_ERROR; 172 } 173 refresh->is_v27_refresh = false; 174 refresh->transfer_pubs = transfer_pubs; 175 } 176 if (refresh->no_blinding_seed != no_cs_r_values) 177 { 178 GNUNET_break (0); 179 GNUNET_PQ_cleanup_result (rs); 180 return GNUNET_DB_STATUS_HARD_ERROR; 181 } 182 if (no_cs_r_choices != no_cs_r_values) 183 { 184 GNUNET_break (0); 185 GNUNET_PQ_cleanup_result (rs); 186 return GNUNET_DB_STATUS_HARD_ERROR; 187 } 188 if (no_cs_r_values) 189 { 190 refresh->cs_r_values = NULL; 191 refresh->num_cs_r_values = 0; 192 } 193 if (refresh->coin.no_age_commitment) 194 memset (&refresh->coin.h_age_commitment, 195 0, 196 sizeof(refresh->coin.h_age_commitment)); 197 refresh->rc = *rc; 198 /* move the result arrays */ 199 refresh->denom_sigs = denom_sigs; 200 refresh->denom_serials = denom_serials; 201 refresh->cs_r_values = cs_r_values; 202 transfer_pubs = NULL; 203 denom_sigs = NULL; 204 denom_serials = NULL; 205 cs_r_values = NULL; 206 GNUNET_PQ_cleanup_result (rs); 207 return qs; 208 }