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/pg_get_refresh_reveal.c
18 : * @brief Implementation of the get_refresh_reveal function for Postgres
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include "taler_error_codes.h"
23 : #include "taler_dbevents.h"
24 : #include "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 0 : add_revealed_coins (void *cls,
62 : PGresult *result,
63 : unsigned int num_results)
64 : {
65 0 : struct GetRevealContext *grctx = cls;
66 :
67 0 : if (0 == num_results)
68 0 : return;
69 0 : grctx->rrcs = GNUNET_new_array (num_results,
70 : struct TALER_EXCHANGEDB_RefreshRevealedCoin);
71 0 : grctx->rrcs_len = num_results;
72 0 : for (unsigned int i = 0; i < num_results; i++)
73 : {
74 : uint32_t off;
75 0 : struct GNUNET_PQ_ResultSpec rso[] = {
76 0 : GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
77 : &off),
78 : GNUNET_PQ_result_spec_end
79 : };
80 :
81 0 : if (GNUNET_OK !=
82 0 : GNUNET_PQ_extract_result (result,
83 : rso,
84 : i))
85 : {
86 0 : GNUNET_break (0);
87 0 : grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
88 0 : return;
89 : }
90 0 : if (off >= num_results)
91 : {
92 0 : GNUNET_break (0);
93 0 : grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
94 0 : return;
95 : }
96 : {
97 0 : struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx->rrcs[off];
98 0 : struct GNUNET_PQ_ResultSpec rsi[] = {
99 : /* NOTE: freshcoin_index selected and discarded here... */
100 0 : GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
101 : &rrc->h_denom_pub),
102 0 : GNUNET_PQ_result_spec_auto_from_type ("link_sig",
103 : &rrc->orig_coin_link_sig),
104 0 : GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
105 : &rrc->coin_envelope_hash),
106 0 : TALER_PQ_result_spec_blinded_planchet ("coin_ev",
107 : &rrc->blinded_planchet),
108 0 : TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
109 : &rrc->exchange_vals),
110 0 : TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
111 : &rrc->coin_sig),
112 : GNUNET_PQ_result_spec_end
113 : };
114 :
115 0 : if (NULL !=
116 0 : rrc->blinded_planchet.blinded_message)
117 : {
118 : /* duplicate offset, not allowed */
119 0 : GNUNET_break (0);
120 0 : grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
121 0 : return;
122 : }
123 0 : if (GNUNET_OK !=
124 0 : GNUNET_PQ_extract_result (result,
125 : rsi,
126 : i))
127 : {
128 0 : GNUNET_break (0);
129 0 : grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
130 0 : return;
131 : }
132 : }
133 : }
134 : }
135 :
136 :
137 : enum GNUNET_DB_QueryStatus
138 0 : TEH_PG_get_refresh_reveal (void *cls,
139 : const struct TALER_RefreshCommitmentP *rc,
140 : TALER_EXCHANGEDB_RefreshCallback cb,
141 : void *cb_cls)
142 : {
143 0 : struct PostgresClosure *pg = cls;
144 : struct GetRevealContext grctx;
145 : enum GNUNET_DB_QueryStatus qs;
146 0 : struct GNUNET_PQ_QueryParam params[] = {
147 0 : GNUNET_PQ_query_param_auto_from_type (rc),
148 : GNUNET_PQ_query_param_end
149 : };
150 :
151 0 : 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 0 : 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 0 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
174 : "get_refresh_revealed_coins",
175 : params,
176 : &add_revealed_coins,
177 : &grctx);
178 0 : switch (qs)
179 : {
180 0 : case GNUNET_DB_STATUS_HARD_ERROR:
181 : case GNUNET_DB_STATUS_SOFT_ERROR:
182 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
183 0 : goto cleanup;
184 0 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
185 : default: /* can have more than one result */
186 0 : break;
187 : }
188 0 : switch (grctx.qs)
189 : {
190 0 : case GNUNET_DB_STATUS_HARD_ERROR:
191 : case GNUNET_DB_STATUS_SOFT_ERROR:
192 0 : goto cleanup;
193 0 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
194 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* should be impossible */
195 0 : break;
196 : }
197 :
198 : /* Pass result back to application */
199 0 : cb (cb_cls,
200 : grctx.rrcs_len,
201 0 : grctx.rrcs);
202 0 : cleanup:
203 0 : for (unsigned int i = 0; i < grctx.rrcs_len; i++)
204 : {
205 0 : struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
206 :
207 0 : TALER_blinded_denom_sig_free (&rrc->coin_sig);
208 0 : TALER_blinded_planchet_free (&rrc->blinded_planchet);
209 0 : TALER_denom_ewv_free (&rrc->exchange_vals);
210 : }
211 0 : GNUNET_free (grctx.rrcs);
212 0 : return qs;
213 : }
|