Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020, 2021, 2022 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU Affero 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 Affero General Public License for more details.
12 :
13 : You should have received a copy of the GNU Affero General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file taler-exchange-httpd_management_wire_fees.c
18 : * @brief Handle request to add wire fee details
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include <gnunet/gnunet_util_lib.h>
23 : #include <gnunet/gnunet_json_lib.h>
24 : #include <jansson.h>
25 : #include <microhttpd.h>
26 : #include <pthread.h>
27 : #include "taler_json_lib.h"
28 : #include "taler_mhd_lib.h"
29 : #include "taler_signatures.h"
30 : #include "taler-exchange-httpd_management.h"
31 : #include "taler-exchange-httpd_responses.h"
32 : #include "taler-exchange-httpd_wire.h"
33 :
34 :
35 : /**
36 : * Closure for the #add_fee transaction.
37 : */
38 : struct AddFeeContext
39 : {
40 : /**
41 : * Fee's signature affirming the #TALER_SIGNATURE_MASTER_WIRE_FEES operation.
42 : */
43 : struct TALER_MasterSignatureP master_sig;
44 :
45 : /**
46 : * Wire method this is about.
47 : */
48 : const char *wire_method;
49 :
50 : /**
51 : * Starting period.
52 : */
53 : struct GNUNET_TIME_Timestamp start_time;
54 :
55 : /**
56 : * End of period.
57 : */
58 : struct GNUNET_TIME_Timestamp end_time;
59 :
60 : /**
61 : * Wire fee amounts.
62 : */
63 : struct TALER_WireFeeSet fees;
64 :
65 : };
66 :
67 :
68 : /**
69 : * Function implementing database transaction to add a fee. Runs the
70 : * transaction logic; IF it returns a non-error code, the transaction logic
71 : * MUST NOT queue a MHD response. IF it returns an hard error, the
72 : * transaction logic MUST queue a MHD response and set @a mhd_ret. IF it
73 : * returns the soft error code, the function MAY be called again to retry and
74 : * MUST not queue a MHD response.
75 : *
76 : * @param cls closure with a `struct AddFeeContext`
77 : * @param connection MHD request which triggered the transaction
78 : * @param[out] mhd_ret set to MHD response status for @a connection,
79 : * if transaction failed (!)
80 : * @return transaction status
81 : */
82 : static enum GNUNET_DB_QueryStatus
83 0 : add_fee (void *cls,
84 : struct MHD_Connection *connection,
85 : MHD_RESULT *mhd_ret)
86 : {
87 0 : struct AddFeeContext *afc = cls;
88 : enum GNUNET_DB_QueryStatus qs;
89 : struct TALER_WireFeeSet fees;
90 :
91 0 : qs = TEH_plugin->lookup_wire_fee_by_time (
92 0 : TEH_plugin->cls,
93 : afc->wire_method,
94 : afc->start_time,
95 : afc->end_time,
96 : &fees);
97 0 : if (qs < 0)
98 : {
99 0 : if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
100 0 : return qs;
101 0 : GNUNET_break (0);
102 0 : *mhd_ret = TALER_MHD_reply_with_error (connection,
103 : MHD_HTTP_INTERNAL_SERVER_ERROR,
104 : TALER_EC_GENERIC_DB_FETCH_FAILED,
105 : "lookup wire fee");
106 0 : return qs;
107 : }
108 0 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
109 : {
110 0 : if ( (GNUNET_OK ==
111 0 : TALER_amount_is_valid (&fees.wire)) &&
112 : (0 ==
113 0 : TALER_wire_fee_set_cmp (&fees,
114 0 : &afc->fees)) )
115 : {
116 : /* this will trigger the 'success' response */
117 0 : return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
118 : }
119 : else
120 : {
121 0 : *mhd_ret = TALER_MHD_reply_with_error (
122 : connection,
123 : MHD_HTTP_CONFLICT,
124 : TALER_EC_EXCHANGE_MANAGEMENT_WIRE_FEE_MISMATCH,
125 : NULL);
126 : }
127 0 : return GNUNET_DB_STATUS_HARD_ERROR;
128 : }
129 :
130 0 : qs = TEH_plugin->insert_wire_fee (
131 0 : TEH_plugin->cls,
132 : afc->wire_method,
133 : afc->start_time,
134 : afc->end_time,
135 0 : &afc->fees,
136 0 : &afc->master_sig);
137 0 : if (qs < 0)
138 : {
139 0 : if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
140 0 : return qs;
141 0 : GNUNET_break (0);
142 0 : *mhd_ret = TALER_MHD_reply_with_error (connection,
143 : MHD_HTTP_INTERNAL_SERVER_ERROR,
144 : TALER_EC_GENERIC_DB_STORE_FAILED,
145 : "insert fee");
146 0 : return qs;
147 : }
148 0 : return qs;
149 : }
150 :
151 :
152 : MHD_RESULT
153 0 : TEH_handler_management_post_wire_fees (
154 : struct MHD_Connection *connection,
155 : const json_t *root)
156 : {
157 : struct AddFeeContext afc;
158 : struct GNUNET_JSON_Specification spec[] = {
159 0 : GNUNET_JSON_spec_fixed_auto ("master_sig",
160 : &afc.master_sig),
161 0 : GNUNET_JSON_spec_string ("wire_method",
162 : &afc.wire_method),
163 0 : GNUNET_JSON_spec_timestamp ("fee_start",
164 : &afc.start_time),
165 0 : GNUNET_JSON_spec_timestamp ("fee_end",
166 : &afc.end_time),
167 0 : TALER_JSON_spec_amount ("wire_fee",
168 : TEH_currency,
169 : &afc.fees.wire),
170 0 : TALER_JSON_spec_amount ("closing_fee",
171 : TEH_currency,
172 : &afc.fees.closing),
173 0 : TALER_JSON_spec_amount ("wad_fee",
174 : TEH_currency,
175 : &afc.fees.wad),
176 0 : GNUNET_JSON_spec_end ()
177 : };
178 :
179 : {
180 : enum GNUNET_GenericReturnValue res;
181 :
182 0 : res = TALER_MHD_parse_json_data (connection,
183 : root,
184 : spec);
185 0 : if (GNUNET_SYSERR == res)
186 0 : return MHD_NO; /* hard failure */
187 0 : if (GNUNET_NO == res)
188 0 : return MHD_YES; /* failure */
189 : }
190 :
191 0 : TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
192 0 : if (GNUNET_OK !=
193 0 : TALER_exchange_offline_wire_fee_verify (
194 : afc.wire_method,
195 : afc.start_time,
196 : afc.end_time,
197 : &afc.fees,
198 : &TEH_master_public_key,
199 : &afc.master_sig))
200 : {
201 : /* signature invalid */
202 0 : GNUNET_break_op (0);
203 0 : return TALER_MHD_reply_with_error (
204 : connection,
205 : MHD_HTTP_FORBIDDEN,
206 : TALER_EC_EXCHANGE_MANAGEMENT_WIRE_FEE_SIGNATURE_INVALID,
207 : NULL);
208 : }
209 :
210 : {
211 : enum GNUNET_GenericReturnValue res;
212 : MHD_RESULT ret;
213 :
214 0 : res = TEH_DB_run_transaction (connection,
215 : "add wire fee",
216 : TEH_MT_REQUEST_OTHER,
217 : &ret,
218 : &add_fee,
219 : &afc);
220 0 : if (GNUNET_SYSERR == res)
221 0 : return ret;
222 : }
223 0 : TEH_wire_update_state ();
224 0 : return TALER_MHD_reply_static (
225 : connection,
226 : MHD_HTTP_NO_CONTENT,
227 : NULL,
228 : NULL,
229 : 0);
230 : }
231 :
232 :
233 : /* end of taler-exchange-httpd_management_wire_fees.c */
|