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