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