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