Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2016-2023 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or
6 : modify it under the terms of the GNU General Public License
7 : as published by the Free Software Foundation; either version 3,
8 : or (at your option) any later version.
9 :
10 : TALER is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public
16 : License along with TALER; see the file COPYING. If not,
17 : see <http://www.gnu.org/licenses/>
18 : */
19 : /**
20 : * @file bank-lib/fakebank_api_check.c
21 : * @brief library that fakes being a Taler bank for testcases
22 : * @author Christian Grothoff <christian@grothoff.org>
23 : */
24 : #include "taler/platform.h"
25 : #include "taler/taler_fakebank_lib.h"
26 : #include "taler/taler_bank_service.h"
27 : #include "taler/taler_mhd_lib.h"
28 : #include <gnunet/gnunet_mhd_compat.h>
29 : #include "fakebank.h"
30 : #include "fakebank_common_lookup.h"
31 :
32 :
33 : /**
34 : * Generate log messages for failed check operation.
35 : *
36 : * @param h handle to output transaction log for
37 : */
38 : static void
39 0 : check_log (struct TALER_FAKEBANK_Handle *h)
40 : {
41 0 : for (uint64_t i = 0; i<h->ram_limit; i++)
42 : {
43 0 : struct Transaction *t = h->transactions[i];
44 :
45 0 : if (NULL == t)
46 0 : continue;
47 0 : if (! t->unchecked)
48 0 : continue;
49 0 : switch (t->type)
50 : {
51 0 : case T_DEBIT:
52 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
53 : "%s -> %s (%s) %s (%s)\n",
54 : t->debit_account->account_name,
55 : t->credit_account->account_name,
56 : TALER_amount2s (&t->amount),
57 : t->subject.debit.exchange_base_url,
58 : "DEBIT");
59 0 : break;
60 0 : case T_CREDIT:
61 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
62 : "%s -> %s (%s) %s (%s)\n",
63 : t->debit_account->account_name,
64 : t->credit_account->account_name,
65 : TALER_amount2s (&t->amount),
66 : TALER_B2S (&t->subject.credit.reserve_pub),
67 : "CREDIT");
68 0 : break;
69 0 : case T_AUTH:
70 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
71 : "%s -> %s (%s) %s (%s)\n",
72 : t->debit_account->account_name,
73 : t->credit_account->account_name,
74 : TALER_amount2s (&t->amount),
75 : TALER_B2S (&t->subject.auth.account_pub),
76 : "AUTH");
77 0 : break;
78 0 : case T_WAD:
79 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
80 : "%s -> %s (%s) %s[%s] (%s)\n",
81 : t->debit_account->account_name,
82 : t->credit_account->account_name,
83 : TALER_amount2s (&t->amount),
84 : t->subject.wad.origin_base_url,
85 : TALER_B2S (&t->subject.wad),
86 : "WAD");
87 0 : break;
88 : }
89 : }
90 0 : }
91 :
92 :
93 : enum GNUNET_GenericReturnValue
94 48 : TALER_FAKEBANK_check_debit (struct TALER_FAKEBANK_Handle *h,
95 : const struct TALER_Amount *want_amount,
96 : const char *want_debit,
97 : const char *want_credit,
98 : const char *exchange_base_url,
99 : struct TALER_WireTransferIdentifierRawP *wtid)
100 : {
101 : struct Account *debit_account;
102 : struct Account *credit_account;
103 :
104 48 : GNUNET_assert (0 ==
105 : strcasecmp (want_amount->currency,
106 : h->currency));
107 48 : debit_account = TALER_FAKEBANK_lookup_account_ (h,
108 : want_debit,
109 : NULL);
110 48 : credit_account = TALER_FAKEBANK_lookup_account_ (h,
111 : want_credit,
112 : NULL);
113 48 : if (NULL == debit_account)
114 : {
115 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
116 : "I wanted: %s->%s (%s) from exchange %s (DEBIT), but debit account does not even exist!\n",
117 : want_debit,
118 : want_credit,
119 : TALER_amount2s (want_amount),
120 : exchange_base_url);
121 0 : return GNUNET_SYSERR;
122 : }
123 48 : if (NULL == credit_account)
124 : {
125 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
126 : "I wanted: %s->%s (%s) from exchange %s (DEBIT), but credit account does not even exist!\n",
127 : want_debit,
128 : want_credit,
129 : TALER_amount2s (want_amount),
130 : exchange_base_url);
131 0 : return GNUNET_SYSERR;
132 : }
133 48 : for (struct Transaction *t = debit_account->out_tail;
134 209 : NULL != t;
135 161 : t = t->prev_out)
136 : {
137 209 : if ( (t->unchecked) &&
138 71 : (credit_account == t->credit_account) &&
139 98 : (T_DEBIT == t->type) &&
140 49 : (0 == TALER_amount_cmp (want_amount,
141 49 : &t->amount)) &&
142 48 : (0 == strcasecmp (exchange_base_url,
143 48 : t->subject.debit.exchange_base_url)) )
144 : {
145 48 : *wtid = t->subject.debit.wtid;
146 48 : t->unchecked = false;
147 48 : return GNUNET_OK;
148 : }
149 : }
150 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
151 : "Did not find matching transaction! I have:\n");
152 0 : check_log (h);
153 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
154 : "I wanted: %s->%s (%s) from exchange %s (DEBIT)\n",
155 : want_debit,
156 : want_credit,
157 : TALER_amount2s (want_amount),
158 : exchange_base_url);
159 0 : return GNUNET_SYSERR;
160 : }
161 :
162 :
163 : enum GNUNET_GenericReturnValue
164 45 : TALER_FAKEBANK_check_credit (struct TALER_FAKEBANK_Handle *h,
165 : const struct TALER_Amount *want_amount,
166 : const char *want_debit,
167 : const char *want_credit,
168 : const struct TALER_ReservePublicKeyP *reserve_pub)
169 : {
170 : struct Account *debit_account;
171 : struct Account *credit_account;
172 :
173 45 : GNUNET_assert (0 == strcasecmp (want_amount->currency,
174 : h->currency));
175 45 : debit_account = TALER_FAKEBANK_lookup_account_ (h,
176 : want_debit,
177 : NULL);
178 45 : credit_account = TALER_FAKEBANK_lookup_account_ (h,
179 : want_credit,
180 : NULL);
181 45 : if (NULL == debit_account)
182 : {
183 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
184 : "I wanted:\n%s -> %s (%s) with subject %s (CREDIT) but debit account is unknown.\n",
185 : want_debit,
186 : want_credit,
187 : TALER_amount2s (want_amount),
188 : TALER_B2S (reserve_pub));
189 0 : return GNUNET_SYSERR;
190 : }
191 45 : if (NULL == credit_account)
192 : {
193 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
194 : "I wanted:\n%s -> %s (%s) with subject %s (CREDIT) but credit account is unknown.\n",
195 : want_debit,
196 : want_credit,
197 : TALER_amount2s (want_amount),
198 : TALER_B2S (reserve_pub));
199 0 : return GNUNET_SYSERR;
200 : }
201 45 : for (struct Transaction *t = credit_account->in_tail;
202 50 : NULL != t;
203 5 : t = t->prev_in)
204 : {
205 50 : if ( (t->unchecked) &&
206 50 : (debit_account == t->debit_account) &&
207 100 : (T_CREDIT == t->type) &&
208 50 : (0 == TALER_amount_cmp (want_amount,
209 50 : &t->amount)) &&
210 45 : (0 == GNUNET_memcmp (reserve_pub,
211 : &t->subject.credit.reserve_pub)) )
212 : {
213 45 : t->unchecked = false;
214 45 : return GNUNET_OK;
215 : }
216 : }
217 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
218 : "Did not find matching transaction!\nI have:\n");
219 0 : check_log (h);
220 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
221 : "I wanted:\n%s -> %s (%s) with subject %s (CREDIT)\n",
222 : want_debit,
223 : want_credit,
224 : TALER_amount2s (want_amount),
225 : TALER_B2S (reserve_pub));
226 0 : return GNUNET_SYSERR;
227 : }
228 :
229 :
230 : enum GNUNET_GenericReturnValue
231 40 : TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h)
232 : {
233 2621480 : for (uint64_t i = 0; i<h->ram_limit; i++)
234 : {
235 2621440 : struct Transaction *t = h->transactions[i];
236 :
237 2621440 : if ( (NULL != t) &&
238 349 : (t->unchecked) )
239 : {
240 33 : if (T_AUTH == t->type)
241 33 : continue; /* ignore */
242 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
243 : "Expected empty transaction set, but I have:\n");
244 0 : check_log (h);
245 0 : return GNUNET_SYSERR;
246 : }
247 : }
248 40 : return GNUNET_OK;
249 : }
|