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 "taler/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/taler_json_lib.h"
28 : #include "taler/taler_mhd_lib.h"
29 : #include "taler/taler_signatures.h"
30 : #include "taler-exchange-httpd_management.h"
31 : #include "taler-exchange-httpd_responses.h"
32 : #include "taler-exchange-httpd_keys.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 27 : add_fee (void *cls,
84 : struct MHD_Connection *connection,
85 : MHD_RESULT *mhd_ret)
86 : {
87 27 : struct AddFeeContext *afc = cls;
88 : enum GNUNET_DB_QueryStatus qs;
89 : struct TALER_WireFeeSet fees;
90 :
91 27 : qs = TEH_plugin->lookup_wire_fee_by_time (
92 27 : TEH_plugin->cls,
93 : afc->wire_method,
94 : afc->start_time,
95 : afc->end_time,
96 : &fees);
97 27 : 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 27 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
109 : {
110 4 : if ( (GNUNET_OK ==
111 8 : TALER_amount_is_valid (&fees.wire)) &&
112 : (0 ==
113 4 : TALER_wire_fee_set_cmp (&fees,
114 4 : &afc->fees)) )
115 : {
116 : /* this will trigger the 'success' response */
117 2 : return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
118 : }
119 : else
120 : {
121 2 : *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 2 : return GNUNET_DB_STATUS_HARD_ERROR;
128 : }
129 :
130 23 : qs = TEH_plugin->insert_wire_fee (
131 23 : TEH_plugin->cls,
132 : afc->wire_method,
133 : afc->start_time,
134 : afc->end_time,
135 23 : &afc->fees,
136 23 : &afc->master_sig);
137 23 : 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 23 : return qs;
149 : }
150 :
151 :
152 : MHD_RESULT
153 29 : 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 29 : GNUNET_JSON_spec_fixed_auto ("master_sig",
160 : &afc.master_sig),
161 29 : GNUNET_JSON_spec_string ("wire_method",
162 : &afc.wire_method),
163 29 : GNUNET_JSON_spec_timestamp ("fee_start",
164 : &afc.start_time),
165 29 : GNUNET_JSON_spec_timestamp ("fee_end",
166 : &afc.end_time),
167 29 : TALER_JSON_spec_amount ("wire_fee",
168 : TEH_currency,
169 : &afc.fees.wire),
170 29 : TALER_JSON_spec_amount ("closing_fee",
171 : TEH_currency,
172 : &afc.fees.closing),
173 29 : GNUNET_JSON_spec_end ()
174 : };
175 :
176 : {
177 : enum GNUNET_GenericReturnValue res;
178 :
179 29 : res = TALER_MHD_parse_json_data (connection,
180 : root,
181 : spec);
182 29 : if (GNUNET_SYSERR == res)
183 0 : return MHD_NO; /* hard failure */
184 29 : if (GNUNET_NO == res)
185 0 : return MHD_YES; /* failure */
186 : }
187 :
188 29 : TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
189 29 : if (GNUNET_OK !=
190 29 : TALER_exchange_offline_wire_fee_verify (
191 : afc.wire_method,
192 : afc.start_time,
193 : afc.end_time,
194 : &afc.fees,
195 : &TEH_master_public_key,
196 : &afc.master_sig))
197 : {
198 : /* signature invalid */
199 2 : GNUNET_break_op (0);
200 2 : return TALER_MHD_reply_with_error (
201 : connection,
202 : MHD_HTTP_FORBIDDEN,
203 : TALER_EC_EXCHANGE_MANAGEMENT_WIRE_FEE_SIGNATURE_INVALID,
204 : NULL);
205 : }
206 :
207 : {
208 : enum GNUNET_GenericReturnValue res;
209 : MHD_RESULT ret;
210 :
211 27 : res = TEH_DB_run_transaction (connection,
212 : "add wire fee",
213 : TEH_MT_REQUEST_OTHER,
214 : &ret,
215 : &add_fee,
216 : &afc);
217 27 : if (GNUNET_SYSERR == res)
218 2 : return ret;
219 : }
220 25 : TEH_wire_update_state ();
221 25 : return TALER_MHD_reply_static (
222 : connection,
223 : MHD_HTTP_NO_CONTENT,
224 : NULL,
225 : NULL,
226 : 0);
227 : }
228 :
229 :
230 : /* end of taler-exchange-httpd_management_wire_fees.c */
|