Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023, 2025 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_withdraw.c
18 : * @brief Implementation of the get_withdraw function for Postgres
19 : * @author Özgür Kesim
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_withdraw.h"
26 : #include "pg_helper.h"
27 :
28 :
29 : enum GNUNET_DB_QueryStatus
30 10 : TEH_PG_get_withdraw (
31 : void *cls,
32 : const struct TALER_HashBlindedPlanchetsP *wch,
33 : struct TALER_EXCHANGEDB_Withdraw *wd)
34 : {
35 : enum GNUNET_DB_QueryStatus ret;
36 10 : struct PostgresClosure *pg = cls;
37 10 : struct GNUNET_PQ_QueryParam params[] = {
38 10 : GNUNET_PQ_query_param_auto_from_type (wch),
39 : GNUNET_PQ_query_param_end
40 : };
41 10 : struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL;
42 10 : uint64_t *my_denom_serials = NULL;
43 10 : struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL;
44 10 : size_t num_sigs = 0;
45 10 : size_t num_coins = 0;
46 10 : size_t num_cs_r_values = 0;
47 : bool no_noreveal_index;
48 : bool no_max_age;
49 : bool no_selected_h;
50 : bool no_blinding_seed;
51 : bool no_cs_r_values;
52 : bool no_cs_r_choices;
53 :
54 10 : struct GNUNET_PQ_ResultSpec rs[] = {
55 10 : GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
56 : &wd->planchets_h),
57 10 : GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
58 : &wd->reserve_sig),
59 10 : GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
60 : &wd->reserve_pub),
61 10 : GNUNET_PQ_result_spec_allow_null (
62 : GNUNET_PQ_result_spec_uint16 ("max_age",
63 : &wd->max_age),
64 : &no_max_age),
65 10 : TALER_PQ_result_spec_amount ("amount_with_fee",
66 10 : pg->currency,
67 : &wd->amount_with_fee),
68 10 : GNUNET_PQ_result_spec_allow_null (
69 : GNUNET_PQ_result_spec_uint16 ("noreveal_index",
70 : &wd->noreveal_index),
71 : &no_noreveal_index),
72 10 : GNUNET_PQ_result_spec_allow_null (
73 10 : GNUNET_PQ_result_spec_auto_from_type ("selected_h",
74 : &wd->selected_h),
75 : &no_selected_h),
76 10 : GNUNET_PQ_result_spec_allow_null (
77 10 : GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
78 : &wd->blinding_seed),
79 : &no_blinding_seed),
80 10 : GNUNET_PQ_result_spec_allow_null (
81 : TALER_PQ_result_spec_array_cs_r_pub (
82 : pg->conn,
83 : "cs_r_values",
84 : &num_cs_r_values,
85 : &my_cs_r_values),
86 : &no_cs_r_values),
87 10 : GNUNET_PQ_result_spec_allow_null (
88 : GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
89 : &wd->cs_r_choices),
90 : &no_cs_r_choices),
91 10 : TALER_PQ_result_spec_array_blinded_denom_sig (
92 : pg->conn,
93 : "denom_sigs",
94 : &num_sigs,
95 : &my_denom_sigs),
96 10 : GNUNET_PQ_result_spec_array_uint64 (
97 : pg->conn,
98 : "denom_serials",
99 : &num_coins,
100 : &my_denom_serials),
101 : GNUNET_PQ_result_spec_end
102 : };
103 :
104 10 : PREPARE (pg,
105 : "get_withdraw",
106 : "SELECT"
107 : " planchets_h"
108 : ",blinding_seed"
109 : ",reserve_sig"
110 : ",reserve_pub"
111 : ",max_age"
112 : ",amount_with_fee"
113 : ",noreveal_index"
114 : ",selected_h"
115 : ",blinding_seed"
116 : ",cs_r_values"
117 : ",cs_r_choices"
118 : ",denom_sigs"
119 : ",denom_serials"
120 : " FROM withdraw"
121 : " WHERE planchets_h=$1;");
122 10 : ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
123 : "get_withdraw",
124 : params,
125 : rs);
126 10 : if (0 > ret)
127 : {
128 0 : GNUNET_break (0);
129 0 : GNUNET_PQ_cleanup_result (rs);
130 0 : return ret;
131 : }
132 10 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret)
133 : {
134 7 : GNUNET_PQ_cleanup_result (rs);
135 7 : return ret;
136 : }
137 :
138 3 : if ((no_max_age != no_noreveal_index) ||
139 3 : (no_max_age != no_selected_h))
140 : {
141 0 : GNUNET_break (0);
142 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
143 : "got inconsistent state for max_age, noreveal_index and planchets_h in DB: "
144 : "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n",
145 : no_max_age ? "true" : "false",
146 : no_noreveal_index ? "true" : "false",
147 : no_selected_h ? "true" : "false");
148 0 : GNUNET_PQ_cleanup_result (rs);
149 0 : return GNUNET_DB_STATUS_HARD_ERROR;
150 : }
151 3 : if (no_blinding_seed != no_cs_r_values)
152 : {
153 0 : GNUNET_break (0);
154 0 : GNUNET_PQ_cleanup_result (rs);
155 0 : return GNUNET_DB_STATUS_HARD_ERROR;
156 : }
157 3 : if (no_cs_r_choices != no_cs_r_values)
158 : {
159 0 : GNUNET_break (0);
160 0 : GNUNET_PQ_cleanup_result (rs);
161 0 : return GNUNET_DB_STATUS_HARD_ERROR;
162 : }
163 3 : if (num_coins != num_sigs)
164 : {
165 0 : GNUNET_break (0);
166 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
167 : "got inconsistent number of entries in withdraw from DB: "
168 : "num_coins=%ld, num_sigs=%ld\n",
169 : num_coins,
170 : num_sigs);
171 0 : GNUNET_PQ_cleanup_result (rs);
172 0 : return GNUNET_DB_STATUS_HARD_ERROR;
173 : }
174 3 : wd->age_proof_required = ! no_max_age;
175 3 : if (no_cs_r_values)
176 : {
177 2 : wd->cs_r_values = NULL;
178 2 : wd->num_cs_r_values = 0;
179 2 : wd->cs_r_choices = 0;
180 : }
181 3 : wd->denom_sigs = my_denom_sigs;
182 3 : wd->num_coins = num_coins;
183 3 : wd->denom_serials = my_denom_serials;
184 3 : wd->cs_r_values = my_cs_r_values;
185 3 : wd->num_cs_r_values = num_cs_r_values;
186 : /* ensure cleanup_result does not trash data we care about */
187 3 : my_denom_sigs = NULL;
188 3 : my_denom_serials = NULL;
189 3 : my_cs_r_values = NULL;
190 3 : num_sigs = 0;
191 3 : num_coins = 0;
192 3 : num_cs_r_values = 0;
193 3 : GNUNET_PQ_cleanup_result (rs);
194 3 : return ret;
195 : }
|