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/do_withdraw.c
18 : * @brief Implementation of the do_withdraw function for Postgres
19 : * @author Özgür Kesim
20 : */
21 : #include "taler/taler_exchangedb_lib.h"
22 : #include "taler/taler_pq_lib.h"
23 : #include "exchange-database/do_withdraw.h"
24 : #include "helper.h"
25 : #include <gnunet/gnunet_time_lib.h>
26 :
27 :
28 : enum GNUNET_DB_QueryStatus
29 71 : TALER_EXCHANGEDB_do_withdraw (
30 : struct TALER_EXCHANGEDB_PostgresContext *pg,
31 : const struct TALER_EXCHANGEDB_Withdraw *withdraw,
32 : const struct GNUNET_TIME_Timestamp *timestamp,
33 : bool *balance_ok,
34 : struct TALER_Amount *reserve_balance,
35 : bool *age_ok,
36 : uint16_t *required_age,
37 : uint32_t *reserve_birthday,
38 : bool *idempotent,
39 : uint16_t *noreveal_index,
40 : bool *nonce_reuse)
41 : {
42 : struct GNUNET_TIME_Timestamp gc;
43 71 : struct GNUNET_PQ_QueryParam params[] = {
44 71 : TALER_PQ_query_param_amount (pg->conn,
45 : &withdraw->amount_with_fee),
46 71 : GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_pub),
47 71 : GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_sig),
48 71 : GNUNET_PQ_query_param_timestamp (timestamp),
49 71 : GNUNET_PQ_query_param_timestamp (&gc),
50 71 : GNUNET_PQ_query_param_auto_from_type (&withdraw->planchets_h),
51 71 : (withdraw->age_proof_required)
52 5 : ? GNUNET_PQ_query_param_uint16 (&withdraw->max_age)
53 71 : : GNUNET_PQ_query_param_null (),
54 71 : (withdraw->age_proof_required)
55 5 : ? GNUNET_PQ_query_param_uint16 (&withdraw->noreveal_index)
56 71 : : GNUNET_PQ_query_param_null (),
57 71 : (withdraw->age_proof_required)
58 5 : ? GNUNET_PQ_query_param_auto_from_type (&withdraw->selected_h)
59 71 : : GNUNET_PQ_query_param_null (),
60 71 : GNUNET_PQ_query_param_array_uint64 (withdraw->num_coins,
61 71 : withdraw->denom_serials,
62 : pg->conn),
63 71 : TALER_PQ_query_param_array_blinded_denom_sig (withdraw->num_coins,
64 71 : withdraw->denom_sigs,
65 : pg->conn),
66 71 : (withdraw->no_blinding_seed)
67 37 : ? GNUNET_PQ_query_param_null ()
68 71 : : GNUNET_PQ_query_param_auto_from_type (&withdraw->blinding_seed),
69 71 : (withdraw->no_blinding_seed)
70 37 : ? GNUNET_PQ_query_param_null ()
71 71 : : TALER_PQ_query_param_array_cs_r_pub (withdraw->num_cs_r_values,
72 34 : withdraw->cs_r_values,
73 : pg->conn),
74 71 : (withdraw->no_blinding_seed)
75 37 : ? GNUNET_PQ_query_param_null ()
76 71 : : GNUNET_PQ_query_param_uint64 (&withdraw->cs_r_choices),
77 : GNUNET_PQ_query_param_end
78 : };
79 : bool reserve_found;
80 : bool no_noreveal_index;
81 71 : struct GNUNET_PQ_ResultSpec rs[] = {
82 71 : GNUNET_PQ_result_spec_bool ("out_reserve_found",
83 : &reserve_found),
84 71 : GNUNET_PQ_result_spec_bool ("out_balance_ok",
85 : balance_ok),
86 71 : TALER_PQ_RESULT_SPEC_AMOUNT ("out_reserve_balance",
87 : reserve_balance),
88 71 : GNUNET_PQ_result_spec_bool ("out_age_ok",
89 : age_ok),
90 71 : GNUNET_PQ_result_spec_uint16 ("out_required_age",
91 : required_age),
92 71 : GNUNET_PQ_result_spec_uint32 ("out_reserve_birthday",
93 : reserve_birthday),
94 71 : GNUNET_PQ_result_spec_bool ("out_idempotent",
95 : idempotent),
96 71 : GNUNET_PQ_result_spec_allow_null (
97 : GNUNET_PQ_result_spec_uint16 ("out_noreveal_index",
98 : noreveal_index),
99 : &no_noreveal_index),
100 71 : GNUNET_PQ_result_spec_bool ("out_nonce_reuse",
101 : nonce_reuse),
102 : GNUNET_PQ_result_spec_end
103 : };
104 : enum GNUNET_DB_QueryStatus qs;
105 :
106 71 : GNUNET_assert ((! withdraw->no_blinding_seed) ||
107 : (0 == withdraw->num_cs_r_values));
108 :
109 71 : gc = GNUNET_TIME_absolute_to_timestamp (
110 : GNUNET_TIME_absolute_add (timestamp->abs_time,
111 : pg->legal_reserve_expiration_time));
112 71 : PREPARE (pg,
113 : "call_withdraw",
114 : "SELECT "
115 : " out_reserve_found"
116 : ",out_balance_ok"
117 : ",out_reserve_balance"
118 : ",out_age_ok"
119 : ",out_required_age"
120 : ",out_reserve_birthday"
121 : ",out_idempotent"
122 : ",out_noreveal_index"
123 : ",out_nonce_reuse"
124 : " FROM exchange_do_withdraw"
125 : " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14);");
126 71 : qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
127 : "call_withdraw",
128 : params,
129 : rs);
130 71 : GNUNET_PQ_cleanup_query_params_closures (params);
131 :
132 71 : if (0 > qs)
133 0 : return qs;
134 71 : if (! reserve_found)
135 0 : return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
136 71 : if ((withdraw->age_proof_required) &&
137 5 : (idempotent && no_noreveal_index))
138 0 : GNUNET_break (0);
139 71 : return qs;
140 : }
|