diff options
Diffstat (limited to 'src/lib')
38 files changed, 963 insertions, 1858 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 529a2d019..53190bc5b 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -32,7 +32,6 @@ libtalerexchange_la_SOURCES = \ exchange_api_csr_melt.c \ exchange_api_csr_withdraw.c \ exchange_api_handle.c exchange_api_handle.h \ - exchange_api_deposit.c \ exchange_api_deposits_get.c \ exchange_api_kyc_check.c \ exchange_api_kyc_proof.c \ @@ -96,7 +95,7 @@ libtalerauditor_la_LDFLAGS = \ -no-undefined libtalerauditor_la_SOURCES = \ auditor_api_curl_defaults.c auditor_api_curl_defaults.h \ - auditor_api_handle.c auditor_api_handle.h \ + auditor_api_get_config.c \ auditor_api_deposit_confirmation.c \ auditor_api_exchanges.c libtalerauditor_la_LIBADD = \ diff --git a/src/lib/auditor_api_deposit_confirmation.c b/src/lib/auditor_api_deposit_confirmation.c index 55a05d962..0b0f4dd4d 100644 --- a/src/lib/auditor_api_deposit_confirmation.c +++ b/src/lib/auditor_api_deposit_confirmation.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -25,9 +25,10 @@ #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_json_lib.h> #include <gnunet/gnunet_curl_lib.h> +#include "taler_util.h" +#include "taler_curl_lib.h" #include "taler_json_lib.h" #include "taler_auditor_service.h" -#include "auditor_api_handle.h" #include "taler_signatures.h" #include "auditor_api_curl_defaults.h" @@ -39,11 +40,6 @@ struct TALER_AUDITOR_DepositConfirmationHandle { /** - * The connection to auditor this request handle will use - */ - struct TALER_AUDITOR_Handle *auditor; - - /** * The url for this request. */ char *url; @@ -87,64 +83,64 @@ handle_deposit_confirmation_finished (void *cls, { const json_t *json = djson; struct TALER_AUDITOR_DepositConfirmationHandle *dh = cls; - struct TALER_AUDITOR_HttpResponse hr = { - .reply = json, - .http_status = (unsigned int) response_code + struct TALER_AUDITOR_DepositConfirmationResponse dcr = { + .hr.reply = json, + .hr.http_status = (unsigned int) response_code }; dh->job = NULL; switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + dcr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: - hr.ec = TALER_EC_NONE; + dcr.hr.ec = TALER_EC_NONE; break; case MHD_HTTP_BAD_REQUEST: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + dcr.hr.ec = TALER_JSON_get_error_code (json); + dcr.hr.hint = TALER_JSON_get_error_hint (json); /* This should never happen, either us or the auditor is buggy (or API version conflict); just pass JSON reply to the application */ break; case MHD_HTTP_FORBIDDEN: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + dcr.hr.ec = TALER_JSON_get_error_code (json); + dcr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, auditor says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + dcr.hr.ec = TALER_JSON_get_error_code (json); + dcr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_GONE: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + dcr.hr.ec = TALER_JSON_get_error_code (json); + dcr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, auditor says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_INTERNAL_SERVER_ERROR: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + dcr.hr.ec = TALER_JSON_get_error_code (json); + dcr.hr.hint = TALER_JSON_get_error_hint (json); /* Server had an internal issue; we should retry, but this API leaves this to the application */ break; default: /* unexpected response code */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + dcr.hr.ec = TALER_JSON_get_error_code (json); + dcr.hr.hint = TALER_JSON_get_error_hint (json); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d for auditor deposit confirmation\n", (unsigned int) response_code, - hr.ec); + dcr.hr.ec); break; } dh->cb (dh->cb_cls, - &hr); + &dcr); TALER_AUDITOR_deposit_confirmation_cancel (dh); } @@ -237,7 +233,8 @@ verify_signatures (const struct TALER_MerchantWireHashP *h_wire, struct TALER_AUDITOR_DepositConfirmationHandle * TALER_AUDITOR_deposit_confirmation ( - struct TALER_AUDITOR_Handle *auditor, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_MerchantWireHashP *h_wire, const struct TALER_ExtensionPolicyHashP *h_policy, const struct TALER_PrivateContractHashP *h_contract_terms, @@ -258,12 +255,9 @@ TALER_AUDITOR_deposit_confirmation ( void *cb_cls) { struct TALER_AUDITOR_DepositConfirmationHandle *dh; - struct GNUNET_CURL_Context *ctx; json_t *deposit_confirmation_obj; CURL *eh; - GNUNET_assert (GNUNET_YES == - TALER_AUDITOR_handle_is_ready_ (auditor)); if (GNUNET_OK != verify_signatures (h_wire, h_policy, @@ -322,18 +316,17 @@ TALER_AUDITOR_deposit_confirmation ( GNUNET_JSON_pack_data_auto ("exchange_pub", exchange_pub)); dh = GNUNET_new (struct TALER_AUDITOR_DepositConfirmationHandle); - dh->auditor = auditor; dh->cb = cb; dh->cb_cls = cb_cls; - dh->url = TALER_AUDITOR_path_to_url_ (auditor, - "/deposit-confirmation"); + dh->url = TALER_url_join (url, + "deposit-confirmation", + NULL); if (NULL == dh->url) { GNUNET_free (dh); return NULL; } eh = TALER_AUDITOR_curl_easy_get_ (dh->url); - if ( (NULL == eh) || (CURLE_OK != curl_easy_setopt (eh, @@ -356,7 +349,6 @@ TALER_AUDITOR_deposit_confirmation ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for deposit-confirmation: `%s'\n", dh->url); - ctx = TALER_AUDITOR_handle_to_context_ (auditor); dh->job = GNUNET_CURL_job_add2 (ctx, eh, dh->ctx.headers, diff --git a/src/lib/auditor_api_exchanges.c b/src/lib/auditor_api_exchanges.c index 7327f11b2..897dfe60f 100644 --- a/src/lib/auditor_api_exchanges.c +++ b/src/lib/auditor_api_exchanges.c @@ -27,7 +27,8 @@ #include <gnunet/gnunet_curl_lib.h> #include "taler_json_lib.h" #include "taler_auditor_service.h" -#include "auditor_api_handle.h" +#include "taler_util.h" +#include "taler_curl_lib.h" #include "taler_signatures.h" #include "auditor_api_curl_defaults.h" @@ -45,11 +46,6 @@ struct TALER_AUDITOR_ListExchangesHandle { /** - * The connection to auditor this request handle will use - */ - struct TALER_AUDITOR_Handle *auditor; - - /** * The url for this request. */ char *url; @@ -89,16 +85,16 @@ handle_exchanges_finished (void *cls, const json_t *ja; unsigned int ja_len; struct TALER_AUDITOR_ListExchangesHandle *leh = cls; - struct TALER_AUDITOR_HttpResponse hr = { - .reply = json, - .http_status = (unsigned int) response_code + struct TALER_AUDITOR_ListExchangesResponse ler = { + .hr.reply = json, + .hr.http_status = (unsigned int) response_code }; leh->job = NULL; switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + ler.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: ja = json_object_get (json, @@ -107,8 +103,8 @@ handle_exchanges_finished (void *cls, (! json_is_array (ja)) ) { GNUNET_break (0); - hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - hr.http_status = 0; + ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + ler.hr.http_status = 0; break; } @@ -116,20 +112,21 @@ handle_exchanges_finished (void *cls, if (ja_len > MAX_EXCHANGES) { GNUNET_break (0); - hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - hr.http_status = 0; + ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + ler.hr.http_status = 0; break; } { - struct TALER_AUDITOR_ExchangeInfo ei[ja_len]; - bool ok; + struct TALER_AUDITOR_ExchangeInfo ei[GNUNET_NZL (ja_len)]; + bool ok = true; - ok = true; for (unsigned int i = 0; i<ja_len; i++) { struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("master_pub", &ei[i].master_pub), - GNUNET_JSON_spec_string ("exchange_url", &ei[i].exchange_url), + GNUNET_JSON_spec_fixed_auto ("master_pub", + &ei[i].master_pub), + GNUNET_JSON_spec_string ("exchange_url", + &ei[i].exchange_url), GNUNET_JSON_spec_end () }; @@ -141,76 +138,71 @@ handle_exchanges_finished (void *cls, { GNUNET_break_op (0); ok = false; - hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - hr.http_status = 0; + ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + ler.hr.http_status = 0; break; } } if (! ok) break; + ler.details.ok.ei = ei; + ler.details.ok.num_exchanges = ja_len; leh->cb (leh->cb_cls, - &hr, - ja_len, - ei); + &ler); TALER_AUDITOR_list_exchanges_cancel (leh); return; } case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the auditor is buggy (or API version conflict); just pass JSON reply to the application */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ler.hr.ec = TALER_JSON_get_error_code (json); + ler.hr.hint = TALER_JSON_get_error_hint (json); break; case MHD_HTTP_NOT_FOUND: /* Nothing really to verify, this should never happen, we should pass the JSON reply to the application */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ler.hr.ec = TALER_JSON_get_error_code (json); + ler.hr.hint = TALER_JSON_get_error_hint (json); break; case MHD_HTTP_INTERNAL_SERVER_ERROR: /* Server had an internal issue; we should retry, but this API leaves this to the application */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ler.hr.ec = TALER_JSON_get_error_code (json); + ler.hr.hint = TALER_JSON_get_error_hint (json); break; default: /* unexpected response code */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ler.hr.ec = TALER_JSON_get_error_code (json); + ler.hr.hint = TALER_JSON_get_error_hint (json); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d for auditor list-exchanges request\n", (unsigned int) response_code, - (int) hr.ec); + (int) ler.hr.ec); GNUNET_break_op (0); break; } if (NULL != leh->cb) leh->cb (leh->cb_cls, - &hr, - 0, - NULL); + &ler); TALER_AUDITOR_list_exchanges_cancel (leh); } struct TALER_AUDITOR_ListExchangesHandle * -TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor, +TALER_AUDITOR_list_exchanges (struct GNUNET_CURL_Context *ctx, + const char *url, TALER_AUDITOR_ListExchangesResultCallback cb, void *cb_cls) { struct TALER_AUDITOR_ListExchangesHandle *leh; - struct GNUNET_CURL_Context *ctx; CURL *eh; - GNUNET_assert (GNUNET_YES == - TALER_AUDITOR_handle_is_ready_ (auditor)); - leh = GNUNET_new (struct TALER_AUDITOR_ListExchangesHandle); - leh->auditor = auditor; leh->cb = cb; leh->cb_cls = cb_cls; - leh->url = TALER_AUDITOR_path_to_url_ (auditor, - "/exchanges"); + leh->url = TALER_url_join (url, + "exchanges", + NULL); if (NULL == leh->url) { GNUNET_free (leh); @@ -227,7 +219,6 @@ TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor, GNUNET_free (leh); return NULL; } - ctx = TALER_AUDITOR_handle_to_context_ (auditor); leh->job = GNUNET_CURL_job_add (ctx, eh, &handle_exchanges_finished, diff --git a/src/lib/auditor_api_get_config.c b/src/lib/auditor_api_get_config.c new file mode 100644 index 000000000..ede702a0d --- /dev/null +++ b/src/lib/auditor_api_get_config.c @@ -0,0 +1,288 @@ +/* + This file is part of TALER + Copyright (C) 2014-2023 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/auditor_api_get_config.c + * @brief Implementation of /config for the auditor's HTTP API + * @author Sree Harsha Totakura <sreeharsha@totakura.in> + * @author Christian Grothoff + */ +#include "platform.h" +#include <microhttpd.h> +#include <gnunet/gnunet_curl_lib.h> +#include "taler_json_lib.h" +#include "taler_auditor_service.h" +#include "taler_signatures.h" +#include "auditor_api_curl_defaults.h" + + +/** + * Which revision of the Taler auditor protocol is implemented + * by this library? Used to determine compatibility. + */ +#define TALER_PROTOCOL_CURRENT 0 + +/** + * How many revisions back are we compatible to? + */ +#define TALER_PROTOCOL_AGE 0 + + +/** + * Log error related to CURL operations. + * + * @param type log level + * @param function which function failed to run + * @param code what was the curl error code + */ +#define CURL_STRERROR(type, function, code) \ + GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \ + function, __FILE__, __LINE__, curl_easy_strerror (code)); + + +/** + * Handle for the get config request. + */ +struct TALER_AUDITOR_GetConfigHandle +{ + /** + * The context of this handle + */ + struct GNUNET_CURL_Context *ctx; + + /** + * Function to call with the auditor's certification data, + * NULL if this has already been done. + */ + TALER_AUDITOR_ConfigCallback config_cb; + + /** + * Closure to pass to @e config_cb. + */ + void *config_cb_cls; + + /** + * Data for the request to get the /config of a auditor, + * NULL once we are past stage #MHS_INIT. + */ + struct GNUNET_CURL_Job *vr; + + /** + * The url for the @e vr job. + */ + char *vr_url; + +}; + + +/* ***************** Internal /config fetching ************* */ + +/** + * Decode the JSON in @a resp_obj from the /config response and store the data + * in the @a key_data. + * + * @param[in] resp_obj JSON object to parse + * @param[in,out] auditor where to store the results we decoded + * @param[out] vc where to store config compatibility data + * @return #TALER_EC_NONE on success + */ +static enum TALER_ErrorCode +decode_config_json (const json_t *resp_obj, + struct TALER_AUDITOR_ConfigInformation *vi, + enum TALER_AUDITOR_VersionCompatibility *vc) +{ + unsigned int age; + unsigned int revision; + unsigned int current; + char dummy; + const char *ver; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("version", + &ver), + GNUNET_JSON_spec_fixed_auto ("auditor_public_key", + &vi->auditor_pub), + GNUNET_JSON_spec_end () + }; + + if (JSON_OBJECT != json_typeof (resp_obj)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + /* check the config */ + if (GNUNET_OK != + GNUNET_JSON_parse (resp_obj, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + if (3 != sscanf (ver, + "%u:%u:%u%c", + ¤t, + &revision, + &age, + &dummy)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_VERSION_MALFORMED; + } + vi->version = ver; + *vc = TALER_AUDITOR_VC_MATCH; + if (TALER_PROTOCOL_CURRENT < current) + { + *vc |= TALER_AUDITOR_VC_NEWER; + if (TALER_PROTOCOL_CURRENT < current - age) + *vc |= TALER_AUDITOR_VC_INCOMPATIBLE; + } + if (TALER_PROTOCOL_CURRENT > current) + { + *vc |= TALER_AUDITOR_VC_OLDER; + if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current) + *vc |= TALER_AUDITOR_VC_INCOMPATIBLE; + } + return TALER_EC_NONE; +} + + +/** + * Callback used when downloading the reply to a /config request + * is complete. + * + * @param cls the `struct TALER_AUDITOR_GetConfigHandle` + * @param response_code HTTP response code, 0 on error + * @param gresp_obj parsed JSON result, NULL on error, must be a `const json_t *` + */ +static void +config_completed_cb (void *cls, + long response_code, + const void *gresp_obj) +{ + struct TALER_AUDITOR_GetConfigHandle *auditor = cls; + const json_t *resp_obj = gresp_obj; + struct TALER_AUDITOR_ConfigResponse vr = { + .hr.reply = resp_obj, + .hr.http_status = (unsigned int) response_code + }; + + auditor->vr = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received config from URL `%s' with status %ld.\n", + auditor->vr_url, + response_code); + switch (response_code) + { + case 0: + GNUNET_break_op (0); + vr.hr.ec = TALER_EC_INVALID; + break; + case MHD_HTTP_OK: + if (NULL == resp_obj) + { + GNUNET_break_op (0); + vr.hr.http_status = 0; + vr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + vr.hr.ec = decode_config_json (resp_obj, + &vr.details.ok.vi, + &vr.details.ok.compat); + if (TALER_EC_NONE != vr.hr.ec) + { + GNUNET_break_op (0); + vr.hr.http_status = 0; + break; + } + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + vr.hr.ec = TALER_JSON_get_error_code (resp_obj); + vr.hr.hint = TALER_JSON_get_error_hint (resp_obj); + break; + default: + vr.hr.ec = TALER_JSON_get_error_code (resp_obj); + vr.hr.hint = TALER_JSON_get_error_hint (resp_obj); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u/%d\n", + (unsigned int) response_code, + (int) vr.hr.ec); + break; + } + auditor->config_cb (auditor->config_cb_cls, + &vr); + TALER_AUDITOR_get_config_cancel (auditor); +} + + +struct TALER_AUDITOR_GetConfigHandle * +TALER_AUDITOR_get_config (struct GNUNET_CURL_Context *ctx, + const char *url, + TALER_AUDITOR_ConfigCallback config_cb, + void *config_cb_cls) +{ + struct TALER_AUDITOR_GetConfigHandle *auditor; + CURL *eh; + + auditor = GNUNET_new (struct TALER_AUDITOR_GetConfigHandle); + auditor->config_cb = config_cb; + auditor->config_cb_cls = config_cb_cls; + auditor->ctx = ctx; + auditor->vr_url = TALER_url_join (url, + "config", + NULL); + if (NULL == auditor->vr_url) + { + GNUNET_break (0); + GNUNET_free (auditor->vr_url); + GNUNET_free (auditor); + return NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Requesting auditor config with URL `%s'.\n", + auditor->vr_url); + eh = TALER_AUDITOR_curl_easy_get_ (auditor->vr_url); + if (NULL == eh) + { + GNUNET_break (0); + TALER_AUDITOR_get_config_cancel (auditor); + return NULL; + } + GNUNET_break (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_TIMEOUT, + (long) 300)); + auditor->vr = GNUNET_CURL_job_add (auditor->ctx, + eh, + &config_completed_cb, + auditor); + return auditor; +} + + +void +TALER_AUDITOR_get_config_cancel (struct TALER_AUDITOR_GetConfigHandle *auditor) +{ + if (NULL != auditor->vr) + { + GNUNET_CURL_job_cancel (auditor->vr); + auditor->vr = NULL; + } + GNUNET_free (auditor->vr_url); + GNUNET_free (auditor); +} + + +/* end of auditor_api_get_config.c */ diff --git a/src/lib/auditor_api_handle.c b/src/lib/auditor_api_handle.c deleted file mode 100644 index 14869de43..000000000 --- a/src/lib/auditor_api_handle.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - <http://www.gnu.org/licenses/> -*/ -/** - * @file lib/auditor_api_handle.c - * @brief Implementation of the "handle" component of the auditor's HTTP API - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - * @author Christian Grothoff - */ -#include "platform.h" -#include <microhttpd.h> -#include <gnunet/gnunet_curl_lib.h> -#include "taler_json_lib.h" -#include "taler_auditor_service.h" -#include "taler_signatures.h" -#include "auditor_api_handle.h" -#include "auditor_api_curl_defaults.h" -#include "backoff.h" - -/** - * Which revision of the Taler auditor protocol is implemented - * by this library? Used to determine compatibility. - */ -#define TALER_PROTOCOL_CURRENT 0 - -/** - * How many revisions back are we compatible to? - */ -#define TALER_PROTOCOL_AGE 0 - - -/** - * Log error related to CURL operations. - * - * @param type log level - * @param function which function failed to run - * @param code what was the curl error code - */ -#define CURL_STRERROR(type, function, code) \ - GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \ - function, __FILE__, __LINE__, curl_easy_strerror (code)); - -/** - * Stages of initialization for the `struct TALER_AUDITOR_Handle` - */ -enum AuditorHandleState -{ - /** - * Just allocated. - */ - MHS_INIT = 0, - - /** - * Obtained the auditor's versioning data and version. - */ - MHS_VERSION = 1, - - /** - * Failed to initialize (fatal). - */ - MHS_FAILED = 2 -}; - - -/** - * Handle to the auditor - */ -struct TALER_AUDITOR_Handle -{ - /** - * The context of this handle - */ - struct GNUNET_CURL_Context *ctx; - - /** - * The URL of the auditor (i.e. "http://auditor.taler.net/") - */ - char *url; - - /** - * Function to call with the auditor's certification data, - * NULL if this has already been done. - */ - TALER_AUDITOR_VersionCallback version_cb; - - /** - * Closure to pass to @e version_cb. - */ - void *version_cb_cls; - - /** - * Data for the request to get the /config of a auditor, - * NULL once we are past stage #MHS_INIT. - */ - struct GNUNET_CURL_Job *vr; - - /** - * The url for the @e vr job. - */ - char *vr_url; - - /** - * Task for retrying /config request. - */ - struct GNUNET_SCHEDULER_Task *retry_task; - - /** - * /config data of the auditor, only valid if - * @e handshake_complete is past stage #MHS_VERSION. - */ - char *version; - - /** - * Version information for the callback. - */ - struct TALER_AUDITOR_VersionInformation vi; - - /** - * Retry /config frequency. - */ - struct GNUNET_TIME_Relative retry_delay; - - /** - * Stage of the auditor's initialization routines. - */ - enum AuditorHandleState state; - -}; - - -/* ***************** Internal /config fetching ************* */ - -/** - * Decode the JSON in @a resp_obj from the /config response and store the data - * in the @a key_data. - * - * @param[in] resp_obj JSON object to parse - * @param[in,out] auditor where to store the results we decoded - * @param[out] vc where to store version compatibility data - * @return #TALER_EC_NONE on success - */ -static enum TALER_ErrorCode -decode_version_json (const json_t *resp_obj, - struct TALER_AUDITOR_Handle *auditor, - enum TALER_AUDITOR_VersionCompatibility *vc) -{ - struct TALER_AUDITOR_VersionInformation *vi = &auditor->vi; - unsigned int age; - unsigned int revision; - unsigned int current; - char dummy; - const char *ver; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("version", - &ver), - GNUNET_JSON_spec_fixed_auto ("auditor_public_key", - &vi->auditor_pub), - GNUNET_JSON_spec_end () - }; - - if (JSON_OBJECT != json_typeof (resp_obj)) - { - GNUNET_break_op (0); - return TALER_EC_GENERIC_JSON_INVALID; - } - /* check the version */ - if (GNUNET_OK != - GNUNET_JSON_parse (resp_obj, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return TALER_EC_GENERIC_JSON_INVALID; - } - if (3 != sscanf (ver, - "%u:%u:%u%c", - ¤t, - &revision, - &age, - &dummy)) - { - GNUNET_break_op (0); - return TALER_EC_GENERIC_VERSION_MALFORMED; - } - GNUNET_free (auditor->version); - auditor->version = GNUNET_strdup (ver); - vi->version = auditor->version; - *vc = TALER_AUDITOR_VC_MATCH; - if (TALER_PROTOCOL_CURRENT < current) - { - *vc |= TALER_AUDITOR_VC_NEWER; - if (TALER_PROTOCOL_CURRENT < current - age) - *vc |= TALER_AUDITOR_VC_INCOMPATIBLE; - } - if (TALER_PROTOCOL_CURRENT > current) - { - *vc |= TALER_AUDITOR_VC_OLDER; - if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current) - *vc |= TALER_AUDITOR_VC_INCOMPATIBLE; - } - return TALER_EC_NONE; -} - - -/** - * Initiate download of /config from the auditor. - * - * @param cls auditor where to download /config from - */ -static void -request_version (void *cls); - - -/** - * Callback used when downloading the reply to a /config request - * is complete. - * - * @param cls the `struct TALER_AUDITOR_Handle` - * @param response_code HTTP response code, 0 on error - * @param gresp_obj parsed JSON result, NULL on error, must be a `const json_t *` - */ -static void -version_completed_cb (void *cls, - long response_code, - const void *gresp_obj) -{ - struct TALER_AUDITOR_Handle *auditor = cls; - const json_t *resp_obj = gresp_obj; - enum TALER_AUDITOR_VersionCompatibility vc; - struct TALER_AUDITOR_HttpResponse hr = { - .reply = resp_obj, - .http_status = (unsigned int) response_code - }; - - auditor->vr = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received version from URL `%s' with status %ld.\n", - auditor->url, - response_code); - vc = TALER_AUDITOR_VC_PROTOCOL_ERROR; - switch (response_code) - { - case 0: - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* NOTE: this design is debatable. We MAY want to throw this error at the - client. We may then still additionally internally re-try. */ - GNUNET_assert (NULL == auditor->retry_task); - auditor->retry_delay = EXCHANGE_LIB_BACKOFF (auditor->retry_delay); - auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay, - &request_version, - auditor); - return; - case MHD_HTTP_OK: - if (NULL == resp_obj) - { - GNUNET_break_op (0); - TALER_LOG_WARNING ("NULL body for a 200-OK /config\n"); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } - hr.ec = decode_version_json (resp_obj, - auditor, - &vc); - if (TALER_EC_NONE != hr.ec) - { - GNUNET_break_op (0); - hr.http_status = 0; - break; - } - auditor->retry_delay = GNUNET_TIME_UNIT_ZERO; /* restart quickly */ - break; - default: - hr.ec = TALER_JSON_get_error_code (resp_obj); - hr.hint = TALER_JSON_get_error_hint (resp_obj); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d\n", - (unsigned int) response_code, - (int) hr.ec); - break; - } - if (MHD_HTTP_OK != response_code) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "/config failed for auditor %s: %u!\n", - auditor->url, - (unsigned int) response_code); - auditor->state = MHS_FAILED; - /* notify application that we failed */ - auditor->version_cb (auditor->version_cb_cls, - &hr, - NULL, - vc); - return; - } - TALER_LOG_DEBUG ("Switching auditor state to 'version'\n"); - auditor->state = MHS_VERSION; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Auditor %s is ready!\n", - auditor->url); - /* notify application about the key information */ - auditor->version_cb (auditor->version_cb_cls, - &hr, - &auditor->vi, - vc); -} - - -/** - * Initiate download of /config from the auditor. - * - * @param cls auditor where to download /config from - */ -static void -request_version (void *cls) -{ - struct TALER_AUDITOR_Handle *auditor = cls; - CURL *eh; - - auditor->retry_task = NULL; - GNUNET_assert (NULL == auditor->vr); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Requesting auditor version with URL `%s'.\n", - auditor->vr_url); - eh = TALER_AUDITOR_curl_easy_get_ (auditor->vr_url); - if (NULL == eh) - { - GNUNET_break (0); - auditor->retry_delay = EXCHANGE_LIB_BACKOFF (auditor->retry_delay); - auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay, - &request_version, - auditor); - return; - } - GNUNET_break (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_TIMEOUT, - (long) 300)); - auditor->vr = GNUNET_CURL_job_add (auditor->ctx, - eh, - &version_completed_cb, - auditor); -} - - -/* ********************* library internal API ********* */ - - -struct GNUNET_CURL_Context * -TALER_AUDITOR_handle_to_context_ (struct TALER_AUDITOR_Handle *h) -{ - return h->ctx; -} - - -enum GNUNET_GenericReturnValue -TALER_AUDITOR_handle_is_ready_ (struct TALER_AUDITOR_Handle *h) -{ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Checking if auditor at `%s` is now ready: %s\n", - h->url, - (MHD_VERSION == h->state) ? "yes" : "no"); - return (MHS_VERSION == h->state) ? GNUNET_YES : GNUNET_NO; -} - - -char * -TALER_AUDITOR_path_to_url_ (struct TALER_AUDITOR_Handle *h, - const char *path) -{ - GNUNET_assert ('/' == path[0]); - return TALER_url_join (h->url, - path + 1, - NULL); -} - - -/* ********************* public API ******************* */ - - -struct TALER_AUDITOR_Handle * -TALER_AUDITOR_connect (struct GNUNET_CURL_Context *ctx, - const char *url, - TALER_AUDITOR_VersionCallback version_cb, - void *version_cb_cls) -{ - struct TALER_AUDITOR_Handle *auditor; - - auditor = GNUNET_new (struct TALER_AUDITOR_Handle); - auditor->version_cb = version_cb; - auditor->version_cb_cls = version_cb_cls; - auditor->retry_delay = GNUNET_TIME_UNIT_SECONDS; /* start slowly */ - auditor->ctx = ctx; - auditor->url = GNUNET_strdup (url); - auditor->vr_url = TALER_AUDITOR_path_to_url_ (auditor, - "/config"); - if (NULL == auditor->vr_url) - { - GNUNET_break (0); - GNUNET_free (auditor->url); - GNUNET_free (auditor); - return NULL; - } - auditor->retry_task = GNUNET_SCHEDULER_add_now (&request_version, - auditor); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Connecting to auditor at URL `%s'.\n", - url); - return auditor; -} - - -void -TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor) -{ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Disconnecting from auditor at URL `%s'.\n", - auditor->url); - if (NULL != auditor->vr) - { - GNUNET_CURL_job_cancel (auditor->vr); - auditor->vr = NULL; - } - if (NULL != auditor->retry_task) - { - GNUNET_SCHEDULER_cancel (auditor->retry_task); - auditor->retry_task = NULL; - } - GNUNET_free (auditor->version); - GNUNET_free (auditor->vr_url); - GNUNET_free (auditor->url); - GNUNET_free (auditor); -} - - -/* end of auditor_api_handle.c */ diff --git a/src/lib/auditor_api_handle.h b/src/lib/auditor_api_handle.h deleted file mode 100644 index 7ff5bfcdb..000000000 --- a/src/lib/auditor_api_handle.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - <http://www.gnu.org/licenses/> -*/ -/** - * @file lib/auditor_api_handle.h - * @brief Internal interface to the handle part of the auditor's HTTP API - * @author Christian Grothoff - */ -#include "platform.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler_auditor_service.h" -#include "taler_curl_lib.h" - -/** - * Get the context of a auditor. - * - * @param h the auditor handle to query - * @return ctx context to execute jobs in - */ -struct GNUNET_CURL_Context * -TALER_AUDITOR_handle_to_context_ (struct TALER_AUDITOR_Handle *h); - - -/** - * Check if the handle is ready to process requests. - * - * @param h the auditor handle to query - * @return #GNUNET_YES if we are ready, #GNUNET_NO if not - */ -int -TALER_AUDITOR_handle_is_ready_ (struct TALER_AUDITOR_Handle *h); - - -/** - * Obtain the URL to use for an API request. - * - * @param h the auditor handle to query - * @param path Taler API path (i.e. "/deposit-confirmation") - * @return the full URL to use with cURL - */ -char * -TALER_AUDITOR_path_to_url_ (struct TALER_AUDITOR_Handle *h, - const char *path); - - -/* end of auditor_api_handle.h */ diff --git a/src/lib/exchange_api_batch_deposit.c b/src/lib/exchange_api_batch_deposit.c index 544407a38..22ae2d58d 100644 --- a/src/lib/exchange_api_batch_deposit.c +++ b/src/lib/exchange_api_batch_deposit.c @@ -44,6 +44,39 @@ */ #define AUDITOR_CHANCE 20 + +/** + * Entry in list of ongoing interactions with an auditor. + */ +struct TEAH_AuditorInteractionEntry +{ + /** + * DLL entry. + */ + struct TEAH_AuditorInteractionEntry *next; + + /** + * DLL entry. + */ + struct TEAH_AuditorInteractionEntry *prev; + + /** + * URL of our auditor. For logging. + */ + const char *auditor_url; + + /** + * Interaction state. + */ + struct TALER_AUDITOR_DepositConfirmationHandle *dch; + + /** + * Batch deposit this is for. + */ + struct TALER_EXCHANGE_BatchDepositHandle *dh; +}; + + /** * @brief A Deposit Handle */ @@ -51,9 +84,14 @@ struct TALER_EXCHANGE_BatchDepositHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange. */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; + + /** + * Context for our curl request(s). + */ + struct GNUNET_CURL_Context *ctx; /** * The url for this request. @@ -64,7 +102,7 @@ struct TALER_EXCHANGE_BatchDepositHandle * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ - struct TALER_CURL_PostContext ctx; + struct TALER_CURL_PostContext post_ctx; /** * Handle for the request. @@ -113,11 +151,31 @@ struct TALER_EXCHANGE_BatchDepositHandle struct TALER_ExchangeSignatureP *exchange_sigs; /** + * Head of DLL of interactions with this auditor. + */ + struct TEAH_AuditorInteractionEntry *ai_head; + + /** + * Tail of DLL of interactions with this auditor. + */ + struct TEAH_AuditorInteractionEntry *ai_tail; + + /** + * Result to return to the application once @e ai_head is empty. + */ + struct TALER_EXCHANGE_BatchDepositResult dr; + + /** * Exchange signing public key, set for #auditor_cb. */ struct TALER_ExchangePublicKeyP exchange_pub; /** + * Response object to free at the end. + */ + json_t *response; + + /** * Chance that we will inform the auditor about the deposit * is 1:n, where the value of this field is "n". */ @@ -132,21 +190,65 @@ struct TALER_EXCHANGE_BatchDepositHandle /** + * Finish batch deposit operation by calling the callback. + * + * @param[in] dh handle to finished batch deposit operation + */ +static void +finish_dh (struct TALER_EXCHANGE_BatchDepositHandle *dh) +{ + dh->cb (dh->cb_cls, + &dh->dr); + TALER_EXCHANGE_batch_deposit_cancel (dh); +} + + +/** + * Function called with the result from our call to the + * auditor's /deposit-confirmation handler. + * + * @param cls closure of type `struct TEAH_AuditorInteractionEntry *` + * @param dcr response + */ +static void +acc_confirmation_cb ( + void *cls, + const struct TALER_AUDITOR_DepositConfirmationResponse *dcr) +{ + struct TEAH_AuditorInteractionEntry *aie = cls; + struct TALER_EXCHANGE_BatchDepositHandle *dh = aie->dh; + + if (MHD_HTTP_OK != dcr->hr.http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to submit deposit confirmation to auditor `%s' with HTTP status %d (EC: %d). This is acceptable if it does not happen often.\n", + aie->auditor_url, + dcr->hr.http_status, + dcr->hr.ec); + } + GNUNET_CONTAINER_DLL_remove (dh->ai_head, + dh->ai_tail, + aie); + GNUNET_free (aie); + if (NULL == dh->ai_head) + finish_dh (dh); +} + + +/** * Function called for each auditor to give us a chance to possibly * launch a deposit confirmation interaction. * * @param cls closure - * @param ah handle to the auditor + * @param auditor_url base URL of the auditor * @param auditor_pub public key of the auditor - * @return NULL if no deposit confirmation interaction was launched */ -static struct TEAH_AuditorInteractionEntry * +static void auditor_cb (void *cls, - struct TALER_AUDITOR_Handle *ah, + const char *auditor_url, const struct TALER_AuditorPublicKeyP *auditor_pub) { struct TALER_EXCHANGE_BatchDepositHandle *dh = cls; - const struct TALER_EXCHANGE_Keys *key_state; const struct TALER_EXCHANGE_SigningPublicKey *spk; struct TEAH_AuditorInteractionEntry *aie; struct TALER_Amount amount_without_fee; @@ -159,31 +261,33 @@ auditor_cb (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Not providing deposit confirmation to auditor\n"); - return NULL; + return; } coin = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, dh->num_cdds); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Will provide deposit confirmation to auditor `%s'\n", TALER_B2S (auditor_pub)); - key_state = TALER_EXCHANGE_get_keys (dh->exchange); - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, + dki = TALER_EXCHANGE_get_denomination_key_by_hash (dh->keys, &dh->cdds[coin].h_denom_pub); GNUNET_assert (NULL != dki); - spk = TALER_EXCHANGE_get_signing_key_info (key_state, + spk = TALER_EXCHANGE_get_signing_key_info (dh->keys, &dh->exchange_pub); if (NULL == spk) { GNUNET_break_op (0); - return NULL; + return; } GNUNET_assert (0 <= TALER_amount_subtract (&amount_without_fee, &dh->cdds[coin].amount, &dki->fees.deposit)); aie = GNUNET_new (struct TEAH_AuditorInteractionEntry); + aie->dh = dh; + aie->auditor_url = auditor_url; aie->dch = TALER_AUDITOR_deposit_confirmation ( - ah, + dh->ctx, + auditor_url, &dh->h_wire, &dh->h_policy, &dh->dcd.h_contract_terms, @@ -195,14 +299,16 @@ auditor_cb (void *cls, &dh->dcd.merchant_pub, &dh->exchange_pub, &dh->exchange_sigs[coin], - &key_state->master_pub, + &dh->keys->master_pub, spk->valid_from, spk->valid_until, spk->valid_legal, &spk->master_sig, - &TEAH_acc_confirmation_cb, + &acc_confirmation_cb, aie); - return aie; + GNUNET_CONTAINER_DLL_insert (dh->ai_head, + dh->ai_tail, + aie); } @@ -221,22 +327,19 @@ handle_deposit_finished (void *cls, { struct TALER_EXCHANGE_BatchDepositHandle *dh = cls; const json_t *j = response; - struct TALER_EXCHANGE_BatchDepositResult dr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - const struct TALER_EXCHANGE_Keys *keys; + struct TALER_EXCHANGE_BatchDepositResult *dr = &dh->dr; dh->job = NULL; - keys = TALER_EXCHANGE_get_keys (dh->exchange); + dh->response = json_incref ((json_t*) j); + dr->hr.reply = dh->response; + dr->hr.http_status = (unsigned int) response_code; switch (response_code) { case 0: - dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + dr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: { - const struct TALER_EXCHANGE_Keys *key_state; const json_t *sigs; json_t *sig; unsigned int idx; @@ -247,7 +350,7 @@ handle_deposit_finished (void *cls, &dh->exchange_pub), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("transaction_base_url", - &dr.details.ok.transaction_base_url), + &dr->details.ok.transaction_base_url), NULL), GNUNET_JSON_spec_timestamp ("exchange_timestamp", &dh->exchange_timestamp), @@ -260,27 +363,26 @@ handle_deposit_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } if (json_array_size (sigs) != dh->num_cdds) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } dh->exchange_sigs = GNUNET_new_array (dh->num_cdds, struct TALER_ExchangeSignatureP); - key_state = TALER_EXCHANGE_get_keys (dh->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (dh->keys, &dh->exchange_pub)) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; break; } json_array_foreach (sigs, idx, sig) @@ -299,11 +401,11 @@ handle_deposit_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, + dki = TALER_EXCHANGE_get_denomination_key_by_hash (dh->keys, &dh->cdds[idx]. h_denom_pub); GNUNET_assert (NULL != dki); @@ -327,42 +429,41 @@ handle_deposit_finished (void *cls, &dh->exchange_sigs[idx])) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; break; } } - TEAH_get_auditors_for_dc (dh->exchange, + TEAH_get_auditors_for_dc (dh->keys, &auditor_cb, dh); } - dr.details.ok.exchange_sigs = dh->exchange_sigs; - dr.details.ok.exchange_pub = &dh->exchange_pub; - dr.details.ok.deposit_timestamp = dh->exchange_timestamp; - dr.details.ok.num_signatures = dh->num_cdds; + dr->details.ok.exchange_sigs = dh->exchange_sigs; + dr->details.ok.exchange_pub = &dh->exchange_pub; + dr->details.ok.deposit_timestamp = dh->exchange_timestamp; + dr->details.ok.num_signatures = dh->num_cdds; break; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); + dr->hr.ec = TALER_JSON_get_error_code (j); + dr->hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_FORBIDDEN: - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); + dr->hr.ec = TALER_JSON_get_error_code (j); + dr->hr.hint = TALER_JSON_get_error_hint (j); /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_NOT_FOUND: - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); + dr->hr.ec = TALER_JSON_get_error_code (j); + dr->hr.hint = TALER_JSON_get_error_hint (j); /* Nothing really to verify, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_CONFLICT: { - const struct TALER_EXCHANGE_Keys *key_state; struct TALER_CoinSpendPublicKeyP coin_pub; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("coin_pub", @@ -378,8 +479,8 @@ handle_deposit_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } for (unsigned int i = 0; i<dh->num_cdds; i++) @@ -388,14 +489,13 @@ handle_deposit_finished (void *cls, GNUNET_memcmp (&coin_pub, &dh->cdds[i].coin_pub)) continue; - key_state = TALER_EXCHANGE_get_keys (dh->exchange); - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, + dki = TALER_EXCHANGE_get_denomination_key_by_hash (dh->keys, &dh->cdds[i]. h_denom_pub); GNUNET_assert (NULL != dki); if (GNUNET_OK != TALER_EXCHANGE_check_coin_conflict_ ( - keys, + dh->keys, j, dki, &dh->cdds[i].coin_pub, @@ -403,8 +503,8 @@ handle_deposit_finished (void *cls, &dh->cdds[i].amount)) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } found = true; @@ -413,12 +513,12 @@ handle_deposit_finished (void *cls, if (! found) { GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); + dr->hr.ec = TALER_JSON_get_error_code (j); + dr->hr.hint = TALER_JSON_get_error_hint (j); } break; case MHD_HTTP_GONE: @@ -426,35 +526,37 @@ handle_deposit_finished (void *cls, /* Note: one might want to check /keys for revocation signature here, alas tricky in case our /keys is outdated => left to clients */ - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); + dr->hr.ec = TALER_JSON_get_error_code (j); + dr->hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_INTERNAL_SERVER_ERROR: - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); + dr->hr.ec = TALER_JSON_get_error_code (j); + dr->hr.hint = TALER_JSON_get_error_hint (j); /* Server had an internal issue; we should retry, but this API leaves this to the application */ break; default: /* unexpected response code */ - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); + dr->hr.ec = TALER_JSON_get_error_code (j); + dr->hr.hint = TALER_JSON_get_error_hint (j); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d for exchange deposit\n", (unsigned int) response_code, - dr.hr.ec); + dr->hr.ec); GNUNET_break_op (0); break; } - dh->cb (dh->cb_cls, - &dr); - TALER_EXCHANGE_batch_deposit_cancel (dh); + if (NULL != dh->ai_head) + return; + finish_dh (dh); } struct TALER_EXCHANGE_BatchDepositHandle * TALER_EXCHANGE_batch_deposit ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DepositContractDetail *dcd, unsigned int num_cdds, const struct TALER_EXCHANGE_CoinDepositDetail *cdds, @@ -462,16 +564,12 @@ TALER_EXCHANGE_batch_deposit ( void *cb_cls, enum TALER_ErrorCode *ec) { - const struct TALER_EXCHANGE_Keys *key_state; struct TALER_EXCHANGE_BatchDepositHandle *dh; - struct GNUNET_CURL_Context *ctx; json_t *deposit_obj; json_t *deposits; CURL *eh; struct TALER_Amount amount_without_fee; - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); if (GNUNET_TIME_timestamp_cmp (dcd->refund_deadline, >, dcd->wire_deadline)) @@ -480,10 +578,8 @@ TALER_EXCHANGE_batch_deposit ( *ec = TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE; return NULL; } - key_state = TALER_EXCHANGE_get_keys (exchange); dh = GNUNET_new (struct TALER_EXCHANGE_BatchDepositHandle); dh->auditor_chance = AUDITOR_CHANCE; - dh->exchange = exchange; dh->cb = cb; dh->cb_cls = cb_cls; dh->cdds = GNUNET_memdup (cdds, @@ -504,7 +600,7 @@ TALER_EXCHANGE_batch_deposit ( const struct TALER_EXCHANGE_CoinDepositDetail *cdd = &cdds[i]; const struct TALER_EXCHANGE_DenomPublicKey *dki; - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, + dki = TALER_EXCHANGE_get_denomination_key_by_hash (keys, &cdd->h_denom_pub); if (NULL == dki) { @@ -563,8 +659,9 @@ TALER_EXCHANGE_batch_deposit ( &cdd->coin_sig) ))); } - dh->url = TEAH_path_to_url (exchange, - "/batch-deposit"); + dh->url = TALER_url_join (url, + "batch-deposit", + NULL); if (NULL == dh->url) { GNUNET_break (0); @@ -600,7 +697,7 @@ TALER_EXCHANGE_batch_deposit ( eh = TALER_EXCHANGE_curl_easy_get_ (dh->url); if ( (NULL == eh) || (GNUNET_OK != - TALER_curl_easy_post (&dh->ctx, + TALER_curl_easy_post (&dh->post_ctx, eh, deposit_obj)) ) { @@ -618,10 +715,11 @@ TALER_EXCHANGE_batch_deposit ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for deposit: `%s'\n", dh->url); - ctx = TEAH_handle_to_context (exchange); + dh->ctx = ctx; + dh->keys = TALER_EXCHANGE_keys_incref (keys); dh->job = GNUNET_CURL_job_add2 (ctx, eh, - dh->ctx.headers, + dh->post_ctx.headers, &handle_deposit_finished, dh); return dh; @@ -640,15 +738,31 @@ void TALER_EXCHANGE_batch_deposit_cancel ( struct TALER_EXCHANGE_BatchDepositHandle *deposit) { + struct TEAH_AuditorInteractionEntry *aie; + + while (NULL != (aie = deposit->ai_head)) + { + GNUNET_assert (aie->dh == deposit); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Not sending deposit confirmation to auditor `%s' due to cancellation\n", + aie->auditor_url); + TALER_AUDITOR_deposit_confirmation_cancel (aie->dch); + GNUNET_CONTAINER_DLL_remove (deposit->ai_head, + deposit->ai_tail, + aie); + GNUNET_free (aie); + } if (NULL != deposit->job) { GNUNET_CURL_job_cancel (deposit->job); deposit->job = NULL; } + TALER_EXCHANGE_keys_decref (deposit->keys); GNUNET_free (deposit->url); GNUNET_free (deposit->cdds); GNUNET_free (deposit->exchange_sigs); - TALER_curl_easy_post_finished (&deposit->ctx); + TALER_curl_easy_post_finished (&deposit->post_ctx); + json_decref (deposit->response); GNUNET_free (deposit); } diff --git a/src/lib/exchange_api_batch_withdraw2.c b/src/lib/exchange_api_batch_withdraw2.c index 04c2c0100..6dd421cea 100644 --- a/src/lib/exchange_api_batch_withdraw2.c +++ b/src/lib/exchange_api_batch_withdraw2.c @@ -218,14 +218,15 @@ reserve_batch_withdraw_payment_required ( } if (GNUNET_OK != - TALER_EXCHANGE_parse_reserve_history (wh->exchange, - history, - &wh->reserve_pub, - balance.currency, - &total_in_from_history, - &total_out_from_history, - len, - rhistory)) + TALER_EXCHANGE_parse_reserve_history ( + TALER_EXCHANGE_get_keys (wh->exchange), + history, + &wh->reserve_pub, + balance.currency, + &total_in_from_history, + &total_out_from_history, + len, + rhistory)) { GNUNET_break_op (0); TALER_EXCHANGE_free_reserve_history (rhistory, diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index 8bbc6c472..f43673d76 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -34,9 +34,9 @@ struct HistoryParseContext { /** - * Exchange we use. + * Keys of the exchange we use. */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * Our reserve public key. @@ -187,7 +187,7 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, const struct TALER_EXCHANGE_Keys *key_state; const struct TALER_EXCHANGE_DenomPublicKey *dki; - key_state = TALER_EXCHANGE_get_keys (uc->exchange); + key_state = uc->keys; dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, &h_denom_pub); if ( (GNUNET_YES != @@ -275,7 +275,7 @@ parse_recoup (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, GNUNET_break_op (0); return GNUNET_SYSERR; } - key_state = TALER_EXCHANGE_get_keys (uc->exchange); + key_state = uc->keys; if (GNUNET_OK != TALER_EXCHANGE_test_signing_key (key_state, &rh->details. @@ -349,7 +349,7 @@ parse_closing (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, GNUNET_break_op (0); return GNUNET_SYSERR; } - key_state = TALER_EXCHANGE_get_keys (uc->exchange); + key_state = uc->keys; if (GNUNET_OK != TALER_EXCHANGE_test_signing_key ( key_state, @@ -647,7 +647,7 @@ parse_close (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, enum GNUNET_GenericReturnValue TALER_EXCHANGE_parse_reserve_history ( - struct TALER_EXCHANGE_Handle *exchange, + struct TALER_EXCHANGE_Keys *keys, const json_t *history, const struct TALER_ReservePublicKeyP *reserve_pub, const char *currency, @@ -673,7 +673,7 @@ TALER_EXCHANGE_parse_reserve_history ( }; struct GNUNET_HashCode uuid[history_length]; struct HistoryParseContext uc = { - .exchange = exchange, + .keys = keys, .reserve_pub = reserve_pub, .uuids = uuid, .total_in = total_in, diff --git a/src/lib/exchange_api_contracts_get.c b/src/lib/exchange_api_contracts_get.c index 8fd4ba1e7..aece7733a 100644 --- a/src/lib/exchange_api_contracts_get.c +++ b/src/lib/exchange_api_contracts_get.c @@ -39,11 +39,6 @@ struct TALER_EXCHANGE_ContractsGetHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -194,7 +189,8 @@ handle_contract_get_finished (void *cls, struct TALER_EXCHANGE_ContractsGetHandle * TALER_EXCHANGE_contract_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ContractDiffiePrivateP *contract_priv, TALER_EXCHANGE_ContractGetCallback cb, void *cb_cls) @@ -203,14 +199,7 @@ TALER_EXCHANGE_contract_get ( CURL *eh; char arg_str[sizeof (cgh->cpub) * 2 + 48]; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } cgh = GNUNET_new (struct TALER_EXCHANGE_ContractsGetHandle); - cgh->exchange = exchange; cgh->cb = cb; cgh->cb_cls = cb_cls; GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv, @@ -226,12 +215,13 @@ TALER_EXCHANGE_contract_get ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/contracts/%s", + "contracts/%s", cpub_str); } - cgh->url = TEAH_path_to_url (exchange, - arg_str); + cgh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == cgh->url) { GNUNET_free (cgh); @@ -247,7 +237,7 @@ TALER_EXCHANGE_contract_get ( GNUNET_free (cgh); return NULL; } - cgh->job = GNUNET_CURL_job_add (TEAH_handle_to_context (exchange), + cgh->job = GNUNET_CURL_job_add (ctx, eh, &handle_contract_get_finished, cgh); diff --git a/src/lib/exchange_api_csr_melt.c b/src/lib/exchange_api_csr_melt.c index 67b1a9b7e..da6c392aa 100644 --- a/src/lib/exchange_api_csr_melt.c +++ b/src/lib/exchange_api_csr_melt.c @@ -38,10 +38,6 @@ */ struct TALER_EXCHANGE_CsRMeltHandle { - /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; /** * Function to call with the result. @@ -220,12 +216,14 @@ handle_csr_finished (void *cls, struct TALER_EXCHANGE_CsRMeltHandle * -TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_RefreshMasterSecretP *rms, - unsigned int nks_len, - struct TALER_EXCHANGE_NonceKey *nks, - TALER_EXCHANGE_CsRMeltCallback res_cb, - void *res_cb_cls) +TALER_EXCHANGE_csr_melt ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_RefreshMasterSecretP *rms, + unsigned int nks_len, + struct TALER_EXCHANGE_NonceKey *nks, + TALER_EXCHANGE_CsRMeltCallback res_cb, + void *res_cb_cls) { struct TALER_EXCHANGE_CsRMeltHandle *csrh; json_t *csr_arr; @@ -242,7 +240,6 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange, return NULL; } csrh = GNUNET_new (struct TALER_EXCHANGE_CsRMeltHandle); - csrh->exchange = exchange; csrh->cb = res_cb; csrh->cb_cls = res_cb_cls; csr_arr = json_array (); @@ -262,8 +259,9 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange, json_array_append_new (csr_arr, csr_obj)); } - csrh->url = TEAH_path_to_url (exchange, - "/csr-melt"); + csrh->url = TALER_url_join (url, + "csr-melt", + NULL); if (NULL == csrh->url) { json_decref (csr_arr); @@ -272,7 +270,6 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange, } { CURL *eh; - struct GNUNET_CURL_Context *ctx; json_t *req; req = GNUNET_JSON_PACK ( @@ -280,7 +277,6 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange, rms), GNUNET_JSON_pack_array_steal ("nks", csr_arr)); - ctx = TEAH_handle_to_context (exchange); eh = TALER_EXCHANGE_curl_easy_get_ (csrh->url); if ( (NULL == eh) || (GNUNET_OK != diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c deleted file mode 100644 index 5a0073f3f..000000000 --- a/src/lib/exchange_api_deposit.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - <http://www.gnu.org/licenses/> - */ -/** - * @file lib/exchange_api_deposit.c - * @brief Implementation of the /deposit request of the exchange's HTTP API - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - * @author Christian Grothoff - */ -#include "platform.h" -#include <jansson.h> -#include <microhttpd.h> /* just for HTTP status codes */ -#include <gnunet/gnunet_util_lib.h> -#include <gnunet/gnunet_json_lib.h> -#include <gnunet/gnunet_curl_lib.h> -#include "taler_json_lib.h" -#include "taler_auditor_service.h" -#include "taler_exchange_service.h" -#include "exchange_api_common.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * 1:#AUDITOR_CHANCE is the probability that we report deposits - * to the auditor. - * - * 20==5% of going to auditor. This is possibly still too high, but set - * deliberately this high for testing - */ -#define AUDITOR_CHANCE 20 - -/** - * @brief A Deposit Handle - */ -struct TALER_EXCHANGE_DepositHandle -{ - - /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** - * The url for this request. - */ - char *url; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_DepositResultCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Details about the contract. - */ - struct TALER_EXCHANGE_DepositContractDetail dcd; - - /** - * Details about the coin. - */ - struct TALER_EXCHANGE_CoinDepositDetail cdd; - - /** - * Hash of the merchant's wire details. - */ - struct TALER_MerchantWireHashP h_wire; - - /** - * Hash over the policy extension, or all zero. - */ - struct TALER_ExtensionPolicyHashP h_policy; - - /** - * Time when this confirmation was generated / when the exchange received - * the deposit request. - */ - struct GNUNET_TIME_Timestamp exchange_timestamp; - - /** - * Exchange signature, set for #auditor_cb. - */ - struct TALER_ExchangeSignatureP exchange_sig; - - /** - * Exchange signing public key, set for #auditor_cb. - */ - struct TALER_ExchangePublicKeyP exchange_pub; - - /** - * Chance that we will inform the auditor about the deposit - * is 1:n, where the value of this field is "n". - */ - unsigned int auditor_chance; - -}; - - -/** - * Function called for each auditor to give us a chance to possibly - * launch a deposit confirmation interaction. - * - * @param cls closure - * @param ah handle to the auditor - * @param auditor_pub public key of the auditor - * @return NULL if no deposit confirmation interaction was launched - */ -static struct TEAH_AuditorInteractionEntry * -auditor_cb (void *cls, - struct TALER_AUDITOR_Handle *ah, - const struct TALER_AuditorPublicKeyP *auditor_pub) -{ - struct TALER_EXCHANGE_DepositHandle *dh = cls; - const struct TALER_EXCHANGE_Keys *key_state; - const struct TALER_EXCHANGE_SigningPublicKey *spk; - struct TEAH_AuditorInteractionEntry *aie; - struct TALER_Amount amount_without_fee; - const struct TALER_EXCHANGE_DenomPublicKey *dki; - - if (0 != - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, - dh->auditor_chance)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Not providing deposit confirmation to auditor\n"); - return NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Will provide deposit confirmation to auditor `%s'\n", - TALER_B2S (auditor_pub)); - key_state = TALER_EXCHANGE_get_keys (dh->exchange); - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, - &dh->cdd.h_denom_pub); - GNUNET_assert (NULL != dki); - spk = TALER_EXCHANGE_get_signing_key_info (key_state, - &dh->exchange_pub); - if (NULL == spk) - { - GNUNET_break_op (0); - return NULL; - } - GNUNET_assert (0 <= - TALER_amount_subtract (&amount_without_fee, - &dh->cdd.amount, - &dki->fees.deposit)); - aie = GNUNET_new (struct TEAH_AuditorInteractionEntry); - aie->dch = TALER_AUDITOR_deposit_confirmation ( - ah, - &dh->h_wire, - &dh->h_policy, - &dh->dcd.h_contract_terms, - dh->exchange_timestamp, - dh->dcd.wire_deadline, - dh->dcd.refund_deadline, - &amount_without_fee, - &dh->cdd.coin_pub, - &dh->dcd.merchant_pub, - &dh->exchange_pub, - &dh->exchange_sig, - &key_state->master_pub, - spk->valid_from, - spk->valid_until, - spk->valid_legal, - &spk->master_sig, - &TEAH_acc_confirmation_cb, - aie); - return aie; -} - - -/** - * Function called when we're done processing the - * HTTP /deposit request. - * - * @param cls the `struct TALER_EXCHANGE_DepositHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_deposit_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_DepositHandle *dh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_DepositResult dr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - const struct TALER_EXCHANGE_Keys *keys; - - dh->job = NULL; - keys = TALER_EXCHANGE_get_keys (dh->exchange); - switch (response_code) - { - case 0: - dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - { - const struct TALER_EXCHANGE_Keys *key_state; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("exchange_sig", - &dh->exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", - &dh->exchange_pub), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("transaction_base_url", - &dr.details.ok.transaction_base_url), - NULL), - GNUNET_JSON_spec_timestamp ("exchange_timestamp", - &dh->exchange_timestamp), - GNUNET_JSON_spec_end () - }; - struct TALER_Amount amount_without_fee; - const struct TALER_EXCHANGE_DenomPublicKey *dki; - - if (GNUNET_OK != - GNUNET_JSON_parse (j, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - key_state = TALER_EXCHANGE_get_keys (dh->exchange); - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, - &dh->cdd.h_denom_pub); - GNUNET_assert (NULL != dki); - if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, - &dh->exchange_pub)) - { - GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; - break; - } - GNUNET_assert (0 <= - TALER_amount_subtract (&amount_without_fee, - &dh->cdd.amount, - &dki->fees.deposit)); - - if (GNUNET_OK != - TALER_exchange_online_deposit_confirmation_verify ( - &dh->dcd.h_contract_terms, - &dh->h_wire, - &dh->h_policy, - dh->exchange_timestamp, - dh->dcd.wire_deadline, - dh->dcd.refund_deadline, - &amount_without_fee, - &dh->cdd.coin_pub, - &dh->dcd.merchant_pub, - &dh->exchange_pub, - &dh->exchange_sig)) - { - GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; - break; - } - - TEAH_get_auditors_for_dc (dh->exchange, - &auditor_cb, - dh); - } - dr.details.ok.exchange_sig = &dh->exchange_sig; - dr.details.ok.exchange_pub = &dh->exchange_pub; - dr.details.ok.deposit_timestamp = dh->exchange_timestamp; - break; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_FORBIDDEN: - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); - /* Nothing really to verify, exchange says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_NOT_FOUND: - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - break; - case MHD_HTTP_CONFLICT: - { - const struct TALER_EXCHANGE_Keys *key_state; - const struct TALER_EXCHANGE_DenomPublicKey *dki; - - key_state = TALER_EXCHANGE_get_keys (dh->exchange); - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, - &dh->cdd.h_denom_pub); - GNUNET_assert (NULL != dki); - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); - if (GNUNET_OK != - TALER_EXCHANGE_check_coin_conflict_ ( - keys, - j, - dki, - &dh->cdd.coin_pub, - &dh->cdd.coin_sig, - &dh->cdd.amount)) - { - GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - } - break; - case MHD_HTTP_GONE: - /* could happen if denomination was revoked */ - /* Note: one might want to check /keys for revocation - signature here, alas tricky in case our /keys - is outdated => left to clients */ - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - dr.hr.ec = TALER_JSON_get_error_code (j); - dr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange deposit\n", - (unsigned int) response_code, - dr.hr.ec); - GNUNET_break_op (0); - break; - } - dh->cb (dh->cb_cls, - &dr); - TALER_EXCHANGE_deposit_cancel (dh); -} - - -struct TALER_EXCHANGE_DepositHandle * -TALER_EXCHANGE_deposit ( - struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_EXCHANGE_DepositContractDetail *dcd, - const struct TALER_EXCHANGE_CoinDepositDetail *cdd, - TALER_EXCHANGE_DepositResultCallback cb, - void *cb_cls, - enum TALER_ErrorCode *ec) -{ - const struct TALER_EXCHANGE_Keys *key_state; - struct TALER_EXCHANGE_DepositHandle *dh; - struct GNUNET_CURL_Context *ctx; - json_t *deposit_obj; - CURL *eh; - const struct TALER_EXCHANGE_DenomPublicKey *dki; - struct TALER_Amount amount_without_fee; - char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); - if (GNUNET_TIME_timestamp_cmp (dcd->refund_deadline, - >, - dcd->wire_deadline)) - { - GNUNET_break_op (0); - *ec = TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE; - return NULL; - } - { - char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &cdd->coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "/coins/%s/deposit", - pub_str); - } - key_state = TALER_EXCHANGE_get_keys (exchange); - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, - &cdd->h_denom_pub); - if (NULL == dki) - { - *ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; - GNUNET_break_op (0); - return NULL; - } - if (0 > - TALER_amount_subtract (&amount_without_fee, - &cdd->amount, - &dki->fees.deposit)) - { - *ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT; - GNUNET_break_op (0); - return NULL; - } - dh = GNUNET_new (struct TALER_EXCHANGE_DepositHandle); - dh->auditor_chance = AUDITOR_CHANCE; - dh->exchange = exchange; - dh->cb = cb; - dh->cb_cls = cb_cls; - dh->cdd = *cdd; - dh->dcd = *dcd; - if (NULL != dcd->policy_details) - TALER_deposit_policy_hash (dcd->policy_details, - &dh->h_policy); - TALER_merchant_wire_signature_hash (dcd->merchant_payto_uri, - &dcd->wire_salt, - &dh->h_wire); - if (GNUNET_OK != - TALER_EXCHANGE_verify_deposit_signature_ (dcd, - &dh->h_policy, - &dh->h_wire, - cdd, - dki)) - { - *ec = TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID; - GNUNET_break_op (0); - GNUNET_free (dh); - return NULL; - } - dh->url = TEAH_path_to_url (exchange, - arg_str); - if (NULL == dh->url) - { - GNUNET_break (0); - *ec = TALER_EC_GENERIC_ALLOCATION_FAILURE; - GNUNET_free (dh->url); - GNUNET_free (dh); - return NULL; - } - - deposit_obj = GNUNET_JSON_PACK ( - TALER_JSON_pack_amount ("contribution", - &cdd->amount), - GNUNET_JSON_pack_string ("merchant_payto_uri", - dcd->merchant_payto_uri), - GNUNET_JSON_pack_data_auto ("wire_salt", - &dcd->wire_salt), - GNUNET_JSON_pack_data_auto ("h_contract_terms", - &dcd->h_contract_terms), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_data_auto ("h_age_commitment", - &cdd->h_age_commitment)), - GNUNET_JSON_pack_data_auto ("denom_pub_hash", - &cdd->h_denom_pub), - TALER_JSON_pack_denom_sig ("ub_sig", - &cdd->denom_sig), - GNUNET_JSON_pack_timestamp ("timestamp", - dcd->timestamp), - GNUNET_JSON_pack_data_auto ("merchant_pub", - &dcd->merchant_pub), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_timestamp ("refund_deadline", - dcd->refund_deadline)), - GNUNET_JSON_pack_timestamp ("wire_transfer_deadline", - dcd->wire_deadline), - GNUNET_JSON_pack_data_auto ("coin_sig", - &cdd->coin_sig)); - GNUNET_assert (NULL != deposit_obj); - eh = TALER_EXCHANGE_curl_easy_get_ (dh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&dh->ctx, - eh, - deposit_obj)) ) - { - *ec = TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE; - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (deposit_obj); - GNUNET_free (dh->url); - GNUNET_free (dh); - return NULL; - } - json_decref (deposit_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for deposit: `%s'\n", - dh->url); - ctx = TEAH_handle_to_context (exchange); - dh->job = GNUNET_CURL_job_add2 (ctx, - eh, - dh->ctx.headers, - &handle_deposit_finished, - dh); - return dh; -} - - -void -TALER_EXCHANGE_deposit_force_dc (struct TALER_EXCHANGE_DepositHandle *deposit) -{ - deposit->auditor_chance = 1; -} - - -void -TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit) -{ - if (NULL != deposit->job) - { - GNUNET_CURL_job_cancel (deposit->job); - deposit->job = NULL; - } - GNUNET_free (deposit->url); - TALER_curl_easy_post_finished (&deposit->ctx); - GNUNET_free (deposit); -} - - -/* end of exchange_api_deposit.c */ diff --git a/src/lib/exchange_api_deposits_get.c b/src/lib/exchange_api_deposits_get.c index 9ec25e45a..8b145dabd 100644 --- a/src/lib/exchange_api_deposits_get.c +++ b/src/lib/exchange_api_deposits_get.c @@ -39,9 +39,9 @@ struct TALER_EXCHANGE_DepositGetHandle { /** - * The connection to exchange this request handle will use + * The keys of the this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -131,7 +131,7 @@ handle_deposit_wtid_finished (void *cls, }; const struct TALER_EXCHANGE_Keys *key_state; - key_state = TALER_EXCHANGE_get_keys (dwh->exchange); + key_state = dwh->keys; GNUNET_assert (NULL != key_state); if (GNUNET_OK != GNUNET_JSON_parse (j, @@ -255,7 +255,9 @@ handle_deposit_wtid_finished (void *cls, struct TALER_EXCHANGE_DepositGetHandle * TALER_EXCHANGE_deposits_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_MerchantPrivateKeyP *merchant_priv, const struct TALER_MerchantWireHashP *h_wire, const struct TALER_PrivateContractHashP *h_contract_terms, @@ -267,7 +269,6 @@ TALER_EXCHANGE_deposits_get ( struct TALER_MerchantPublicKeyP merchant; struct TALER_MerchantSignatureP merchant_sig; struct TALER_EXCHANGE_DepositGetHandle *dwh; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[(sizeof (struct TALER_CoinSpendPublicKeyP) + sizeof (struct TALER_MerchantWireHashP) @@ -275,12 +276,6 @@ TALER_EXCHANGE_deposits_get ( + sizeof (struct TALER_PrivateContractHashP) + sizeof (struct TALER_MerchantSignatureP)) * 2 + 48]; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, &merchant.eddsa_pub); TALER_merchant_deposit_sign (h_contract_terms, @@ -339,7 +334,7 @@ TALER_EXCHANGE_deposits_get ( GNUNET_snprintf (arg_str, sizeof (arg_str), - "/deposits/%s/%s/%s/%s?merchant_sig=%s%s%s", + "deposits/%s/%s/%s/%s?merchant_sig=%s%s%s", whash_str, mpub_str, chash_str, @@ -352,11 +347,11 @@ TALER_EXCHANGE_deposits_get ( } dwh = GNUNET_new (struct TALER_EXCHANGE_DepositGetHandle); - dwh->exchange = exchange; dwh->cb = cb; dwh->cb_cls = cb_cls; - dwh->url = TEAH_path_to_url (exchange, - arg_str); + dwh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == dwh->url) { GNUNET_free (dwh); @@ -365,7 +360,6 @@ TALER_EXCHANGE_deposits_get ( dwh->h_wire = *h_wire; dwh->h_contract_terms = *h_contract_terms; dwh->coin_pub = *coin_pub; - eh = TALER_EXCHANGE_curl_easy_get_ (dwh->url); if (NULL == eh) { @@ -374,11 +368,11 @@ TALER_EXCHANGE_deposits_get ( GNUNET_free (dwh); return NULL; } - ctx = TEAH_handle_to_context (exchange); dwh->job = GNUNET_CURL_job_add (ctx, eh, &handle_deposit_wtid_finished, dwh); + dwh->keys = TALER_EXCHANGE_keys_incref (keys); return dwh; } @@ -393,6 +387,7 @@ TALER_EXCHANGE_deposits_get_cancel (struct TALER_EXCHANGE_DepositGetHandle *dwh) } GNUNET_free (dwh->url); TALER_curl_easy_post_finished (&dwh->ctx); + TALER_EXCHANGE_keys_decref (dwh->keys); GNUNET_free (dwh); } diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index 20bac43a0..fe73f0504 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -110,17 +110,7 @@ struct TEAH_AuditorListEntry /** * Handle to the auditor. */ - struct TALER_AUDITOR_Handle *ah; - - /** - * Head of DLL of interactions with this auditor. - */ - struct TEAH_AuditorInteractionEntry *ai_head; - - /** - * Tail of DLL of interactions with this auditor. - */ - struct TEAH_AuditorInteractionEntry *ai_tail; + struct TALER_AUDITOR_GetConfigHandle *ah; /** * Public key of the auditor. @@ -168,57 +158,24 @@ struct KeysRequest void -TEAH_acc_confirmation_cb (void *cls, - const struct TALER_AUDITOR_HttpResponse *hr) -{ - struct TEAH_AuditorInteractionEntry *aie = cls; - struct TEAH_AuditorListEntry *ale = aie->ale; - - if (MHD_HTTP_OK != hr->http_status) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to submit deposit confirmation to auditor `%s' with HTTP status %d (EC: %d). This is acceptable if it does not happen often.\n", - ale->auditor_url, - hr->http_status, - hr->ec); - } - GNUNET_CONTAINER_DLL_remove (ale->ai_head, - ale->ai_tail, - aie); - GNUNET_free (aie); -} - - -void -TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h, +TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys, TEAH_AuditorCallback ac, void *ac_cls) { - if (NULL == h->auditors_head) + if (0 == keys->num_auditors) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "No auditor available for exchange `%s'. Not submitting deposit confirmations.\n", - h->url); + "No auditor available. Not submitting deposit confirmations.\n"); return; } - for (struct TEAH_AuditorListEntry *ale = h->auditors_head; - NULL != ale; - ale = ale->next) + for (unsigned int i = 0; i<keys->num_auditors; i++) { - struct TEAH_AuditorInteractionEntry *aie; + const struct TALER_EXCHANGE_AuditorInformation *auditor + = &keys->auditors[i]; - if (! ale->is_up) - continue; - aie = ac (ac_cls, - ale->ah, - &ale->auditor_pub); - if (NULL != aie) - { - aie->ale = ale; - GNUNET_CONTAINER_DLL_insert (ale->ai_head, - ale->ai_tail, - aie); - } + ac (ac_cls, + auditor->auditor_url, + &auditor->auditor_pub); } } @@ -579,21 +536,18 @@ parse_global_fee (struct TALER_EXCHANGE_GlobalFee *gf, * auditor as 'up'. * * @param cls closure, a `struct TEAH_AuditorListEntry *` - * @param hr http response from the auditor - * @param vi basic information about the auditor - * @param compat protocol compatibility information + * @param vr response from the auditor */ static void -auditor_version_cb ( +auditor_config_cb ( void *cls, - const struct TALER_AUDITOR_HttpResponse *hr, - const struct TALER_AUDITOR_VersionInformation *vi, - enum TALER_AUDITOR_VersionCompatibility compat) + const struct TALER_AUDITOR_ConfigResponse *vr) { struct TEAH_AuditorListEntry *ale = cls; + enum TALER_AUDITOR_VersionCompatibility compat; - (void) hr; - if (NULL == vi) + ale->ah = NULL; + if (MHD_HTTP_OK != vr->hr.http_status) { /* In this case, we don't mark the auditor as 'up' */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -601,7 +555,7 @@ auditor_version_cb ( ale->auditor_url); return; } - + compat = vr->details.ok.compat; if (0 != (TALER_AUDITOR_VC_INCOMPATIBLE & compat)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -667,10 +621,10 @@ update_auditors (struct TALER_EXCHANGE_Handle *exchange) GNUNET_CONTAINER_DLL_insert (exchange->auditors_head, exchange->auditors_tail, ale); - ale->ah = TALER_AUDITOR_connect (exchange->ctx, - ale->auditor_url, - &auditor_version_cb, - ale); + ale->ah = TALER_AUDITOR_get_config (exchange->ctx, + ale->auditor_url, + &auditor_config_cb, + ale); } } @@ -2123,26 +2077,14 @@ TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange) while (NULL != (ale = exchange->auditors_head)) { - struct TEAH_AuditorInteractionEntry *aie; - - while (NULL != (aie = ale->ai_head)) - { - GNUNET_assert (aie->ale == ale); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Not sending deposit confirmation to auditor `%s' due to exchange disconnect\n", - ale->auditor_url); - TALER_AUDITOR_deposit_confirmation_cancel (aie->dch); - GNUNET_CONTAINER_DLL_remove (ale->ai_head, - ale->ai_tail, - aie); - GNUNET_free (aie); - } GNUNET_CONTAINER_DLL_remove (exchange->auditors_head, exchange->auditors_tail, ale); - TALER_LOG_DEBUG ("Disconnecting the auditor `%s'\n", - ale->auditor_url); - TALER_AUDITOR_disconnect (ale->ah); + if (NULL != ale->ah) + { + TALER_AUDITOR_get_config_cancel (ale->ah); + ale->ah = NULL; + } GNUNET_free (ale->auditor_url); GNUNET_free (ale); } @@ -2275,7 +2217,7 @@ TALER_EXCHANGE_get_denomination_key_by_hash ( } -const struct TALER_EXCHANGE_Keys * +struct TALER_EXCHANGE_Keys * TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange) { (void) TALER_EXCHANGE_check_keys_current (exchange, @@ -2297,4 +2239,33 @@ TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange) } +/** + * Obtain the keys from the exchange in the raw JSON format. + * + * @param keys the keys structure + * @return the keys in raw JSON + */ +json_t * +TALER_EXCHANGE_keys_to_json (struct TALER_EXCHANGE_Keys *keys) +{ + // FIXME! + return NULL; +} + + +struct TALER_EXCHANGE_Keys * +TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys) +{ + // FIXME + return keys; +} + + +void +TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) +{ + // FIXME +} + + /* end of exchange_api_handle.c */ diff --git a/src/lib/exchange_api_handle.h b/src/lib/exchange_api_handle.h index 3b1d875fb..6b96e21eb 100644 --- a/src/lib/exchange_api_handle.h +++ b/src/lib/exchange_api_handle.h @@ -35,32 +35,6 @@ struct TEAH_AuditorListEntry; /** - * Entry in list of ongoing interactions with an auditor. - */ -struct TEAH_AuditorInteractionEntry -{ - /** - * DLL entry. - */ - struct TEAH_AuditorInteractionEntry *next; - - /** - * DLL entry. - */ - struct TEAH_AuditorInteractionEntry *prev; - - /** - * Which auditor is this action associated with? - */ - struct TEAH_AuditorListEntry *ale; - - /** - * Interaction state. - */ - struct TALER_AUDITOR_DepositConfirmationHandle *dch; -}; - -/** * Stages of initialization for the `struct TALER_EXCHANGE_Handle` */ enum ExchangeHandleState @@ -178,39 +152,26 @@ struct TALER_EXCHANGE_Handle * launch a deposit confirmation interaction. * * @param cls closure - * @param ah handle to the auditor + * @param auditor_url base URL of the auditor * @param auditor_pub public key of the auditor - * @return NULL if no deposit confirmation interaction was launched */ -typedef struct TEAH_AuditorInteractionEntry * +typedef void (*TEAH_AuditorCallback)(void *cls, - struct TALER_AUDITOR_Handle *ah, + const char *auditor_url, const struct TALER_AuditorPublicKeyP *auditor_pub); /** - * Signature of functions called with the result from our call to the - * auditor's /deposit-confirmation handler. - * - * @param cls closure of type `struct TEAH_AuditorInteractionEntry *` - * @param hr HTTP response - */ -void -TEAH_acc_confirmation_cb (void *cls, - const struct TALER_AUDITOR_HttpResponse *hr); - - -/** * Iterate over all available auditors for @a h, calling * @a ac and giving it a chance to start a deposit * confirmation interaction. * - * @param h exchange to go over auditors for + * @param keys the keys to go over auditors for * @param ac function to call per auditor * @param ac_cls closure for @a ac */ void -TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h, +TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys, TEAH_AuditorCallback ac, void *ac_cls); diff --git a/src/lib/exchange_api_kyc_proof.c b/src/lib/exchange_api_kyc_proof.c index 1298df4fd..e7cc9c4cf 100644 --- a/src/lib/exchange_api_kyc_proof.c +++ b/src/lib/exchange_api_kyc_proof.c @@ -37,11 +37,6 @@ struct TALER_EXCHANGE_KycProofHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -140,27 +135,22 @@ handle_kyc_proof_finished (void *cls, struct TALER_EXCHANGE_KycProofHandle * -TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_PaytoHashP *h_payto, - const char *logic, - const char *args, - TALER_EXCHANGE_KycProofCallback cb, - void *cb_cls) +TALER_EXCHANGE_kyc_proof ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_PaytoHashP *h_payto, + const char *logic, + const char *args, + TALER_EXCHANGE_KycProofCallback cb, + void *cb_cls) { struct TALER_EXCHANGE_KycProofHandle *kph; - struct GNUNET_CURL_Context *ctx; char *arg_str; if (NULL == args) args = ""; else GNUNET_assert (args[0] == '&'); - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } { char hstr[sizeof (struct TALER_PaytoHashP) * 2]; char *end; @@ -171,17 +161,17 @@ TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange, sizeof (hstr)); *end = '\0'; GNUNET_asprintf (&arg_str, - "/kyc-proof/%s?state=%s%s", + "kyc-proof/%s?state=%s%s", logic, hstr, args); } kph = GNUNET_new (struct TALER_EXCHANGE_KycProofHandle); - kph->exchange = exchange; kph->cb = cb; kph->cb_cls = cb_cls; - kph->url = TEAH_path_to_url (exchange, - arg_str); + kph->url = TALER_url_join (url, + arg_str, + NULL); GNUNET_free (arg_str); if (NULL == kph->url) { @@ -202,7 +192,6 @@ TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange, curl_easy_setopt (kph->eh, CURLOPT_FOLLOWLOCATION, 0L)); - ctx = TEAH_handle_to_context (exchange); kph->job = GNUNET_CURL_job_add_raw (ctx, kph->eh, NULL, diff --git a/src/lib/exchange_api_kyc_wallet.c b/src/lib/exchange_api_kyc_wallet.c index 56794b94e..7197694ae 100644 --- a/src/lib/exchange_api_kyc_wallet.c +++ b/src/lib/exchange_api_kyc_wallet.c @@ -43,11 +43,6 @@ struct TALER_EXCHANGE_KycWalletHandle struct TALER_CURL_PostContext ctx; /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -154,16 +149,17 @@ handle_kyc_wallet_finished (void *cls, struct TALER_EXCHANGE_KycWalletHandle * -TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_Amount *balance, - TALER_EXCHANGE_KycWalletCallback cb, - void *cb_cls) +TALER_EXCHANGE_kyc_wallet ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_Amount *balance, + TALER_EXCHANGE_KycWalletCallback cb, + void *cb_cls) { struct TALER_EXCHANGE_KycWalletHandle *kwh; CURL *eh; json_t *req; - struct GNUNET_CURL_Context *ctx; struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReserveSignatureP reserve_sig; @@ -181,18 +177,17 @@ TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle *exchange, &reserve_sig)); GNUNET_assert (NULL != req); kwh = GNUNET_new (struct TALER_EXCHANGE_KycWalletHandle); - kwh->exchange = exchange; kwh->cb = cb; kwh->cb_cls = cb_cls; - kwh->url = TEAH_path_to_url (exchange, - "/kyc-wallet"); + kwh->url = TALER_url_join (url, + "kyc-wallet", + NULL); if (NULL == kwh->url) { json_decref (req); GNUNET_free (kwh); return NULL; } - ctx = TEAH_handle_to_context (exchange); eh = TALER_EXCHANGE_curl_easy_get_ (kwh->url); if ( (NULL == eh) || (GNUNET_OK != diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c index c2b7ac0b4..04beeb296 100644 --- a/src/lib/exchange_api_link.c +++ b/src/lib/exchange_api_link.c @@ -37,11 +37,6 @@ struct TALER_EXCHANGE_LinkHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -451,26 +446,19 @@ handle_link_finished (void *cls, struct TALER_EXCHANGE_LinkHandle * -TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - const struct - TALER_AgeCommitmentProof *age_commitment_proof, - TALER_EXCHANGE_LinkCallback link_cb, - void *link_cb_cls) +TALER_EXCHANGE_link ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentProof *age_commitment_proof, + TALER_EXCHANGE_LinkCallback link_cb, + void *link_cb_cls) { struct TALER_EXCHANGE_LinkHandle *lh; CURL *eh; - struct GNUNET_CURL_Context *ctx; struct TALER_CoinSpendPublicKeyP coin_pub; char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } - GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, &coin_pub.eddsa_pub); { @@ -485,17 +473,17 @@ TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange, *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/coins/%s/link", + "coins/%s/link", pub_str); } lh = GNUNET_new (struct TALER_EXCHANGE_LinkHandle); - lh->exchange = exchange; lh->link_cb = link_cb; lh->link_cb_cls = link_cb_cls; lh->coin_priv = *coin_priv; lh->age_commitment_proof = age_commitment_proof; - lh->url = TEAH_path_to_url (exchange, - arg_str); + lh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == lh->url) { GNUNET_free (lh); @@ -509,7 +497,6 @@ TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange, GNUNET_free (lh); return NULL; } - ctx = TEAH_handle_to_context (exchange); lh->job = GNUNET_CURL_job_add_with_ct_json (ctx, eh, &handle_link_finished, diff --git a/src/lib/exchange_api_melt.c b/src/lib/exchange_api_melt.c index 3a8144a3c..1da4184d2 100644 --- a/src/lib/exchange_api_melt.c +++ b/src/lib/exchange_api_melt.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015-2022 Taler Systems SA + Copyright (C) 2015-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -41,9 +41,9 @@ struct TALER_EXCHANGE_MeltHandle { /** - * The connection to exchange this request handle will use + * The keys of the this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -51,6 +51,16 @@ struct TALER_EXCHANGE_MeltHandle char *url; /** + * The exchange base url. + */ + char *exchange_url; + + /** + * Curl context. + */ + struct GNUNET_CURL_Context *cctx; + + /** * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ @@ -159,7 +169,7 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh, return GNUNET_SYSERR; } /* check that exchange signing key is permitted */ - key_state = TALER_EXCHANGE_get_keys (mh->exchange); + key_state = mh->keys; if (GNUNET_OK != TALER_EXCHANGE_test_signing_key (key_state, exchange_pub)) @@ -211,7 +221,7 @@ handle_melt_finished (void *cls, const struct TALER_EXCHANGE_Keys *keys; mh->job = NULL; - keys = TALER_EXCHANGE_get_keys (mh->exchange); + keys = mh->keys; switch (response_code) { case 0: @@ -309,7 +319,6 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh) const struct TALER_EXCHANGE_Keys *key_state; json_t *melt_obj; CURL *eh; - struct GNUNET_CURL_Context *ctx; char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; struct TALER_DenominationHashP h_denom_pub; struct TALER_ExchangeWithdrawValues alg_values[mh->rd->fresh_pks_len]; @@ -371,19 +380,19 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh) *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/coins/%s/melt", + "coins/%s/melt", pub_str); } - ctx = TEAH_handle_to_context (mh->exchange); - key_state = TALER_EXCHANGE_get_keys (mh->exchange); + key_state = mh->keys; mh->dki = TALER_EXCHANGE_get_denomination_key (key_state, &mh->md.melted_coin.pub_key); /* and now we can at last begin the actual request handling */ - mh->url = TEAH_path_to_url (mh->exchange, - arg_str); + mh->url = TALER_url_join (mh->exchange_url, + arg_str, + NULL); if (NULL == mh->url) { json_decref (melt_obj); @@ -403,7 +412,7 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh) return GNUNET_SYSERR; } json_decref (melt_obj); - mh->job = GNUNET_CURL_job_add2 (ctx, + mh->job = GNUNET_CURL_job_add2 (mh->cctx, eh, mh->ctx.headers, &handle_melt_finished, @@ -496,11 +505,14 @@ csr_cb (void *cls, struct TALER_EXCHANGE_MeltHandle * -TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData *rd, - TALER_EXCHANGE_MeltCallback melt_cb, - void *melt_cb_cls) +TALER_EXCHANGE_melt ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_EXCHANGE_RefreshData *rd, + TALER_EXCHANGE_MeltCallback melt_cb, + void *melt_cb_cls) { struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL (rd->fresh_pks_len)]; unsigned int nks_off = 0; @@ -511,11 +523,10 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange, GNUNET_break (0); return NULL; } - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle); mh->noreveal_index = TALER_CNC_KAPPA; /* invalid value */ - mh->exchange = exchange; + mh->cctx = ctx; + mh->exchange_url = GNUNET_strdup (url); mh->rd = rd; mh->rms = *rms; mh->melt_cb = melt_cb; @@ -545,9 +556,11 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange, break; } } + mh->keys = TALER_EXCHANGE_keys_incref (keys); if (0 != nks_off) { - mh->csr = TALER_EXCHANGE_csr_melt (exchange, + mh->csr = TALER_EXCHANGE_csr_melt (ctx, + url, rms, nks_off, nks, @@ -588,7 +601,9 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh) TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */ GNUNET_free (mh->mbds); GNUNET_free (mh->url); + GNUNET_free (mh->exchange_url); TALER_curl_easy_post_finished (&mh->ctx); + TALER_EXCHANGE_keys_decref (mh->keys); GNUNET_free (mh); } diff --git a/src/lib/exchange_api_purse_create_with_deposit.c b/src/lib/exchange_api_purse_create_with_deposit.c index a2618d639..af05bf923 100644 --- a/src/lib/exchange_api_purse_create_with_deposit.c +++ b/src/lib/exchange_api_purse_create_with_deposit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -73,9 +73,9 @@ struct TALER_EXCHANGE_PurseCreateDepositHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -83,6 +83,11 @@ struct TALER_EXCHANGE_PurseCreateDepositHandle char *url; /** + * The base URL of the exchange. + */ + char *exchange_url; + + /** * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ @@ -170,10 +175,9 @@ handle_purse_create_deposit_finished (void *cls, .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - const struct TALER_EXCHANGE_Keys *keys; + const struct TALER_EXCHANGE_Keys *keys = pch->keys; pch->job = NULL; - keys = TALER_EXCHANGE_get_keys (pch->exchange); switch (response_code) { case 0: @@ -181,7 +185,6 @@ handle_purse_create_deposit_finished (void *cls, break; case MHD_HTTP_OK: { - const struct TALER_EXCHANGE_Keys *key_state; struct GNUNET_TIME_Timestamp etime; struct TALER_Amount total_deposited; struct TALER_ExchangeSignatureP exchange_sig; @@ -209,9 +212,8 @@ handle_purse_create_deposit_finished (void *cls, dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - key_state = TALER_EXCHANGE_get_keys (pch->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (keys, &exchange_pub)) { GNUNET_break_op (0); @@ -387,7 +389,7 @@ handle_purse_create_deposit_finished (void *cls, if (GNUNET_OK != TALER_EXCHANGE_check_purse_coin_conflict_ ( &pch->purse_pub, - pch->exchange->url, + pch->exchange_url, j, &h_denom_pub, &phac, @@ -496,7 +498,9 @@ handle_purse_create_deposit_finished (void *cls, struct TALER_EXCHANGE_PurseCreateDepositHandle * TALER_EXCHANGE_purse_create_with_deposit ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_PurseContractPrivateKeyP *purse_priv, const struct TALER_PurseMergePrivateKeyP *merge_priv, const struct TALER_ContractDiffiePrivateP *contract_priv, @@ -508,16 +512,13 @@ TALER_EXCHANGE_purse_create_with_deposit ( void *cb_cls) { struct TALER_EXCHANGE_PurseCreateDepositHandle *pch; - struct GNUNET_CURL_Context *ctx; json_t *create_obj; json_t *deposit_arr; CURL *eh; char arg_str[sizeof (pch->purse_pub) * 2 + 32]; - char *url; uint32_t min_age = 0; pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle); - pch->exchange = exchange; pch->cb = cb; pch->cb_cls = cb_cls; { @@ -542,8 +543,6 @@ TALER_EXCHANGE_purse_create_with_deposit ( return NULL; } } - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); if (GNUNET_OK != TALER_JSON_contract_hash (contract_terms, &pch->h_contract_terms)) @@ -565,13 +564,14 @@ TALER_EXCHANGE_purse_create_with_deposit ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/purses/%s/create", + "purses/%s/create", pub_str); } GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv, &pch->merge_pub.eddsa_pub); - pch->url = TEAH_path_to_url (exchange, - arg_str); + pch->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == pch->url) { GNUNET_break (0); @@ -583,8 +583,6 @@ TALER_EXCHANGE_purse_create_with_deposit ( struct Deposit); deposit_arr = json_array (); GNUNET_assert (NULL != deposit_arr); - url = TEAH_path_to_url (exchange, - "/"); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Signing with URL `%s'\n", url); @@ -610,7 +608,6 @@ TALER_EXCHANGE_purse_create_with_deposit ( { GNUNET_break (0); json_decref (deposit_arr); - GNUNET_free (url); GNUNET_free (pch); return NULL; } @@ -648,7 +645,6 @@ TALER_EXCHANGE_purse_create_with_deposit ( json_array_append_new (deposit_arr, jdeposit)); } - GNUNET_free (url); TALER_wallet_purse_create_sign (pch->purse_expiration, &pch->h_contract_terms, &pch->merge_pub, @@ -714,7 +710,8 @@ TALER_EXCHANGE_purse_create_with_deposit ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for purse create with deposit: `%s'\n", pch->url); - ctx = TEAH_handle_to_context (exchange); + pch->keys = TALER_EXCHANGE_keys_incref (keys); + pch->exchange_url = GNUNET_strdup (url); pch->job = GNUNET_CURL_job_add2 (ctx, eh, pch->ctx.headers, @@ -734,8 +731,10 @@ TALER_EXCHANGE_purse_create_with_deposit_cancel ( pch->job = NULL; } GNUNET_free (pch->econtract.econtract); + GNUNET_free (pch->exchange_url); GNUNET_free (pch->url); GNUNET_free (pch->deposits); + TALER_EXCHANGE_keys_decref (pch->keys); TALER_curl_easy_post_finished (&pch->ctx); GNUNET_free (pch); } diff --git a/src/lib/exchange_api_purse_create_with_merge.c b/src/lib/exchange_api_purse_create_with_merge.c index 460239fc8..0c8878342 100644 --- a/src/lib/exchange_api_purse_create_with_merge.c +++ b/src/lib/exchange_api_purse_create_with_merge.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -41,9 +41,9 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -51,6 +51,11 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle char *url; /** + * The exchange base URL. + */ + char *exchange_url; + + /** * Context for #TEH_curl_easy_post(). Keeps the data that must * persist for Curl to make the upload. */ @@ -157,7 +162,6 @@ handle_purse_create_with_merge_finished (void *cls, break; case MHD_HTTP_OK: { - const struct TALER_EXCHANGE_Keys *key_state; struct GNUNET_TIME_Timestamp etime; struct TALER_Amount total_deposited; struct TALER_ExchangeSignatureP exchange_sig; @@ -184,9 +188,8 @@ handle_purse_create_with_merge_finished (void *cls, dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - key_state = TALER_EXCHANGE_get_keys (pcm->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (pcm->keys, &exchange_pub)) { GNUNET_break_op (0); @@ -253,7 +256,7 @@ handle_purse_create_with_merge_finished (void *cls, &pcm->merge_sig, &pcm->merge_pub, &pcm->purse_pub, - pcm->exchange->url, + pcm->exchange_url, j)) { GNUNET_break_op (0); @@ -340,7 +343,9 @@ handle_purse_create_with_merge_finished (void *cls, struct TALER_EXCHANGE_PurseCreateMergeHandle * TALER_EXCHANGE_purse_create_with_merge ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_PurseContractPrivateKeyP *purse_priv, const struct TALER_PurseMergePrivateKeyP *merge_priv, @@ -353,7 +358,6 @@ TALER_EXCHANGE_purse_create_with_merge ( void *cb_cls) { struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm; - struct GNUNET_CURL_Context *ctx; json_t *create_with_merge_obj; CURL *eh; char arg_str[sizeof (pcm->reserve_pub) * 2 + 32]; @@ -362,7 +366,6 @@ TALER_EXCHANGE_purse_create_with_merge ( enum TALER_WalletAccountMergeFlags flags; pcm = GNUNET_new (struct TALER_EXCHANGE_PurseCreateMergeHandle); - pcm->exchange = exchange; pcm->cb = cb; pcm->cb_cls = cb_cls; if (GNUNET_OK != @@ -409,7 +412,7 @@ TALER_EXCHANGE_purse_create_with_merge ( const struct TALER_EXCHANGE_GlobalFee *gf; gf = TALER_EXCHANGE_get_global_fee ( - TALER_EXCHANGE_get_keys (exchange), + keys, GNUNET_TIME_timestamp_get ()); purse_fee = gf->fees.purse; flags = TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE; @@ -422,8 +425,6 @@ TALER_EXCHANGE_purse_create_with_merge ( flags = TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA; } - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); { char pub_str[sizeof (pcm->reserve_pub) * 2]; char *end; @@ -436,11 +437,12 @@ TALER_EXCHANGE_purse_create_with_merge ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves/%s/purse", + "reserves/%s/purse", pub_str); } - pcm->url = TEAH_path_to_url (exchange, - arg_str); + pcm->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == pcm->url) { GNUNET_break (0); @@ -457,7 +459,7 @@ TALER_EXCHANGE_purse_create_with_merge ( { char *payto_uri; - payto_uri = TALER_reserve_make_payto (exchange->url, + payto_uri = TALER_reserve_make_payto (url, &pcm->reserve_pub); TALER_wallet_purse_merge_sign (payto_uri, merge_timestamp, @@ -546,7 +548,8 @@ TALER_EXCHANGE_purse_create_with_merge ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for purse create_with_merge: `%s'\n", pcm->url); - ctx = TEAH_handle_to_context (exchange); + pcm->keys = TALER_EXCHANGE_keys_incref (keys); + pcm->exchange_url = GNUNET_strdup (url); pcm->job = GNUNET_CURL_job_add2 (ctx, eh, pcm->ctx.headers, @@ -566,7 +569,9 @@ TALER_EXCHANGE_purse_create_with_merge_cancel ( pcm->job = NULL; } GNUNET_free (pcm->url); + GNUNET_free (pcm->exchange_url); TALER_curl_easy_post_finished (&pcm->ctx); + TALER_EXCHANGE_keys_decref (pcm->keys); GNUNET_free (pcm->econtract.econtract); GNUNET_free (pcm); } diff --git a/src/lib/exchange_api_purse_delete.c b/src/lib/exchange_api_purse_delete.c index 624838105..6f8ecc381 100644 --- a/src/lib/exchange_api_purse_delete.c +++ b/src/lib/exchange_api_purse_delete.c @@ -41,11 +41,6 @@ struct TALER_EXCHANGE_PurseDeleteHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -148,26 +143,23 @@ handle_purse_delete_finished (void *cls, struct TALER_EXCHANGE_PurseDeleteHandle * TALER_EXCHANGE_purse_delete ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_PurseContractPrivateKeyP *purse_priv, TALER_EXCHANGE_PurseDeleteCallback cb, void *cb_cls) { struct TALER_EXCHANGE_PurseDeleteHandle *pdh; - struct GNUNET_CURL_Context *ctx; CURL *eh; struct TALER_PurseContractPublicKeyP purse_pub; struct TALER_PurseContractSignatureP purse_sig; char arg_str[sizeof (purse_pub) * 2 + 32]; pdh = GNUNET_new (struct TALER_EXCHANGE_PurseDeleteHandle); - pdh->exchange = exchange; pdh->cb = cb; pdh->cb_cls = cb_cls; GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv->eddsa_priv, &purse_pub.eddsa_pub); - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); { char pub_str[sizeof (purse_pub) * 2]; char *end; @@ -179,11 +171,12 @@ TALER_EXCHANGE_purse_delete ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/purses/%s", + "purses/%s", pub_str); } - pdh->url = TEAH_path_to_url (exchange, - arg_str); + pdh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == pdh->url) { GNUNET_break (0); @@ -223,7 +216,6 @@ TALER_EXCHANGE_purse_delete ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for purse delete: `%s'\n", pdh->url); - ctx = TEAH_handle_to_context (exchange); pdh->job = GNUNET_CURL_job_add2 (ctx, eh, pdh->xhdr, diff --git a/src/lib/exchange_api_purse_deposit.c b/src/lib/exchange_api_purse_deposit.c index f88d23299..e1d38d16e 100644 --- a/src/lib/exchange_api_purse_deposit.c +++ b/src/lib/exchange_api_purse_deposit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -73,9 +73,9 @@ struct TALER_EXCHANGE_PurseDepositHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -144,10 +144,9 @@ handle_purse_deposit_finished (void *cls, .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - const struct TALER_EXCHANGE_Keys *keys; + const struct TALER_EXCHANGE_Keys *keys = pch->keys; pch->job = NULL; - keys = TALER_EXCHANGE_get_keys (pch->exchange); switch (response_code) { case 0: @@ -447,7 +446,9 @@ handle_purse_deposit_finished (void *cls, struct TALER_EXCHANGE_PurseDepositHandle * TALER_EXCHANGE_purse_deposit ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const char *purse_exchange_url, const struct TALER_PurseContractPublicKeyP *purse_pub, uint8_t min_age, @@ -457,7 +458,6 @@ TALER_EXCHANGE_purse_deposit ( void *cb_cls) { struct TALER_EXCHANGE_PurseDepositHandle *pch; - struct GNUNET_CURL_Context *ctx; json_t *create_obj; json_t *deposit_arr; CURL *eh; @@ -470,11 +470,8 @@ TALER_EXCHANGE_purse_deposit ( GNUNET_break (0); return NULL; } - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); pch = GNUNET_new (struct TALER_EXCHANGE_PurseDepositHandle); pch->purse_pub = *purse_pub; - pch->exchange = exchange; pch->cb = cb; pch->cb_cls = cb_cls; { @@ -489,11 +486,12 @@ TALER_EXCHANGE_purse_deposit ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/purses/%s/deposit", + "purses/%s/deposit", pub_str); } - pch->url = TEAH_path_to_url (exchange, - arg_str); + pch->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == pch->url) { GNUNET_break (0); @@ -502,8 +500,7 @@ TALER_EXCHANGE_purse_deposit ( } deposit_arr = json_array (); GNUNET_assert (NULL != deposit_arr); - pch->base_url = TEAH_path_to_url (exchange, - "/"); + pch->base_url = GNUNET_strdup (url); pch->num_deposits = num_deposits; pch->coins = GNUNET_new_array (num_deposits, struct Coin); @@ -594,7 +591,7 @@ TALER_EXCHANGE_purse_deposit ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for purse deposit: `%s'\n", pch->url); - ctx = TEAH_handle_to_context (exchange); + pch->keys = TALER_EXCHANGE_keys_incref (keys); pch->job = GNUNET_CURL_job_add2 (ctx, eh, pch->ctx.headers, @@ -616,6 +613,7 @@ TALER_EXCHANGE_purse_deposit_cancel ( GNUNET_free (pch->base_url); GNUNET_free (pch->url); GNUNET_free (pch->coins); + TALER_EXCHANGE_keys_decref (pch->keys); TALER_curl_easy_post_finished (&pch->ctx); GNUNET_free (pch); } diff --git a/src/lib/exchange_api_purse_merge.c b/src/lib/exchange_api_purse_merge.c index 6e1995e0d..8fd952515 100644 --- a/src/lib/exchange_api_purse_merge.c +++ b/src/lib/exchange_api_purse_merge.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -41,9 +41,9 @@ struct TALER_EXCHANGE_AccountMergeHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -148,7 +148,6 @@ handle_purse_merge_finished (void *cls, break; case MHD_HTTP_OK: { - const struct TALER_EXCHANGE_Keys *key_state; struct TALER_Amount total_deposited; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("exchange_sig", @@ -173,9 +172,8 @@ handle_purse_merge_finished (void *cls, dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - key_state = TALER_EXCHANGE_get_keys (pch->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (pch->keys, &dr.details.ok.exchange_pub)) { GNUNET_break_op (0); @@ -302,7 +300,9 @@ handle_purse_merge_finished (void *cls, struct TALER_EXCHANGE_AccountMergeHandle * TALER_EXCHANGE_account_merge ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const char *reserve_exchange_url, const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_PurseContractPublicKeyP *purse_pub, @@ -316,14 +316,12 @@ TALER_EXCHANGE_account_merge ( void *cb_cls) { struct TALER_EXCHANGE_AccountMergeHandle *pch; - struct GNUNET_CURL_Context *ctx; json_t *merge_obj; CURL *eh; char arg_str[sizeof (pch->purse_pub) * 2 + 32]; char *reserve_url; pch = GNUNET_new (struct TALER_EXCHANGE_AccountMergeHandle); - pch->exchange = exchange; pch->merge_priv = *merge_priv; pch->cb = cb; pch->cb_cls = cb_cls; @@ -332,14 +330,12 @@ TALER_EXCHANGE_account_merge ( pch->purse_expiration = purse_expiration; pch->purse_value_after_fees = *purse_value_after_fees; if (NULL == reserve_exchange_url) - pch->provider_url = GNUNET_strdup (exchange->url); + pch->provider_url = GNUNET_strdup (url); else pch->provider_url = GNUNET_strdup (reserve_exchange_url); GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, &pch->reserve_pub.eddsa_pub); - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); { char pub_str[sizeof (*purse_pub) * 2]; char *end; @@ -352,7 +348,7 @@ TALER_EXCHANGE_account_merge ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/purses/%s/merge", + "purses/%s/merge", pub_str); } reserve_url = TALER_reserve_make_payto (pch->provider_url, @@ -364,8 +360,9 @@ TALER_EXCHANGE_account_merge ( GNUNET_free (pch); return NULL; } - pch->url = TEAH_path_to_url (exchange, - arg_str); + pch->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == pch->url) { GNUNET_break (0); @@ -426,7 +423,7 @@ TALER_EXCHANGE_account_merge ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for purse merge: `%s'\n", pch->url); - ctx = TEAH_handle_to_context (exchange); + pch->keys = TALER_EXCHANGE_keys_incref (keys); pch->job = GNUNET_CURL_job_add2 (ctx, eh, pch->ctx.headers, @@ -448,6 +445,7 @@ TALER_EXCHANGE_account_merge_cancel ( GNUNET_free (pch->url); GNUNET_free (pch->provider_url); TALER_curl_easy_post_finished (&pch->ctx); + TALER_EXCHANGE_keys_decref (pch->keys); GNUNET_free (pch); } diff --git a/src/lib/exchange_api_purses_get.c b/src/lib/exchange_api_purses_get.c index 4c2fdd79c..7a6b2707f 100644 --- a/src/lib/exchange_api_purses_get.c +++ b/src/lib/exchange_api_purses_get.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,9 +39,9 @@ struct TALER_EXCHANGE_PurseGetHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -117,7 +117,6 @@ handle_purse_get_finished (void *cls, &exchange_sig), GNUNET_JSON_spec_end () }; - const struct TALER_EXCHANGE_Keys *key_state; if (GNUNET_OK != GNUNET_JSON_parse (j, @@ -130,9 +129,8 @@ handle_purse_get_finished (void *cls, break; } - key_state = TALER_EXCHANGE_get_keys (pgh->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (pgh->keys, &exchange_pub)) { GNUNET_break_op (0); @@ -207,7 +205,9 @@ handle_purse_get_finished (void *cls, struct TALER_EXCHANGE_PurseGetHandle * TALER_EXCHANGE_purse_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_PurseContractPublicKeyP *purse_pub, struct GNUNET_TIME_Relative timeout, bool wait_for_merge, @@ -218,14 +218,7 @@ TALER_EXCHANGE_purse_get ( CURL *eh; char arg_str[sizeof (*purse_pub) * 2 + 64]; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } pgh = GNUNET_new (struct TALER_EXCHANGE_PurseGetHandle); - pgh->exchange = exchange; pgh->cb = cb; pgh->cb_cls = cb_cls; { @@ -247,19 +240,20 @@ TALER_EXCHANGE_purse_get ( if (GNUNET_TIME_relative_is_zero (timeout)) GNUNET_snprintf (arg_str, sizeof (arg_str), - "/purses/%s/%s", + "purses/%s/%s", cpub_str, wait_for_merge ? "merge" : "deposit"); else GNUNET_snprintf (arg_str, sizeof (arg_str), - "/purses/%s/%s?timeout_ms=%s", + "purses/%s/%s?timeout_ms=%s", cpub_str, wait_for_merge ? "merge" : "deposit", timeout_str); } - pgh->url = TEAH_path_to_url (exchange, - arg_str); + pgh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == pgh->url) { GNUNET_free (pgh); @@ -273,10 +267,11 @@ TALER_EXCHANGE_purse_get ( GNUNET_free (pgh); return NULL; } - pgh->job = GNUNET_CURL_job_add (TEAH_handle_to_context (exchange), + pgh->job = GNUNET_CURL_job_add (ctx, eh, &handle_purse_get_finished, pgh); + pgh->keys = TALER_EXCHANGE_keys_incref (keys); return pgh; } @@ -291,6 +286,7 @@ TALER_EXCHANGE_purse_get_cancel ( pgh->job = NULL; } GNUNET_free (pgh->url); + TALER_EXCHANGE_keys_decref (pgh->keys); GNUNET_free (pgh); } diff --git a/src/lib/exchange_api_recoup.c b/src/lib/exchange_api_recoup.c index b89bda8b3..e7daff165 100644 --- a/src/lib/exchange_api_recoup.c +++ b/src/lib/exchange_api_recoup.c @@ -40,9 +40,9 @@ struct TALER_EXCHANGE_RecoupHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -143,10 +143,8 @@ handle_recoup_finished (void *cls, .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - const struct TALER_EXCHANGE_Keys *keys; ph->job = NULL; - keys = TALER_EXCHANGE_get_keys (ph->exchange); switch (response_code) { case 0: @@ -177,7 +175,7 @@ handle_recoup_finished (void *cls, rr.hr.ec = TALER_JSON_get_error_code (j); rr.hr.hint = TALER_JSON_get_error_hint (j); if (GNUNET_OK != - TALER_EXCHANGE_get_min_denomination_ (keys, + TALER_EXCHANGE_get_min_denomination_ (ph->keys, &min_key)) { GNUNET_break (0); @@ -187,7 +185,7 @@ handle_recoup_finished (void *cls, } if (GNUNET_OK != TALER_EXCHANGE_check_coin_conflict_ ( - keys, + ph->keys, j, &ph->pk, &ph->coin_pub, @@ -244,16 +242,18 @@ handle_recoup_finished (void *cls, struct TALER_EXCHANGE_RecoupHandle * -TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeWithdrawValues *exchange_vals, - const struct TALER_PlanchetMasterSecretP *ps, - TALER_EXCHANGE_RecoupResultCallback recoup_cb, - void *recoup_cb_cls) +TALER_EXCHANGE_recoup ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DenomPublicKey *pk, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_PlanchetMasterSecretP *ps, + TALER_EXCHANGE_RecoupResultCallback recoup_cb, + void *recoup_cb_cls) { struct TALER_EXCHANGE_RecoupHandle *ph; - struct GNUNET_CURL_Context *ctx; struct TALER_DenominationHashP h_denom_pub; json_t *recoup_obj; CURL *eh; @@ -261,8 +261,6 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange, struct TALER_CoinSpendPrivateKeyP coin_priv; union TALER_DenominationBlindingKeyP bks; - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); ph = GNUNET_new (struct TALER_EXCHANGE_RecoupHandle); TALER_planchet_setup_coin_priv (ps, exchange_vals, @@ -319,19 +317,19 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange, *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/coins/%s/recoup", + "coins/%s/recoup", pub_str); } - ph->exchange = exchange; ph->pk = *pk; memset (&ph->pk.key, 0, sizeof (ph->pk.key)); /* zero out, as lifetime cannot be warranted */ ph->cb = recoup_cb; ph->cb_cls = recoup_cb_cls; - ph->url = TEAH_path_to_url (exchange, - arg_str); + ph->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == ph->url) { json_decref (recoup_obj); @@ -357,7 +355,7 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for recoup: `%s'\n", ph->url); - ctx = TEAH_handle_to_context (exchange); + ph->keys = TALER_EXCHANGE_keys_incref (keys); ph->job = GNUNET_CURL_job_add2 (ctx, eh, ph->ctx.headers, @@ -377,6 +375,7 @@ TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph) } GNUNET_free (ph->url); TALER_curl_easy_post_finished (&ph->ctx); + TALER_EXCHANGE_keys_decref (ph->keys); GNUNET_free (ph); } diff --git a/src/lib/exchange_api_recoup_refresh.c b/src/lib/exchange_api_recoup_refresh.c index 7b42aa7eb..f5745deb0 100644 --- a/src/lib/exchange_api_recoup_refresh.c +++ b/src/lib/exchange_api_recoup_refresh.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2017-2022 Taler Systems SA + Copyright (C) 2017-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -40,9 +40,9 @@ struct TALER_EXCHANGE_RecoupRefreshHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -144,10 +144,8 @@ handle_recoup_refresh_finished (void *cls, .hr.reply = j, .hr.http_status = (unsigned int) response_code }; - const struct TALER_EXCHANGE_Keys *keys; ph->job = NULL; - keys = TALER_EXCHANGE_get_keys (ph->exchange); switch (response_code) { case 0: @@ -191,7 +189,7 @@ handle_recoup_refresh_finished (void *cls, rrr.hr.ec = TALER_JSON_get_error_code (j); rrr.hr.hint = TALER_JSON_get_error_hint (j); if (GNUNET_OK != - TALER_EXCHANGE_get_min_denomination_ (keys, + TALER_EXCHANGE_get_min_denomination_ (ph->keys, &min_key)) { GNUNET_break (0); @@ -201,7 +199,7 @@ handle_recoup_refresh_finished (void *cls, } if (GNUNET_OK != TALER_EXCHANGE_check_coin_conflict_ ( - keys, + ph->keys, j, &ph->pk, &ph->coin_pub, @@ -246,7 +244,9 @@ handle_recoup_refresh_finished (void *cls, struct TALER_EXCHANGE_RecoupRefreshHandle * TALER_EXCHANGE_recoup_refresh ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, const struct TALER_ExchangeWithdrawValues *exchange_vals, @@ -257,7 +257,6 @@ TALER_EXCHANGE_recoup_refresh ( void *recoup_cb_cls) { struct TALER_EXCHANGE_RecoupRefreshHandle *ph; - struct GNUNET_CURL_Context *ctx; struct TALER_DenominationHashP h_denom_pub; json_t *recoup_obj; CURL *eh; @@ -266,10 +265,7 @@ TALER_EXCHANGE_recoup_refresh ( union TALER_DenominationBlindingKeyP bks; GNUNET_assert (NULL != recoup_cb); - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); ph = GNUNET_new (struct TALER_EXCHANGE_RecoupRefreshHandle); - ph->exchange = exchange; ph->pk = *pk; memset (&ph->pk.key, 0, @@ -333,12 +329,13 @@ TALER_EXCHANGE_recoup_refresh ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/coins/%s/recoup-refresh", + "coins/%s/recoup-refresh", pub_str); } - ph->url = TEAH_path_to_url (exchange, - arg_str); + ph->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == ph->url) { json_decref (recoup_obj); @@ -364,7 +361,7 @@ TALER_EXCHANGE_recoup_refresh ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for recoup-refresh: `%s'\n", ph->url); - ctx = TEAH_handle_to_context (exchange); + ph->keys = TALER_EXCHANGE_keys_incref (keys); ph->job = GNUNET_CURL_job_add2 (ctx, eh, ph->ctx.headers, @@ -385,6 +382,7 @@ TALER_EXCHANGE_recoup_refresh_cancel ( } GNUNET_free (ph->url); TALER_curl_easy_post_finished (&ph->ctx); + TALER_EXCHANGE_keys_decref (ph->keys); GNUNET_free (ph); } diff --git a/src/lib/exchange_api_refreshes_reveal.c b/src/lib/exchange_api_refreshes_reveal.c index 50de76810..9b6f9b19c 100644 --- a/src/lib/exchange_api_refreshes_reveal.c +++ b/src/lib/exchange_api_refreshes_reveal.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015-2022 Taler Systems SA + Copyright (C) 2015-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -40,11 +40,6 @@ struct TALER_EXCHANGE_RefreshesRevealHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -310,7 +305,8 @@ handle_refresh_reveal_finished (void *cls, struct TALER_EXCHANGE_RefreshesRevealHandle * TALER_EXCHANGE_refreshes_reveal ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_RefreshMasterSecretP *rms, const struct TALER_EXCHANGE_RefreshData *rd, unsigned int num_coins, @@ -327,7 +323,6 @@ TALER_EXCHANGE_refreshes_reveal ( json_t *link_sigs; json_t *old_age_commitment = NULL; CURL *eh; - struct GNUNET_CURL_Context *ctx; struct MeltData md; char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32]; bool send_rms = false; @@ -342,12 +337,6 @@ TALER_EXCHANGE_refreshes_reveal ( GNUNET_break (0); return NULL; } - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } if (GNUNET_OK != TALER_EXCHANGE_get_melt_data_ (rms, rd, @@ -467,22 +456,22 @@ TALER_EXCHANGE_refreshes_reveal ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/refreshes/%s/reveal", + "refreshes/%s/reveal", pub_str); } /* finally, we can actually issue the request */ rrh = GNUNET_new (struct TALER_EXCHANGE_RefreshesRevealHandle); - rrh->exchange = exchange; rrh->noreveal_index = noreveal_index; rrh->reveal_cb = reveal_cb; rrh->reveal_cb_cls = reveal_cb_cls; rrh->md = md; - rrh->alg_values = GNUNET_memdup (alg_values, - md.num_fresh_coins - * sizeof (struct - TALER_ExchangeWithdrawValues)); - rrh->url = TEAH_path_to_url (rrh->exchange, - arg_str); + rrh->alg_values + = GNUNET_memdup (alg_values, + md.num_fresh_coins + * sizeof (struct TALER_ExchangeWithdrawValues)); + rrh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rrh->url) { json_decref (reveal_obj); @@ -510,7 +499,6 @@ TALER_EXCHANGE_refreshes_reveal ( return NULL; } json_decref (reveal_obj); - ctx = TEAH_handle_to_context (rrh->exchange); rrh->job = GNUNET_CURL_job_add2 (ctx, eh, rrh->ctx.headers, diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c index 35524ca4b..83f9612df 100644 --- a/src/lib/exchange_api_refund.c +++ b/src/lib/exchange_api_refund.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,9 +39,9 @@ struct TALER_EXCHANGE_RefundHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -117,7 +117,6 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, struct TALER_ExchangePublicKeyP *exchange_pub, struct TALER_ExchangeSignatureP *exchange_sig) { - const struct TALER_EXCHANGE_Keys *key_state; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("exchange_sig", exchange_sig), @@ -134,9 +133,8 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, GNUNET_break_op (0); return GNUNET_SYSERR; } - key_state = TALER_EXCHANGE_get_keys (rh->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (rh->keys, exchange_pub)) { GNUNET_break_op (0); @@ -672,7 +670,9 @@ handle_refund_finished (void *cls, struct TALER_EXCHANGE_RefundHandle * TALER_EXCHANGE_refund ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_Amount *amount, const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, @@ -684,13 +684,10 @@ TALER_EXCHANGE_refund ( struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantSignatureP merchant_sig; struct TALER_EXCHANGE_RefundHandle *rh; - struct GNUNET_CURL_Context *ctx; json_t *refund_obj; CURL *eh; char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, &merchant_pub.eddsa_pub); TALER_merchant_refund_sign (coin_pub, @@ -711,7 +708,7 @@ TALER_EXCHANGE_refund ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/coins/%s/refund", + "coins/%s/refund", pub_str); } refund_obj = GNUNET_JSON_PACK ( @@ -726,11 +723,11 @@ TALER_EXCHANGE_refund ( GNUNET_JSON_pack_data_auto ("merchant_sig", &merchant_sig)); rh = GNUNET_new (struct TALER_EXCHANGE_RefundHandle); - rh->exchange = exchange; rh->cb = cb; rh->cb_cls = cb_cls; - rh->url = TEAH_path_to_url (exchange, - arg_str); + rh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rh->url) { json_decref (refund_obj); @@ -761,7 +758,7 @@ TALER_EXCHANGE_refund ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for refund: `%s'\n", rh->url); - ctx = TEAH_handle_to_context (exchange); + rh->keys = TALER_EXCHANGE_keys_incref (keys); rh->job = GNUNET_CURL_job_add2 (ctx, eh, rh->ctx.headers, @@ -781,6 +778,7 @@ TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund) } GNUNET_free (refund->url); TALER_curl_easy_post_finished (&refund->ctx); + TALER_EXCHANGE_keys_decref (refund->keys); GNUNET_free (refund); } diff --git a/src/lib/exchange_api_reserves_attest.c b/src/lib/exchange_api_reserves_attest.c index 82d5785b7..ea9ec8426 100644 --- a/src/lib/exchange_api_reserves_attest.c +++ b/src/lib/exchange_api_reserves_attest.c @@ -39,11 +39,6 @@ struct TALER_EXCHANGE_ReservesAttestHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -131,6 +126,8 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh, GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } + /* FIXME: validate exchange_pub is actually + a good exchange signing key */ rsh->cb (rsh->cb_cls, &rs); rsh->cb = NULL; @@ -228,7 +225,8 @@ handle_reserves_attest_finished (void *cls, struct TALER_EXCHANGE_ReservesAttestHandle * TALER_EXCHANGE_reserves_attest ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ReservePrivateKeyP *reserve_priv, unsigned int attributes_length, const char *const*attributes, @@ -236,7 +234,6 @@ TALER_EXCHANGE_reserves_attest ( void *cb_cls) { struct TALER_EXCHANGE_ReservesAttestHandle *rsh; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; struct TALER_ReserveSignatureP reserve_sig; @@ -248,12 +245,6 @@ TALER_EXCHANGE_reserves_attest ( GNUNET_break (0); return NULL; } - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } details = json_array (); GNUNET_assert (NULL != details); for (unsigned int i = 0; i<attributes_length; i++) @@ -263,7 +254,6 @@ TALER_EXCHANGE_reserves_attest ( json_string (attributes[i]))); } rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesAttestHandle); - rsh->exchange = exchange; rsh->cb = cb; rsh->cb_cls = cb_cls; GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, @@ -280,11 +270,12 @@ TALER_EXCHANGE_reserves_attest ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves-attest/%s", + "reserves-attest/%s", pub_str); } - rsh->url = TEAH_path_to_url (exchange, - arg_str); + rsh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rsh->url) { json_decref (details); @@ -328,7 +319,6 @@ TALER_EXCHANGE_reserves_attest ( } json_decref (attest_obj); } - ctx = TEAH_handle_to_context (exchange); rsh->job = GNUNET_CURL_job_add2 (ctx, eh, rsh->post_ctx.headers, diff --git a/src/lib/exchange_api_reserves_close.c b/src/lib/exchange_api_reserves_close.c index 278d13101..a3769a22f 100644 --- a/src/lib/exchange_api_reserves_close.c +++ b/src/lib/exchange_api_reserves_close.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,11 +39,6 @@ struct TALER_EXCHANGE_ReservesCloseHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -269,26 +264,19 @@ handle_reserves_close_finished (void *cls, struct TALER_EXCHANGE_ReservesCloseHandle * TALER_EXCHANGE_reserves_close ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ReservePrivateKeyP *reserve_priv, const char *target_payto_uri, TALER_EXCHANGE_ReservesCloseCallback cb, void *cb_cls) { struct TALER_EXCHANGE_ReservesCloseHandle *rch; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; struct TALER_PaytoHashP h_payto; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } rch = GNUNET_new (struct TALER_EXCHANGE_ReservesCloseHandle); - rch->exchange = exchange; rch->cb = cb; rch->cb_cls = cb_cls; rch->ts = GNUNET_TIME_timestamp_get (); @@ -306,11 +294,12 @@ TALER_EXCHANGE_reserves_close ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves/%s/close", + "reserves/%s/close", pub_str); } - rch->url = TEAH_path_to_url (exchange, - arg_str); + rch->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rch->url) { GNUNET_free (rch); @@ -357,7 +346,6 @@ TALER_EXCHANGE_reserves_close ( } json_decref (close_obj); } - ctx = TEAH_handle_to_context (exchange); rch->job = GNUNET_CURL_job_add2 (ctx, eh, rch->post_ctx.headers, diff --git a/src/lib/exchange_api_reserves_get.c b/src/lib/exchange_api_reserves_get.c index 1c2c2b027..7b59ba9a4 100644 --- a/src/lib/exchange_api_reserves_get.c +++ b/src/lib/exchange_api_reserves_get.c @@ -39,11 +39,6 @@ struct TALER_EXCHANGE_ReservesGetHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -186,23 +181,17 @@ handle_reserves_get_finished (void *cls, struct TALER_EXCHANGE_ReservesGetHandle * TALER_EXCHANGE_reserves_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ReservePublicKeyP *reserve_pub, struct GNUNET_TIME_Relative timeout, TALER_EXCHANGE_ReservesGetCallback cb, void *cb_cls) { struct TALER_EXCHANGE_ReservesGetHandle *rgh; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 16 + 32]; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } { char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; char *end; @@ -223,22 +212,22 @@ TALER_EXCHANGE_reserves_get ( if (GNUNET_TIME_relative_is_zero (timeout)) GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves/%s", + "reserves/%s", pub_str); else GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves/%s?timeout_ms=%s", + "reserves/%s?timeout_ms=%s", pub_str, timeout_str); } rgh = GNUNET_new (struct TALER_EXCHANGE_ReservesGetHandle); - rgh->exchange = exchange; rgh->cb = cb; rgh->cb_cls = cb_cls; rgh->reserve_pub = *reserve_pub; - rgh->url = TEAH_path_to_url (exchange, - arg_str); + rgh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rgh->url) { GNUNET_free (rgh); @@ -252,7 +241,6 @@ TALER_EXCHANGE_reserves_get ( GNUNET_free (rgh); return NULL; } - ctx = TEAH_handle_to_context (exchange); rgh->job = GNUNET_CURL_job_add (ctx, eh, &handle_reserves_get_finished, diff --git a/src/lib/exchange_api_reserves_get_attestable.c b/src/lib/exchange_api_reserves_get_attestable.c index b272d478a..f58e0592e 100644 --- a/src/lib/exchange_api_reserves_get_attestable.c +++ b/src/lib/exchange_api_reserves_get_attestable.c @@ -39,11 +39,6 @@ struct TALER_EXCHANGE_ReservesGetAttestHandle { /** - * The connection to exchange this request handle will use - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** * The url for this request. */ char *url; @@ -211,22 +206,16 @@ handle_reserves_get_attestable_finished (void *cls, struct TALER_EXCHANGE_ReservesGetAttestHandle * TALER_EXCHANGE_reserves_get_attestable ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ReservePublicKeyP *reserve_pub, TALER_EXCHANGE_ReservesGetAttestCallback cb, void *cb_cls) { struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } { char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; char *end; @@ -239,16 +228,16 @@ TALER_EXCHANGE_reserves_get_attestable ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves-attest/%s", + "reserves-attest/%s", pub_str); } rgah = GNUNET_new (struct TALER_EXCHANGE_ReservesGetAttestHandle); - rgah->exchange = exchange; rgah->cb = cb; rgah->cb_cls = cb_cls; rgah->reserve_pub = *reserve_pub; - rgah->url = TEAH_path_to_url (exchange, - arg_str); + rgah->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rgah->url) { GNUNET_free (rgah); @@ -262,7 +251,6 @@ TALER_EXCHANGE_reserves_get_attestable ( GNUNET_free (rgah); return NULL; } - ctx = TEAH_handle_to_context (exchange); rgah->job = GNUNET_CURL_job_add (ctx, eh, &handle_reserves_get_attestable_finished, diff --git a/src/lib/exchange_api_reserves_history.c b/src/lib/exchange_api_reserves_history.c index ccc11a270..a48e0c087 100644 --- a/src/lib/exchange_api_reserves_history.c +++ b/src/lib/exchange_api_reserves_history.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,9 +39,9 @@ struct TALER_EXCHANGE_ReservesHistoryHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -131,7 +131,7 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh, rhistory = GNUNET_new_array (len, struct TALER_EXCHANGE_ReserveHistoryEntry); if (GNUNET_OK != - TALER_EXCHANGE_parse_reserve_history (rsh->exchange, + TALER_EXCHANGE_parse_reserve_history (rsh->keys, history, &rsh->reserve_pub, rs.details.ok.balance.currency, @@ -250,26 +250,19 @@ handle_reserves_history_finished (void *cls, struct TALER_EXCHANGE_ReservesHistoryHandle * TALER_EXCHANGE_reserves_history ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, TALER_EXCHANGE_ReservesHistoryCallback cb, void *cb_cls) { struct TALER_EXCHANGE_ReservesHistoryHandle *rsh; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; - const struct TALER_EXCHANGE_Keys *keys; const struct TALER_EXCHANGE_GlobalFee *gf; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesHistoryHandle); - rsh->exchange = exchange; rsh->cb = cb; rsh->cb_cls = cb_cls; rsh->ts = GNUNET_TIME_timestamp_get (); @@ -287,11 +280,12 @@ TALER_EXCHANGE_reserves_history ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves/%s/history", + "reserves/%s/history", pub_str); } - rsh->url = TEAH_path_to_url (exchange, - arg_str); + rsh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rsh->url) { GNUNET_free (rsh); @@ -305,15 +299,6 @@ TALER_EXCHANGE_reserves_history ( GNUNET_free (rsh); return NULL; } - keys = TALER_EXCHANGE_get_keys (exchange); - if (NULL == keys) - { - GNUNET_break (0); - curl_easy_cleanup (eh); - GNUNET_free (rsh->url); - GNUNET_free (rsh); - return NULL; - } gf = TALER_EXCHANGE_get_global_fee (keys, rsh->ts); if (NULL == gf) @@ -349,7 +334,7 @@ TALER_EXCHANGE_reserves_history ( } json_decref (history_obj); } - ctx = TEAH_handle_to_context (exchange); + rsh->keys = TALER_EXCHANGE_keys_incref (keys); rsh->job = GNUNET_CURL_job_add2 (ctx, eh, rsh->post_ctx.headers, @@ -370,6 +355,7 @@ TALER_EXCHANGE_reserves_history_cancel ( } TALER_curl_easy_post_finished (&rsh->post_ctx); GNUNET_free (rsh->url); + TALER_EXCHANGE_keys_decref (rsh->keys); GNUNET_free (rsh); } diff --git a/src/lib/exchange_api_reserves_open.c b/src/lib/exchange_api_reserves_open.c index 2b7ef0d90..b28333d51 100644 --- a/src/lib/exchange_api_reserves_open.c +++ b/src/lib/exchange_api_reserves_open.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -67,9 +67,9 @@ struct TALER_EXCHANGE_ReservesOpenHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -321,7 +321,6 @@ handle_reserves_open_finished (void *cls, break; case MHD_HTTP_CONFLICT: { - const struct TALER_EXCHANGE_Keys *keys; const struct CoinData *cd = NULL; struct TALER_CoinSpendPublicKeyP coin_pub; const struct TALER_EXCHANGE_DenomPublicKey *dk; @@ -331,8 +330,6 @@ handle_reserves_open_finished (void *cls, GNUNET_JSON_spec_end () }; - keys = TALER_EXCHANGE_get_keys (roh->exchange); - GNUNET_assert (NULL != keys); if (GNUNET_OK != GNUNET_JSON_parse (j, spec, @@ -362,7 +359,7 @@ handle_reserves_open_finished (void *cls, rs.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - dk = TALER_EXCHANGE_get_denomination_key_by_hash (keys, + dk = TALER_EXCHANGE_get_denomination_key_by_hash (roh->keys, &cd->h_denom_pub); if (NULL == dk) { @@ -372,7 +369,7 @@ handle_reserves_open_finished (void *cls, break; } if (GNUNET_OK != - TALER_EXCHANGE_check_coin_conflict_ (keys, + TALER_EXCHANGE_check_coin_conflict_ (roh->keys, j, dk, &coin_pub, @@ -427,7 +424,9 @@ handle_reserves_open_finished (void *cls, struct TALER_EXCHANGE_ReservesOpenHandle * TALER_EXCHANGE_reserves_open ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_Amount *reserve_contribution, unsigned int coin_payments_length, @@ -438,20 +437,11 @@ TALER_EXCHANGE_reserves_open ( void *cb_cls) { struct TALER_EXCHANGE_ReservesOpenHandle *roh; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; - const struct TALER_EXCHANGE_Keys *keys; json_t *cpa; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } roh = GNUNET_new (struct TALER_EXCHANGE_ReservesOpenHandle); - roh->exchange = exchange; roh->cb = cb; roh->cb_cls = cb_cls; roh->ts = GNUNET_TIME_timestamp_get (); @@ -469,11 +459,12 @@ TALER_EXCHANGE_reserves_open ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves/%s/open", + "reserves/%s/open", pub_str); } - roh->url = TEAH_path_to_url (exchange, - arg_str); + roh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == roh->url) { GNUNET_free (roh); @@ -487,15 +478,6 @@ TALER_EXCHANGE_reserves_open ( GNUNET_free (roh); return NULL; } - keys = TALER_EXCHANGE_get_keys (exchange); - if (NULL == keys) - { - GNUNET_break (0); - curl_easy_cleanup (eh); - GNUNET_free (roh->url); - GNUNET_free (roh); - return NULL; - } TALER_wallet_reserve_open_sign (reserve_contribution, roh->ts, expiration_time, @@ -578,7 +560,7 @@ TALER_EXCHANGE_reserves_open ( } json_decref (open_obj); } - ctx = TEAH_handle_to_context (exchange); + roh->keys = TALER_EXCHANGE_keys_incref (keys); roh->job = GNUNET_CURL_job_add2 (ctx, eh, roh->post_ctx.headers, @@ -600,6 +582,7 @@ TALER_EXCHANGE_reserves_open_cancel ( TALER_curl_easy_post_finished (&roh->post_ctx); GNUNET_free (roh->coins); GNUNET_free (roh->url); + TALER_EXCHANGE_keys_decref (roh->keys); GNUNET_free (roh); } diff --git a/src/lib/exchange_api_reserves_status.c b/src/lib/exchange_api_reserves_status.c index 57fb04276..9f98b7f8c 100644 --- a/src/lib/exchange_api_reserves_status.c +++ b/src/lib/exchange_api_reserves_status.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,9 +39,9 @@ struct TALER_EXCHANGE_ReservesStatusHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -119,7 +119,7 @@ handle_reserves_status_ok (struct TALER_EXCHANGE_ReservesStatusHandle *rsh, rhistory = GNUNET_new_array (len, struct TALER_EXCHANGE_ReserveHistoryEntry); if (GNUNET_OK != - TALER_EXCHANGE_parse_reserve_history (rsh->exchange, + TALER_EXCHANGE_parse_reserve_history (rsh->keys, history, &rsh->reserve_pub, rs.details.ok.balance.currency, @@ -233,27 +233,21 @@ handle_reserves_status_finished (void *cls, struct TALER_EXCHANGE_ReservesStatusHandle * TALER_EXCHANGE_reserves_status ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, TALER_EXCHANGE_ReservesStatusCallback cb, void *cb_cls) { struct TALER_EXCHANGE_ReservesStatusHandle *rsh; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; struct TALER_ReserveSignatureP reserve_sig; struct GNUNET_TIME_Timestamp ts = GNUNET_TIME_timestamp_get (); - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesStatusHandle); - rsh->exchange = exchange; rsh->cb = cb; rsh->cb_cls = cb_cls; GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, @@ -270,11 +264,12 @@ TALER_EXCHANGE_reserves_status ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/reserves/%s/status", + "reserves/%s/status", pub_str); } - rsh->url = TEAH_path_to_url (exchange, - arg_str); + rsh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rsh->url) { GNUNET_free (rsh); @@ -312,7 +307,7 @@ TALER_EXCHANGE_reserves_status ( } json_decref (status_obj); } - ctx = TEAH_handle_to_context (exchange); + rsh->keys = TALER_EXCHANGE_keys_incref (keys); rsh->job = GNUNET_CURL_job_add2 (ctx, eh, rsh->post_ctx.headers, @@ -333,6 +328,7 @@ TALER_EXCHANGE_reserves_status_cancel ( } TALER_curl_easy_post_finished (&rsh->post_ctx); GNUNET_free (rsh->url); + TALER_EXCHANGE_keys_decref (rsh->keys); GNUNET_free (rsh); } diff --git a/src/lib/exchange_api_transfers_get.c b/src/lib/exchange_api_transfers_get.c index 3a5a64fd5..14cf51ff9 100644 --- a/src/lib/exchange_api_transfers_get.c +++ b/src/lib/exchange_api_transfers_get.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -38,9 +38,9 @@ struct TALER_EXCHANGE_TransfersGetHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -130,7 +130,7 @@ check_transfers_get_response_ok ( } if (GNUNET_OK != TALER_EXCHANGE_test_signing_key ( - TALER_EXCHANGE_get_keys (wdh->exchange), + wdh->keys, &td->exchange_pub)) { GNUNET_break_op (0); @@ -320,25 +320,18 @@ handle_transfers_get_finished (void *cls, struct TALER_EXCHANGE_TransfersGetHandle * TALER_EXCHANGE_transfers_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_WireTransferIdentifierRawP *wtid, TALER_EXCHANGE_TransfersGetCallback cb, void *cb_cls) { struct TALER_EXCHANGE_TransfersGetHandle *wdh; - struct GNUNET_CURL_Context *ctx; CURL *eh; char arg_str[sizeof (struct TALER_WireTransferIdentifierRawP) * 2 + 32]; - if (GNUNET_YES != - TEAH_handle_is_ready (exchange)) - { - GNUNET_break (0); - return NULL; - } - wdh = GNUNET_new (struct TALER_EXCHANGE_TransfersGetHandle); - wdh->exchange = exchange; wdh->cb = cb; wdh->cb_cls = cb_cls; @@ -354,11 +347,12 @@ TALER_EXCHANGE_transfers_get ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/transfers/%s", + "transfers/%s", wtid_str); } - wdh->url = TEAH_path_to_url (wdh->exchange, - arg_str); + wdh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == wdh->url) { GNUNET_free (wdh); @@ -372,7 +366,7 @@ TALER_EXCHANGE_transfers_get ( GNUNET_free (wdh); return NULL; } - ctx = TEAH_handle_to_context (exchange); + wdh->keys = TALER_EXCHANGE_keys_incref (keys); wdh->job = GNUNET_CURL_job_add_with_ct_json (ctx, eh, &handle_transfers_get_finished, @@ -397,6 +391,7 @@ TALER_EXCHANGE_transfers_get_cancel ( wdh->job = NULL; } GNUNET_free (wdh->url); + TALER_EXCHANGE_keys_decref (wdh->keys); GNUNET_free (wdh); } diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c index bf2bd0237..daac429c7 100644 --- a/src/lib/exchange_api_withdraw2.c +++ b/src/lib/exchange_api_withdraw2.c @@ -192,7 +192,8 @@ reserve_withdraw_payment_required ( } if (GNUNET_OK != - TALER_EXCHANGE_parse_reserve_history (wh->exchange, + TALER_EXCHANGE_parse_reserve_history (TALER_EXCHANGE_get_keys ( + wh->exchange), history, &wh->reserve_pub, balance.currency, |