get_refresh.c (7653B)
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/get_refresh.c 18 * @brief Implementation of the get_refresh function for Postgres 19 * @author get_refresh 20 */ 21 #include "taler/taler_pq_lib.h" 22 #include "exchange-database/get_refresh.h" 23 #include "helper.h" 24 25 26 enum GNUNET_DB_QueryStatus 27 TALER_EXCHANGEDB_get_refresh ( 28 struct TALER_EXCHANGEDB_PostgresContext *pg, 29 const struct TALER_RefreshCommitmentP *rc, 30 struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh) 31 { 32 struct GNUNET_PQ_QueryParam params[] = { 33 GNUNET_PQ_query_param_auto_from_type (rc), 34 GNUNET_PQ_query_param_end 35 }; 36 bool no_cs_r_values; 37 bool no_cs_r_choices; 38 bool no_transfer_pubs; 39 size_t num_denom_sigs; 40 size_t num_transfer_pubs; 41 struct TALER_BlindedDenominationSignature *denom_sigs = NULL; 42 struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values = NULL; 43 struct TALER_TransferPublicKeyP *transfer_pubs = NULL; 44 uint64_t *denom_serials = NULL; 45 struct GNUNET_PQ_ResultSpec rs[] = { 46 GNUNET_PQ_result_spec_uint64 ("refresh_id", 47 &refresh->refresh_id), 48 TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", 49 &refresh->amount_with_fee), 50 GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", 51 &refresh->coin.coin_pub), 52 GNUNET_PQ_result_spec_allow_null ( 53 GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", 54 &refresh->coin.h_age_commitment), 55 &refresh->coin.no_age_commitment), 56 GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", 57 &refresh->coin_sig), 58 GNUNET_PQ_result_spec_auto_from_type ("refresh_seed", 59 &refresh->refresh_seed), 60 GNUNET_PQ_result_spec_uint32 ("noreveal_index", 61 &refresh->noreveal_index), 62 GNUNET_PQ_result_spec_allow_null ( 63 GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", 64 &refresh->blinding_seed), 65 &refresh->no_blinding_seed), 66 GNUNET_PQ_result_spec_allow_null ( 67 TALER_PQ_result_spec_array_cs_r_pub (pg->conn, 68 "cs_r_values", 69 &refresh->num_cs_r_values, 70 &cs_r_values), 71 &no_cs_r_values), 72 GNUNET_PQ_result_spec_allow_null ( 73 GNUNET_PQ_result_spec_uint64 ("cs_r_choices", 74 &refresh->cs_r_choices), 75 &no_cs_r_choices), 76 GNUNET_PQ_result_spec_auto_from_type ("planchets_h", 77 &refresh->planchets_h), 78 GNUNET_PQ_result_spec_auto_from_type ("selected_h", 79 &refresh->selected_h), 80 GNUNET_PQ_result_spec_allow_null ( 81 GNUNET_PQ_result_spec_array_fixed_size (pg->conn, 82 "transfer_pubs", 83 sizeof(*transfer_pubs), 84 &num_transfer_pubs, 85 (void **) &transfer_pubs), 86 &no_transfer_pubs), 87 GNUNET_PQ_result_spec_array_uint64 (pg->conn, 88 "denom_serials", 89 &refresh->num_coins, 90 &denom_serials), 91 TALER_PQ_result_spec_array_blinded_denom_sig (pg->conn, 92 "denom_sigs", 93 &num_denom_sigs, 94 &denom_sigs), 95 GNUNET_PQ_result_spec_bool ("revealed", 96 &refresh->revealed), 97 GNUNET_PQ_result_spec_end 98 }; 99 enum GNUNET_DB_QueryStatus qs; 100 101 memset (&refresh->coin.denom_sig, 102 0, 103 sizeof (refresh->coin.denom_sig)); 104 PREPARE (pg, 105 "get_refresh", 106 "SELECT" 107 " refresh_id" 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 }