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 src/backenddb/iterate_pending_deposits.c
18 : * @brief Implementation of the iterate_pending_deposits function for Postgres
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include <taler/taler_pq_lib.h>
23 : #include "merchant-database/iterate_pending_deposits.h"
24 : #include "helper.h"
25 :
26 :
27 : /**
28 : * Context for iterate_pending_deposits().
29 : */
30 : struct LookupDepositsContext
31 : {
32 : /**
33 : * Function to call with the results.
34 : */
35 : TALER_MERCHANTDB_PendingDepositsCallback cb;
36 :
37 : /**
38 : * Closure for @e cb.
39 : */
40 : void *cb_cls;
41 :
42 : /**
43 : * Database context.
44 : */
45 : struct TALER_MERCHANTDB_PostgresContext *pg;
46 :
47 : /**
48 : * Set to the return value on errors.
49 : */
50 : enum GNUNET_DB_QueryStatus qs;
51 :
52 : };
53 :
54 :
55 : /**
56 : * Function to be called with the results of a SELECT statement
57 : * that has returned @a num_results results about instances.
58 : *
59 : * @param cls of type `struct LookupDepositsContext *`
60 : * @param result the postgres result
61 : * @param num_results the number of results in @a result
62 : */
63 : static void
64 20 : lookup_deposits_cb (void *cls,
65 : PGresult *result,
66 : unsigned int num_results)
67 : {
68 20 : struct LookupDepositsContext *ldc = cls;
69 :
70 31 : for (unsigned int i = 0; i < num_results; i++)
71 : {
72 : uint64_t deposit_serial;
73 : struct GNUNET_TIME_Absolute wire_deadline;
74 : struct GNUNET_TIME_Absolute retry_time;
75 : struct TALER_PrivateContractHashP h_contract_terms;
76 : struct TALER_MerchantPrivateKeyP merchant_priv;
77 : char *instance_id;
78 : struct TALER_MerchantWireHashP h_wire;
79 : struct TALER_Amount amount_with_fee;
80 : struct TALER_Amount deposit_fee;
81 : struct TALER_CoinSpendPublicKeyP coin_pub;
82 : bool no_priv;
83 11 : struct GNUNET_PQ_ResultSpec rs[] = {
84 11 : GNUNET_PQ_result_spec_uint64 ("out_deposit_serial",
85 : &deposit_serial),
86 11 : GNUNET_PQ_result_spec_auto_from_type ("out_h_contract_terms",
87 : &h_contract_terms),
88 11 : GNUNET_PQ_result_spec_allow_null (
89 : GNUNET_PQ_result_spec_auto_from_type ("out_merchant_priv",
90 : &merchant_priv),
91 : &no_priv),
92 11 : GNUNET_PQ_result_spec_string ("out_merchant_id",
93 : &instance_id),
94 11 : GNUNET_PQ_result_spec_absolute_time ("out_wire_transfer_deadline",
95 : &wire_deadline),
96 11 : GNUNET_PQ_result_spec_absolute_time ("out_retry_time",
97 : &retry_time),
98 11 : GNUNET_PQ_result_spec_auto_from_type ("out_h_wire",
99 : &h_wire),
100 11 : TALER_PQ_result_spec_amount_with_currency ("out_amount_with_fee",
101 : &amount_with_fee),
102 11 : TALER_PQ_result_spec_amount_with_currency ("out_deposit_fee",
103 : &deposit_fee),
104 11 : GNUNET_PQ_result_spec_auto_from_type ("out_coin_pub",
105 : &coin_pub),
106 : GNUNET_PQ_result_spec_end
107 : };
108 :
109 11 : if (GNUNET_OK !=
110 11 : GNUNET_PQ_extract_result (result,
111 : rs,
112 : i))
113 : {
114 0 : GNUNET_break (0);
115 0 : ldc->qs = GNUNET_DB_STATUS_HARD_ERROR;
116 0 : return;
117 : }
118 11 : if (no_priv)
119 : {
120 : /* Instance was deleted (private key purged); we can no longer
121 : sign the tracking request, so there is nothing to be done for
122 : this deposit. The SQL already filters those out, this is
123 : merely belt-and-braces. */
124 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
125 : "Skipping deposit %llu of instance `%s': private key was deleted\n",
126 : (unsigned long long) deposit_serial,
127 : instance_id);
128 0 : GNUNET_PQ_cleanup_result (rs);
129 0 : continue;
130 : }
131 11 : ldc->cb (ldc->cb_cls,
132 : deposit_serial,
133 : wire_deadline,
134 : retry_time,
135 : &h_contract_terms,
136 : &merchant_priv,
137 : instance_id,
138 : &h_wire,
139 : &amount_with_fee,
140 : &deposit_fee,
141 : &coin_pub);
142 11 : GNUNET_PQ_cleanup_result (rs);
143 : }
144 : }
145 :
146 :
147 : enum GNUNET_DB_QueryStatus
148 20 : TALER_MERCHANTDB_iterate_pending_deposits (
149 : struct TALER_MERCHANTDB_PostgresContext *pg,
150 : const char *exchange_url,
151 : uint64_t limit,
152 : bool allow_future,
153 : TALER_MERCHANTDB_PendingDepositsCallback cb,
154 : void *cb_cls)
155 : {
156 20 : struct LookupDepositsContext ldc = {
157 : .cb = cb,
158 : .cb_cls = cb_cls,
159 : .pg = pg
160 : };
161 : struct GNUNET_TIME_Absolute now
162 20 : = GNUNET_TIME_absolute_get ();
163 20 : struct GNUNET_PQ_QueryParam params[] = {
164 20 : GNUNET_PQ_query_param_string (exchange_url),
165 20 : GNUNET_PQ_query_param_absolute_time (&now),
166 20 : GNUNET_PQ_query_param_uint64 (&limit),
167 20 : GNUNET_PQ_query_param_bool (allow_future),
168 : GNUNET_PQ_query_param_end
169 : };
170 : enum GNUNET_DB_QueryStatus qs;
171 :
172 20 : PREPARE (pg,
173 : "iterate_pending_deposits",
174 : "SELECT"
175 : " out_deposit_serial"
176 : " ,out_h_contract_terms"
177 : " ,out_merchant_priv"
178 : " ,out_merchant_id"
179 : " ,out_wire_transfer_deadline"
180 : " ,out_retry_time"
181 : " ,out_h_wire"
182 : " ,out_amount_with_fee"
183 : " ,out_deposit_fee"
184 : " ,out_coin_pub"
185 : " FROM merchant.lookup_pending_deposits($1, $2, $3, $4)");
186 20 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
187 : "iterate_pending_deposits",
188 : params,
189 : &lookup_deposits_cb,
190 : &ldc);
191 20 : if (0 > ldc.qs)
192 0 : return ldc.qs;
193 20 : return qs;
194 : }
|