aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.am4
-rw-r--r--src/lib/exchange_api_age_withdraw.c42
-rw-r--r--src/lib/exchange_api_batch_withdraw2.c45
-rw-r--r--src/lib/exchange_api_withdraw.c364
-rw-r--r--src/lib/exchange_api_withdraw2.c389
5 files changed, 45 insertions, 799 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 12f991d89..230dfba21 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -75,9 +75,7 @@ libtalerexchange_la_SOURCES = \
exchange_api_reserves_history.c \
exchange_api_reserves_open.c \
exchange_api_stefan.c \
- exchange_api_transfers_get.c \
- exchange_api_withdraw.c \
- exchange_api_withdraw2.c
+ exchange_api_transfers_get.c
libtalerexchange_la_LIBADD = \
libtalerauditor.la \
$(top_builddir)/src/json/libtalerjson.la \
diff --git a/src/lib/exchange_api_age_withdraw.c b/src/lib/exchange_api_age_withdraw.c
index 4092c5c2c..ea9c0371e 100644
--- a/src/lib/exchange_api_age_withdraw.c
+++ b/src/lib/exchange_api_age_withdraw.c
@@ -396,27 +396,6 @@ handle_reserve_age_withdraw_blinded_finished (
GNUNET_assert (NULL == awbh->callback);
TALER_EXCHANGE_age_withdraw_blinded_cancel (awbh);
return;
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- /* only validate reply is well-formed */
- {
- uint64_t ptu;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint64 ("legitimization_uuid",
- &ptu),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j_response,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- awbr.hr.http_status = 0;
- awbr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- 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 */
@@ -452,6 +431,27 @@ handle_reserve_age_withdraw_blinded_finished (
awbr.hr.ec = TALER_JSON_get_error_code (j_response);
awbr.hr.hint = TALER_JSON_get_error_hint (j_response);
break;
+ case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ /* only validate reply is well-formed */
+ {
+ uint64_t ptu;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_uint64 ("requirement_row",
+ &ptu),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j_response,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ awbr.hr.http_status = 0;
+ awbr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ }
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
diff --git a/src/lib/exchange_api_batch_withdraw2.c b/src/lib/exchange_api_batch_withdraw2.c
index 12c6aeff3..b6f773197 100644
--- a/src/lib/exchange_api_batch_withdraw2.c
+++ b/src/lib/exchange_api_batch_withdraw2.c
@@ -193,28 +193,6 @@ handle_reserve_batch_withdraw_finished (void *cls,
GNUNET_assert (NULL == wh->cb);
TALER_EXCHANGE_batch_withdraw2_cancel (wh);
return;
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- /* only validate reply is well-formed */
- {
- uint64_t ptu;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint64 ("legitimization_uuid",
- &ptu),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- bwr.hr.http_status = 0;
- bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- }
- 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 */
@@ -249,6 +227,29 @@ handle_reserve_batch_withdraw_finished (void *cls,
bwr.hr.ec = TALER_JSON_get_error_code (j);
bwr.hr.hint = TALER_JSON_get_error_hint (j);
break;
+ case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ {
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto (
+ "h_payto",
+ &bwr.details.unavailable_for_legal_reasons.h_payto),
+ GNUNET_JSON_spec_uint64 ("requirement_row",
+ &bwr.details.unavailable_for_legal_reasons.
+ kyc_requirement_id),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ bwr.hr.http_status = 0;
+ bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ }
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c
deleted file mode 100644
index 87218989a..000000000
--- a/src/lib/exchange_api_withdraw.c
+++ /dev/null
@@ -1,364 +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/exchange_api_withdraw.c
- * @brief Implementation of /reserves/$RESERVE_PUB/withdraw requests with blinding/unblinding
- * @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_exchange_service.h"
-#include "taler_json_lib.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "exchange_api_curl_defaults.h"
-
-
-/**
- * @brief A Withdraw Handle
- */
-struct TALER_EXCHANGE_WithdrawHandle
-{
-
- /**
- * The curl context to use
- */
- struct GNUNET_CURL_Context *curl_ctx;
-
- /**
- * The base-URL to the exchange
- */
- const char *exchange_url;
-
- /**
- * The /keys material from the exchange
- */
- struct TALER_EXCHANGE_Keys *keys;
-
- /**
- * Handle for the actual (internal) withdraw operation.
- */
- struct TALER_EXCHANGE_Withdraw2Handle *wh2;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_WithdrawCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Reserve private key.
- */
- const struct TALER_ReservePrivateKeyP *reserve_priv;
-
- /**
- * Seed of the planchet.
- */
- struct TALER_PlanchetMasterSecretP ps;
-
- /**
- * blinding secret
- */
- union TALER_DenominationBlindingKeyP bks;
-
- /**
- * Private key of the coin we are withdrawing.
- */
- struct TALER_CoinSpendPrivateKeyP priv;
-
- /**
- * Details of the planchet.
- */
- struct TALER_PlanchetDetail pd;
-
- /**
- * Values of the @cipher selected
- */
- struct TALER_ExchangeWithdrawValues alg_values;
-
- /**
- * Hash of the age commitment for this coin, if applicable. Maybe NULL
- */
- const struct TALER_AgeCommitmentHash *ach;
-
- /**
- * Denomination key we are withdrawing.
- */
- struct TALER_EXCHANGE_DenomPublicKey pk;
-
- /**
- * Hash of the public key of the coin we are signing.
- */
- struct TALER_CoinPubHashP c_hash;
-
- /**
- * Handler for the CS R request (only used for TALER_DENOMINATION_CS denominations)
- */
- struct TALER_EXCHANGE_CsRWithdrawHandle *csrh;
-
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reserves/$RESERVE_PUB/withdraw request.
- *
- * @param cls the `struct TALER_EXCHANGE_WithdrawHandle`
- * @param w2r response data
- */
-static void
-handle_reserve_withdraw_finished (
- void *cls,
- const struct TALER_EXCHANGE_Withdraw2Response *w2r)
-{
- struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
- struct TALER_EXCHANGE_WithdrawResponse wr = {
- .hr = w2r->hr
- };
-
- wh->wh2 = NULL;
- switch (w2r->hr.http_status)
- {
- case MHD_HTTP_OK:
- {
- struct TALER_FreshCoin fc;
-
- if (GNUNET_OK !=
- TALER_planchet_to_coin (&wh->pk.key,
- &w2r->details.ok.blind_sig,
- &wh->bks,
- &wh->priv,
- wh->ach,
- &wh->c_hash,
- &wh->alg_values,
- &fc))
- {
- wr.hr.http_status = 0;
- wr.hr.ec = TALER_EC_EXCHANGE_WITHDRAW_UNBLIND_FAILURE;
- break;
- }
- wr.details.ok.coin_priv = wh->priv;
- wr.details.ok.bks = wh->bks;
- wr.details.ok.sig = fc.sig;
- wr.details.ok.exchange_vals = wh->alg_values;
- break;
- }
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- {
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &wr.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &wr.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (w2r->hr.reply,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- wr.hr.http_status = 0;
- wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- }
- break;
- default:
- break;
- }
- wh->cb (wh->cb_cls,
- &wr);
- if (MHD_HTTP_OK == w2r->hr.http_status)
- TALER_denom_sig_free (&wr.details.ok.sig);
- TALER_EXCHANGE_withdraw_cancel (wh);
-}
-
-
-/**
- * Function called when stage 1 of CS withdraw is finished (request r_pub's)
- *
- * @param cls the `struct TALER_EXCHANGE_WithdrawHandle`
- * @param csrr replies from the /csr-withdraw request
- */
-static void
-withdraw_cs_stage_two_callback (
- void *cls,
- const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr)
-{
- struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
- struct TALER_EXCHANGE_WithdrawResponse wr = {
- .hr = csrr->hr
- };
-
- wh->csrh = NULL;
- GNUNET_assert (TALER_DENOMINATION_CS == wh->pk.key.cipher);
- switch (csrr->hr.http_status)
- {
- case MHD_HTTP_OK:
- wh->alg_values = csrr->details.ok.alg_values;
- TALER_planchet_setup_coin_priv (&wh->ps,
- &wh->alg_values,
- &wh->priv);
- TALER_planchet_blinding_secret_create (&wh->ps,
- &wh->alg_values,
- &wh->bks);
- /* This initializes the 2nd half of the
- wh->pd.blinded_planchet! */
- if (GNUNET_OK !=
- TALER_planchet_prepare (&wh->pk.key,
- &wh->alg_values,
- &wh->bks,
- &wh->priv,
- wh->ach,
- &wh->c_hash,
- &wh->pd))
- {
- GNUNET_break (0);
- break;
- }
- wh->wh2 = TALER_EXCHANGE_withdraw2 (wh->curl_ctx,
- wh->exchange_url,
- wh->keys,
- &wh->pd,
- wh->reserve_priv,
- &handle_reserve_withdraw_finished,
- wh);
- return;
- default:
- break;
- }
- wh->cb (wh->cb_cls,
- &wr);
- TALER_EXCHANGE_withdraw_cancel (wh);
-}
-
-
-struct TALER_EXCHANGE_WithdrawHandle *
-TALER_EXCHANGE_withdraw (
- struct GNUNET_CURL_Context *curl_ctx,
- const char *exchange_url,
- struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_EXCHANGE_WithdrawCoinInput *wci,
- TALER_EXCHANGE_WithdrawCallback res_cb,
- void *res_cb_cls)
-{
- struct TALER_EXCHANGE_WithdrawHandle *wh;
-
- wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle);
- wh->keys = TALER_EXCHANGE_keys_incref (keys);
- wh->exchange_url = exchange_url;
- wh->curl_ctx = curl_ctx;
- wh->cb = res_cb;
- wh->cb_cls = res_cb_cls;
- wh->reserve_priv = reserve_priv;
- wh->ps = *wci->ps;
- wh->ach = wci->ach;
- wh->pk = *wci->pk;
- TALER_denom_pub_deep_copy (&wh->pk.key,
- &wci->pk->key);
-
- switch (wci->pk->key.cipher)
- {
- case TALER_DENOMINATION_RSA:
- {
- wh->alg_values.cipher = TALER_DENOMINATION_RSA;
- TALER_planchet_setup_coin_priv (&wh->ps,
- &wh->alg_values,
- &wh->priv);
- TALER_planchet_blinding_secret_create (&wh->ps,
- &wh->alg_values,
- &wh->bks);
- if (GNUNET_OK !=
- TALER_planchet_prepare (&wh->pk.key,
- &wh->alg_values,
- &wh->bks,
- &wh->priv,
- wh->ach,
- &wh->c_hash,
- &wh->pd))
- {
- GNUNET_break (0);
- GNUNET_free (wh);
- return NULL;
- }
- wh->wh2 = TALER_EXCHANGE_withdraw2 (curl_ctx,
- exchange_url,
- keys,
- &wh->pd,
- wh->reserve_priv,
- &handle_reserve_withdraw_finished,
- wh);
- break;
- }
- case TALER_DENOMINATION_CS:
- {
- TALER_cs_withdraw_nonce_derive (
- &wh->ps,
- &wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce);
- /* Note that we only initialize the first half
- of the blinded_planchet here; the other part
- will be done after the /csr-withdraw request! */
- wh->pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
- wh->csrh = TALER_EXCHANGE_csr_withdraw (
- curl_ctx,
- exchange_url,
- &wh->pk,
- &wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce,
- &withdraw_cs_stage_two_callback,
- wh);
- break;
- }
- default:
- GNUNET_break (0);
- GNUNET_free (wh);
- return NULL;
- }
- return wh;
-}
-
-
-void
-TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh)
-{
- TALER_blinded_planchet_free (&wh->pd.blinded_planchet);
- if (NULL != wh->csrh)
- {
- TALER_EXCHANGE_csr_withdraw_cancel (wh->csrh);
- wh->csrh = NULL;
- }
- if (NULL != wh->wh2)
- {
- TALER_EXCHANGE_withdraw2_cancel (wh->wh2);
- wh->wh2 = NULL;
- }
- TALER_EXCHANGE_keys_decref (wh->keys);
- TALER_denom_pub_free (&wh->pk.key);
- GNUNET_free (wh);
-}
diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c
deleted file mode 100644
index 53a5934d8..000000000
--- a/src/lib/exchange_api_withdraw2.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- 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/exchange_api_withdraw2.c
- * @brief Implementation of /reserves/$RESERVE_PUB/withdraw requests without blinding/unblinding
- * @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_exchange_service.h"
-#include "taler_json_lib.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "exchange_api_curl_defaults.h"
-
-
-/**
- * @brief A Withdraw Handle
- */
-struct TALER_EXCHANGE_Withdraw2Handle
-{
-
- /**
- * The /keys material from the exchange
- */
- struct TALER_EXCHANGE_Keys *keys;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_Withdraw2Callback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Context for #TEH_curl_easy_post(). Keeps the data that must
- * persist for Curl to make the upload.
- */
- struct TALER_CURL_PostContext post_ctx;
-
- /**
- * Total amount requested (value plus withdraw fee).
- */
- struct TALER_Amount requested_amount;
-
- /**
- * Public key of the reserve we are withdrawing from.
- */
- struct TALER_ReservePublicKeyP reserve_pub;
-
-};
-
-
-/**
- * We got a 200 OK response for the /reserves/$RESERVE_PUB/withdraw operation.
- * Extract the coin's signature and return it to the caller. The signature we
- * get from the exchange is for the blinded value. Thus, we first must
- * unblind it and then should verify its validity against our coin's hash.
- *
- * If everything checks out, we return the unblinded signature
- * to the application via the callback.
- *
- * @param wh operation handle
- * @param json reply from the exchange
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static enum GNUNET_GenericReturnValue
-reserve_withdraw_ok (struct TALER_EXCHANGE_Withdraw2Handle *wh,
- const json_t *json)
-{
- struct TALER_EXCHANGE_Withdraw2Response w2r = {
- .hr.reply = json,
- .hr.http_status = MHD_HTTP_OK
- };
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_blinded_denom_sig ("ev_sig",
- &w2r.details.ok.blind_sig),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* signature is valid, return it to the application */
- wh->cb (wh->cb_cls,
- &w2r);
- /* make sure callback isn't called again after return */
- wh->cb = NULL;
- GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reserves/$RESERVE_PUB/withdraw request.
- *
- * @param cls the `struct TALER_EXCHANGE_WithdrawHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_reserve_withdraw_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_Withdraw2Handle *wh = cls;
- const json_t *j = response;
- struct TALER_EXCHANGE_Withdraw2Response w2r = {
- .hr.reply = j,
- .hr.http_status = (unsigned int) response_code
- };
-
- wh->job = NULL;
- switch (response_code)
- {
- case 0:
- w2r.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- reserve_withdraw_ok (wh,
- j))
- {
- GNUNET_break_op (0);
- w2r.hr.http_status = 0;
- w2r.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- GNUNET_assert (NULL == wh->cb);
- TALER_EXCHANGE_withdraw2_cancel (wh);
- return;
- 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 */
- w2r.hr.ec = TALER_JSON_get_error_code (j);
- w2r.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_FORBIDDEN:
- GNUNET_break_op (0);
- /* 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 */
- w2r.hr.ec = TALER_JSON_get_error_code (j);
- w2r.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, the exchange basically just says
- that it doesn't know this reserve. Can happen if we
- query before the wire transfer went through.
- We should simply pass the JSON reply to the application. */
- w2r.hr.ec = TALER_JSON_get_error_code (j);
- w2r.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_CONFLICT:
- w2r.hr.ec = TALER_JSON_get_error_code (j);
- w2r.hr.hint = TALER_JSON_get_error_hint (j);
- 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 */
- w2r.hr.ec = TALER_JSON_get_error_code (j);
- w2r.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- /* only validate reply is well-formed */
- {
- uint64_t ptu;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint64 ("requirement_row",
- &ptu),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- w2r.hr.http_status = 0;
- w2r.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- }
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- w2r.hr.ec = TALER_JSON_get_error_code (j);
- w2r.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- default:
- /* unexpected response code */
- GNUNET_break_op (0);
- w2r.hr.ec = TALER_JSON_get_error_code (j);
- w2r.hr.hint = TALER_JSON_get_error_hint (j);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for exchange withdraw\n",
- (unsigned int) response_code,
- (int) w2r.hr.ec);
- break;
- }
- if (NULL != wh->cb)
- {
- wh->cb (wh->cb_cls,
- &w2r);
- wh->cb = NULL;
- }
- TALER_EXCHANGE_withdraw2_cancel (wh);
-}
-
-
-struct TALER_EXCHANGE_Withdraw2Handle *
-TALER_EXCHANGE_withdraw2 (
- struct GNUNET_CURL_Context *curl_ctx,
- const char *exchange_url,
- struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_PlanchetDetail *pd,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- TALER_EXCHANGE_Withdraw2Callback res_cb,
- void *res_cb_cls)
-{
- struct TALER_EXCHANGE_Withdraw2Handle *wh;
- const struct TALER_EXCHANGE_DenomPublicKey *dk;
- struct TALER_ReserveSignatureP reserve_sig;
- char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
- struct TALER_BlindedCoinHashP bch;
-
- GNUNET_assert (NULL != keys);
- dk = TALER_EXCHANGE_get_denomination_key_by_hash (keys,
- &pd->denom_pub_hash);
- if (NULL == dk)
- {
- GNUNET_break (0);
- return NULL;
- }
- wh = GNUNET_new (struct TALER_EXCHANGE_Withdraw2Handle);
- wh->keys = TALER_EXCHANGE_keys_incref (keys);
- wh->cb = res_cb;
- wh->cb_cls = res_cb_cls;
- /* Compute how much we expected to charge to the reserve */
- if (0 >
- TALER_amount_add (&wh->requested_amount,
- &dk->value,
- &dk->fees.withdraw))
- {
- /* Overflow here? Very strange, our CPU must be fried... */
- GNUNET_break (0);
- GNUNET_free (wh);
- return NULL;
- }
-
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
- &wh->reserve_pub.eddsa_pub);
-
- {
- char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2];
- char *end;
-
- end = GNUNET_STRINGS_data_to_string (
- &wh->reserve_pub,
- sizeof (struct TALER_ReservePublicKeyP),
- pub_str,
- sizeof (pub_str));
- *end = '\0';
- GNUNET_snprintf (arg_str,
- sizeof (arg_str),
- "reserves/%s/withdraw",
- pub_str);
- }
-
- if (GNUNET_OK !=
- TALER_coin_ev_hash (&pd->blinded_planchet,
- &pd->denom_pub_hash,
- &bch))
- {
- GNUNET_break (0);
- GNUNET_free (wh);
- return NULL;
- }
-
- TALER_wallet_withdraw_sign (&pd->denom_pub_hash,
- &wh->requested_amount,
- &bch,
- reserve_priv,
- &reserve_sig);
- {
- json_t *withdraw_obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("denom_pub_hash",
- &pd->denom_pub_hash),
- TALER_JSON_pack_blinded_planchet ("coin_ev",
- &pd->blinded_planchet),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &reserve_sig));
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Attempting to withdraw from reserve %s\n",
- TALER_B2S (&wh->reserve_pub));
- wh->url = TALER_url_join (exchange_url,
- arg_str,
- NULL);
- if (NULL == wh->url)
- {
- json_decref (withdraw_obj);
- GNUNET_free (wh);
- return NULL;
- }
- {
- CURL *eh;
-
- eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
- if ( (NULL == eh) ||
- (GNUNET_OK !=
- TALER_curl_easy_post (&wh->post_ctx,
- eh,
- withdraw_obj)) )
- {
- GNUNET_break (0);
- if (NULL != eh)
- curl_easy_cleanup (eh);
- json_decref (withdraw_obj);
- GNUNET_free (wh->url);
- GNUNET_free (wh);
- return NULL;
- }
- json_decref (withdraw_obj);
- wh->job = GNUNET_CURL_job_add2 (curl_ctx,
- eh,
- wh->post_ctx.headers,
- &handle_reserve_withdraw_finished,
- wh);
- }
- }
- return wh;
-}
-
-
-void
-TALER_EXCHANGE_withdraw2_cancel (struct TALER_EXCHANGE_Withdraw2Handle *wh)
-{
- if (NULL != wh->job)
- {
- GNUNET_CURL_job_cancel (wh->job);
- wh->job = NULL;
- }
- GNUNET_free (wh->url);
- TALER_curl_easy_post_finished (&wh->post_ctx);
- TALER_EXCHANGE_keys_decref (wh->keys);
- GNUNET_free (wh);
-}