Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 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_do_refresh.c
18 : * @brief Implementation of the do_refresh function for Postgres
19 : * @author Özgür Kesim
20 : */
21 : #include "taler/platform.h"
22 : #include "taler/taler_error_codes.h"
23 : #include "taler/taler_dbevents.h"
24 : #include "taler/taler_exchangedb_plugin.h"
25 : #include "taler/taler_pq_lib.h"
26 : #include "pg_do_refresh.h"
27 : #include "pg_helper.h"
28 :
29 :
30 : enum GNUNET_DB_QueryStatus
31 29 : TEH_PG_do_refresh (
32 : void *cls,
33 : struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh,
34 : const struct GNUNET_TIME_Timestamp *timestamp,
35 : bool *found,
36 : uint32_t *noreveal_index,
37 : bool *zombie_required,
38 : bool *nonce_reuse,
39 : bool *balance_ok,
40 : struct TALER_Amount *coin_balance)
41 : {
42 29 : struct PostgresClosure *pg = cls;
43 29 : struct GNUNET_PQ_QueryParam params[] = {
44 29 : GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
45 29 : GNUNET_PQ_query_param_timestamp (timestamp),
46 29 : GNUNET_PQ_query_param_auto_from_type (&refresh->refresh_seed), /* 3 */
47 29 : (refresh->is_v27_refresh)
48 0 : ? GNUNET_PQ_query_param_null ()
49 29 : : GNUNET_PQ_query_param_array_auto_from_type (refresh->num_coins,
50 : refresh->transfer_pubs,
51 : pg->conn),
52 29 : GNUNET_PQ_query_param_auto_from_type (&refresh->planchets_h),
53 29 : TALER_PQ_query_param_amount (pg->conn, /* 6 */
54 29 : &refresh->amount_with_fee),
55 29 : (refresh->no_blinding_seed)
56 14 : ? GNUNET_PQ_query_param_null ()
57 29 : : GNUNET_PQ_query_param_auto_from_type (&refresh->blinding_seed),
58 29 : (0 < refresh->num_cs_r_values)
59 15 : ? TALER_PQ_query_param_array_cs_r_pub (refresh->num_cs_r_values,
60 15 : refresh->cs_r_values,
61 : pg->conn)
62 29 : : GNUNET_PQ_query_param_null (),
63 29 : (0 < refresh->num_cs_r_values)
64 15 : ? GNUNET_PQ_query_param_uint64 (&refresh->cs_r_choices) /* 9 */
65 29 : : GNUNET_PQ_query_param_null (),
66 29 : GNUNET_PQ_query_param_auto_from_type (&refresh->selected_h),
67 29 : TALER_PQ_query_param_array_blinded_denom_sig (refresh->num_coins,
68 29 : refresh->denom_sigs,
69 : pg->conn),
70 29 : GNUNET_PQ_query_param_array_uint64 (refresh->num_coins, /* 12 */
71 29 : refresh->denom_serials,
72 : pg->conn),
73 29 : GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
74 29 : GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig),
75 29 : GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index), /* 15 */
76 29 : GNUNET_PQ_query_param_bool (*zombie_required),
77 : GNUNET_PQ_query_param_end
78 : };
79 : bool coin_found;
80 : bool no_noreveal_index;
81 : bool no_coin_balance;
82 29 : struct GNUNET_PQ_ResultSpec rs[] = {
83 29 : GNUNET_PQ_result_spec_bool ("coin_found",
84 : &coin_found),
85 29 : GNUNET_PQ_result_spec_bool ("balance_ok",
86 : balance_ok),
87 29 : GNUNET_PQ_result_spec_bool ("zombie_required",
88 : zombie_required),
89 29 : GNUNET_PQ_result_spec_bool ("nonce_reuse",
90 : nonce_reuse),
91 29 : GNUNET_PQ_result_spec_bool ("found",
92 : found),
93 29 : GNUNET_PQ_result_spec_allow_null (
94 : GNUNET_PQ_result_spec_uint32 ("noreveal_index",
95 : noreveal_index),
96 : &no_noreveal_index),
97 29 : GNUNET_PQ_result_spec_allow_null (
98 29 : TALER_PQ_RESULT_SPEC_AMOUNT ("coin_balance",
99 : coin_balance),
100 : &no_coin_balance),
101 : GNUNET_PQ_result_spec_end
102 : };
103 : enum GNUNET_DB_QueryStatus qs;
104 :
105 29 : PREPARE (pg,
106 : "call_refresh",
107 : "SELECT "
108 : " out_coin_found AS coin_found"
109 : ",out_balance_ok AS balance_ok"
110 : ",out_zombie_bad AS zombie_required"
111 : ",out_nonce_reuse AS nonce_reuse"
112 : ",out_idempotent AS found"
113 : ",out_noreveal_index AS noreveal_index"
114 : ",out_coin_balance AS coin_balance"
115 : " FROM exchange_do_refresh"
116 : " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);");
117 29 : qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
118 : "call_refresh",
119 : params,
120 : rs);
121 29 : GNUNET_PQ_cleanup_query_params_closures (params);
122 29 : if (0 > qs)
123 : {
124 0 : GNUNET_break (0);
125 0 : return qs;
126 : }
127 29 : if (! coin_found)
128 : {
129 0 : return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
130 : }
131 29 : if (*found && no_noreveal_index)
132 : {
133 0 : GNUNET_break (0);
134 0 : return GNUNET_DB_STATUS_HARD_ERROR;
135 : }
136 29 : if (! balance_ok && no_coin_balance)
137 : {
138 0 : GNUNET_break (0);
139 0 : return GNUNET_DB_STATUS_HARD_ERROR;
140 : }
141 29 : return qs;
142 : }
|