commit 1eadd66ae0c4abe6867321bcac0ad2f9832a0baf
parent cc47c5c701340c9be0acc6b7394aa2afad0cd0d3
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 19 Sep 2015 22:08:49 +0200
renaming /withdraw to /reserve (#3968)
Diffstat:
21 files changed, 1369 insertions(+), 1364 deletions(-)
diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h
@@ -547,13 +547,13 @@ void
TALER_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit);
-/* ********************* /withdraw/status *********************** */
+/* ********************* /reserve/status *********************** */
/**
- * @brief A /withdraw/status Handle
+ * @brief A /reserve/status Handle
*/
-struct TALER_MINT_WithdrawStatusHandle;
+struct TALER_MINT_ReserveStatusHandle;
/**
@@ -623,12 +623,12 @@ struct TALER_MINT_ReserveHistory
* @param history detailed transaction history, NULL on error
*/
typedef void
-(*TALER_MINT_WithdrawStatusResultCallback) (void *cls,
- unsigned int http_status,
- json_t *json,
- const struct TALER_Amount *balance,
- unsigned int history_length,
- const struct TALER_MINT_ReserveHistory *history);
+(*TALER_MINT_ReserveStatusResultCallback) (void *cls,
+ unsigned int http_status,
+ json_t *json,
+ const struct TALER_Amount *balance,
+ unsigned int history_length,
+ const struct TALER_MINT_ReserveHistory *history);
/**
@@ -647,11 +647,11 @@ typedef void
* @return a handle for this request; NULL if the inputs are invalid (i.e.
* signatures fail to verify). In this case, the callback is not called.
*/
-struct TALER_MINT_WithdrawStatusHandle *
-TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- TALER_MINT_WithdrawStatusResultCallback cb,
- void *cb_cls);
+struct TALER_MINT_ReserveStatusHandle *
+TALER_MINT_reserve_status (struct TALER_MINT_Handle *mint,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ TALER_MINT_ReserveStatusResultCallback cb,
+ void *cb_cls);
/**
@@ -661,16 +661,16 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
* @param wsh the withdraw status request handle
*/
void
-TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh);
+TALER_MINT_reserve_status_cancel (struct TALER_MINT_ReserveStatusHandle *wsh);
-/* ********************* /withdraw/sign *********************** */
+/* ********************* /reserve/withdraw *********************** */
/**
- * @brief A /withdraw/sign Handle
+ * @brief A /reserve/withdraw Handle
*/
-struct TALER_MINT_WithdrawSignHandle;
+struct TALER_MINT_ReserveWithdrawHandle;
/**
@@ -684,14 +684,14 @@ struct TALER_MINT_WithdrawSignHandle;
* @param full_response full response from the mint (for logging, in case of errors)
*/
typedef void
-(*TALER_MINT_WithdrawSignResultCallback) (void *cls,
- unsigned int http_status,
- const struct TALER_DenominationSignature *sig,
- json_t *full_response);
+(*TALER_MINT_ReserveWithdrawResultCallback) (void *cls,
+ unsigned int http_status,
+ const struct TALER_DenominationSignature *sig,
+ json_t *full_response);
/**
- * Withdraw a coin from the mint using a /withdraw/sign request. This
+ * Withdraw a coin from the mint using a /reserve/withdraw request. This
* API is typically used by a wallet. Note that to ensure that no
* money is lost in case of hardware failures, the caller must have
* committed (most of) the arguments to disk before calling, and be
@@ -711,14 +711,14 @@ typedef void
* if the inputs are invalid (i.e. denomination key not with this mint).
* In this case, the callback is not called.
*/
-struct TALER_MINT_WithdrawSignHandle *
-TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
- const struct TALER_MINT_DenomPublicKey *pk,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_DenominationBlindingKey *blinding_key,
- TALER_MINT_WithdrawSignResultCallback res_cb,
- void *res_cb_cls);
+struct TALER_MINT_ReserveWithdrawHandle *
+TALER_MINT_reserve_withdraw (struct TALER_MINT_Handle *mint,
+ const struct TALER_MINT_DenomPublicKey *pk,
+ const struct TALER_ReservePrivateKeyP *reserve_priv,
+ const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+ const struct TALER_DenominationBlindingKey *blinding_key,
+ TALER_MINT_ReserveWithdrawResultCallback res_cb,
+ void *res_cb_cls);
/**
@@ -728,7 +728,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
* @param sign the withdraw sign request handle
*/
void
-TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign);
+TALER_MINT_reserve_withdraw_cancel (struct TALER_MINT_ReserveWithdrawHandle *sign);
/* ********************* /refresh/melt+reveal ***************************** */
diff --git a/src/mint-lib/Makefile.am b/src/mint-lib/Makefile.am
@@ -22,8 +22,8 @@ libtalermint_la_SOURCES = \
mint_api_deposit.c \
mint_api_refresh.c \
mint_api_refresh_link.c \
- mint_api_wire.c \
- mint_api_withdraw.c
+ mint_api_reserve.c \
+ mint_api_wire.c
libtalermint_la_LIBADD = \
-lgnunetutil \
diff --git a/src/mint-lib/mint_api_handle.c b/src/mint-lib/mint_api_handle.c
@@ -686,7 +686,7 @@ MAH_handle_is_ready (struct TALER_MINT_Handle *h)
* Obtain the URL to use for an API request.
*
* @param h the mint handle to query
- * @param path Taler API path (i.e. "/withdraw/sign")
+ * @param path Taler API path (i.e. "/reserve/withdraw")
* @return the full URI to use with cURL
*/
char *
diff --git a/src/mint-lib/mint_api_handle.h b/src/mint-lib/mint_api_handle.h
@@ -48,7 +48,7 @@ MAH_handle_is_ready (struct TALER_MINT_Handle *h);
* Obtain the URL to use for an API request.
*
* @param h the mint handle to query
- * @param path Taler API path (i.e. "/withdraw/sign")
+ * @param path Taler API path (i.e. "/reserve/withdraw")
* @return the full URI to use with cURL
*/
char *
diff --git a/src/mint-lib/mint_api_reserve.c b/src/mint-lib/mint_api_reserve.c
@@ -0,0 +1,927 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
+
+ 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, If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file mint-lib/mint_api_reserve.c
+ * @brief Implementation of the /reserve requests of the mint's HTTP API
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include "taler_mint_service.h"
+#include "mint_api_json.h"
+#include "mint_api_context.h"
+#include "mint_api_handle.h"
+#include "taler_signatures.h"
+
+
+/* ********************** /reserve/status ********************** */
+
+/**
+ * @brief A Withdraw Status Handle
+ */
+struct TALER_MINT_ReserveStatusHandle
+{
+
+ /**
+ * The connection to mint this request handle will use
+ */
+ struct TALER_MINT_Handle *mint;
+
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * Handle for the request.
+ */
+ struct MAC_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_MINT_ReserveStatusResultCallback cb;
+
+ /**
+ * Public key of the reserve we are querying.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Download buffer
+ */
+ struct MAC_DownloadBuffer db;
+
+};
+
+
+/**
+ * Parse history given in JSON format and return it in binary
+ * format.
+ *
+ * @param[in] history JSON array with the history
+ * @param reserve_pub public key of the reserve to inspect
+ * @param currency currency we expect the balance to be in
+ * @param[out] balance final balance
+ * @param history_length number of entries in @a history
+ * @param[out] rhistory array of length @a history_length, set to the
+ * parsed history entries
+ * @return #GNUNET_OK if history was valid and @a rhistory and @a balance
+ * were set,
+ * #GNUNET_SYSERR if there was a protocol violation in @a history
+ */
+static int
+parse_reserve_history (json_t *history,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const char *currency,
+ struct TALER_Amount *balance,
+ unsigned int history_length,
+ struct TALER_MINT_ReserveHistory *rhistory)
+{
+ struct GNUNET_HashCode uuid[history_length];
+ unsigned int uuid_off;
+ struct TALER_Amount total_in;
+ struct TALER_Amount total_out;
+ size_t off;
+
+ TALER_amount_get_zero (currency,
+ &total_in);
+ TALER_amount_get_zero (currency,
+ &total_out);
+ uuid_off = 0;
+ for (off=0;off<history_length;off++)
+ {
+ json_t *transaction;
+ struct TALER_Amount amount;
+ const char *type;
+ struct MAJ_Specification hist_spec[] = {
+ MAJ_spec_string ("type", &type),
+ MAJ_spec_amount ("amount",
+ &amount),
+ /* 'wire' and 'signature' are optional depending on 'type'! */
+ MAJ_spec_end
+ };
+
+ transaction = json_array_get (history,
+ off);
+ if (GNUNET_OK !=
+ MAJ_parse_json (transaction,
+ hist_spec))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ rhistory[off].amount = amount;
+
+ if (0 == strcasecmp (type,
+ "DEPOSIT"))
+ {
+ json_t *wire;
+
+ rhistory[off].type = TALER_MINT_RTT_DEPOSIT;
+ if (GNUNET_OK !=
+ TALER_amount_add (&total_in,
+ &total_in,
+ &amount))
+ {
+ /* overflow in history already!? inconceivable! Bad mint! */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ wire = json_object_get (transaction,
+ "wire");
+ /* check 'wire' is a JSON object (no need to check wireformat,
+ but we do at least expect "some" JSON object here) */
+ if ( (NULL == wire) ||
+ (! json_is_object (wire)) )
+ {
+ /* not even a JSON 'wire' specification, not acceptable */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ rhistory[off].details.wire_in_details = wire;
+ /* end type==DEPOSIT */
+ }
+ else if (0 == strcasecmp (type,
+ "WITHDRAW"))
+ {
+ struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+ const struct TALER_WithdrawRequestPS *withdraw_purpose;
+ struct TALER_Amount amount_from_purpose;
+ struct MAJ_Specification withdraw_spec[] = {
+ MAJ_spec_eddsa_signed_purpose ("signature",
+ &purpose,
+ &reserve_pub->eddsa_pub),
+ MAJ_spec_end
+ };
+ unsigned int i;
+
+ rhistory[off].type = TALER_MINT_RTT_WITHDRAWAL;
+ if (GNUNET_OK !=
+ MAJ_parse_json (transaction,
+ withdraw_spec))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ /* Check that the signature actually signed a withdraw request */
+ if ( (ntohl (purpose->purpose) != TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW) ||
+ (ntohl (purpose->size) != sizeof (struct TALER_WithdrawRequestPS)) )
+ {
+ GNUNET_break_op (0);
+ MAJ_parse_free (withdraw_spec);
+ return GNUNET_SYSERR;
+ }
+ withdraw_purpose = (const struct TALER_WithdrawRequestPS *) purpose;
+ TALER_amount_ntoh (&amount_from_purpose,
+ &withdraw_purpose->amount_with_fee);
+ if (0 != TALER_amount_cmp (&amount,
+ &amount_from_purpose))
+ {
+ GNUNET_break_op (0);
+ MAJ_parse_free (withdraw_spec);
+ return GNUNET_SYSERR;
+ }
+ rhistory[off].details.out_authorization_sig = json_object_get (transaction,
+ "signature");
+ /* Check check that the same withdraw transaction
+ isn't listed twice by the mint. We use the
+ "uuid" array to remember the hashes of all
+ purposes, and compare the hashes to find
+ duplicates. */
+ GNUNET_CRYPTO_hash (withdraw_purpose,
+ ntohl (withdraw_purpose->purpose.size),
+ &uuid[uuid_off]);
+ for (i=0;i<uuid_off;i++)
+ {
+ if (0 == memcmp (&uuid[uuid_off],
+ &uuid[i],
+ sizeof (struct GNUNET_HashCode)))
+ {
+ GNUNET_break_op (0);
+ MAJ_parse_free (withdraw_spec);
+ return GNUNET_SYSERR;
+ }
+ }
+ uuid_off++;
+
+ if (GNUNET_OK !=
+ TALER_amount_add (&total_out,
+ &total_out,
+ &amount))
+ {
+ /* overflow in history already!? inconceivable! Bad mint! */
+ GNUNET_break_op (0);
+ MAJ_parse_free (withdraw_spec);
+ return GNUNET_SYSERR;
+ }
+ /* end type==WITHDRAW */
+ }
+ else
+ {
+ /* unexpected 'type', protocol incompatibility, complain! */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ }
+
+ /* check balance = total_in - total_out < withdraw-amount */
+ if (GNUNET_SYSERR ==
+ TALER_amount_subtract (balance,
+ &total_in,
+ &total_out))
+ {
+ /* total_in < total_out, why did the mint ever allow this!? */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /reserve/status request.
+ *
+ * @param cls the `struct TALER_MINT_ReserveStatusHandle`
+ * @param eh curl handle of the request that finished
+ */
+static void
+handle_reserve_status_finished (void *cls,
+ CURL *eh)
+{
+ struct TALER_MINT_ReserveStatusHandle *wsh = cls;
+ long response_code;
+ json_t *json;
+
+ wsh->job = NULL;
+ json = MAC_download_get_result (&wsh->db,
+ eh,
+ &response_code);
+ switch (response_code)
+ {
+ case 0:
+ break;
+ case MHD_HTTP_OK:
+ {
+ /* TODO: move into separate function... */
+ json_t *history;
+ unsigned int len;
+ struct TALER_Amount balance;
+ struct TALER_Amount balance_from_history;
+ struct MAJ_Specification spec[] = {
+ MAJ_spec_amount ("balance", &balance),
+ MAJ_spec_end
+ };
+
+ if (GNUNET_OK !=
+ MAJ_parse_json (json,
+ spec))
+ {
+ GNUNET_break_op (0);
+ response_code = 0;
+ break;
+ }
+ history = json_object_get (json,
+ "history");
+ if (NULL == history)
+ {
+ GNUNET_break_op (0);
+ response_code = 0;
+ break;
+ }
+ len = json_array_size (history);
+ {
+ struct TALER_MINT_ReserveHistory rhistory[len];
+
+ if (GNUNET_OK !=
+ parse_reserve_history (history,
+ &wsh->reserve_pub,
+ balance.currency,
+ &balance_from_history,
+ len,
+ rhistory))
+ {
+ GNUNET_break_op (0);
+ response_code = 0;
+ break;
+ }
+ if (0 !=
+ TALER_amount_cmp (&balance_from_history,
+ &balance))
+ {
+ /* mint cannot add up balances!? */
+ GNUNET_break_op (0);
+ response_code = 0;
+ break;
+ }
+ wsh->cb (wsh->cb_cls,
+ response_code,
+ json,
+ &balance,
+ len,
+ rhistory);
+ wsh->cb = NULL;
+ }
+ }
+ break;
+ case MHD_HTTP_BAD_REQUEST:
+ /* This should never happen, either us or the mint is buggy
+ (or API version conflict); just pass JSON reply to the application */
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the application */
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry, but this API
+ leaves this to the application */
+ break;
+ default:
+ /* unexpected response code */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u\n",
+ response_code);
+ GNUNET_break (0);
+ response_code = 0;
+ break;
+ }
+ if (NULL != wsh->cb)
+ wsh->cb (wsh->cb_cls,
+ response_code,
+ json,
+ NULL,
+ 0, NULL);
+ json_decref (json);
+ TALER_MINT_reserve_status_cancel (wsh);
+}
+
+
+/**
+ * Submit a request to obtain the transaction history of a reserve
+ * from the mint. Note that while we return the full response to the
+ * caller for further processing, we do already verify that the
+ * response is well-formed (i.e. that signatures included in the
+ * response are all valid and add up to the balance). If the mint's
+ * reply is not well-formed, we return an HTTP status code of zero to
+ * @a cb.
+ *
+ * @param mint the mint handle; the mint must be ready to operate
+ * @param reserve_pub public key of the reserve to inspect
+ * @param cb the callback to call when a reply for this request is available
+ * @param cb_cls closure for the above callback
+ * @return a handle for this request; NULL if the inputs are invalid (i.e.
+ * signatures fail to verify). In this case, the callback is not called.
+ */
+struct TALER_MINT_ReserveStatusHandle *
+TALER_MINT_reserve_status (struct TALER_MINT_Handle *mint,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ TALER_MINT_ReserveStatusResultCallback cb,
+ void *cb_cls)
+{
+ struct TALER_MINT_ReserveStatusHandle *wsh;
+ struct TALER_MINT_Context *ctx;
+ CURL *eh;
+ char *pub_str;
+ char *arg_str;
+
+ if (GNUNET_YES !=
+ MAH_handle_is_ready (mint))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ pub_str = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
+ sizeof (struct TALER_ReservePublicKeyP));
+ GNUNET_asprintf (&arg_str,
+ "/reserve/status?reserve_pub=%s",
+ pub_str);
+ GNUNET_free (pub_str);
+ wsh = GNUNET_new (struct TALER_MINT_ReserveStatusHandle);
+ wsh->mint = mint;
+ wsh->cb = cb;
+ wsh->cb_cls = cb_cls;
+ wsh->reserve_pub = *reserve_pub;
+ wsh->url = MAH_path_to_url (mint,
+ arg_str);
+ GNUNET_free (arg_str);
+
+ eh = curl_easy_init ();
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ wsh->url));
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_WRITEFUNCTION,
+ &MAC_download_cb));
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_WRITEDATA,
+ &wsh->db));
+ ctx = MAH_handle_to_context (mint);
+ wsh->job = MAC_job_add (ctx,
+ eh,
+ GNUNET_NO,
+ &handle_reserve_status_finished,
+ wsh);
+ return wsh;
+}
+
+
+/**
+ * Cancel a withdraw status request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param wsh the withdraw status request handle
+ */
+void
+TALER_MINT_reserve_status_cancel (struct TALER_MINT_ReserveStatusHandle *wsh)
+{
+ if (NULL != wsh->job)
+ {
+ MAC_job_cancel (wsh->job);
+ wsh->job = NULL;
+ }
+ GNUNET_free_non_null (wsh->db.buf);
+ GNUNET_free (wsh->url);
+ GNUNET_free (wsh);
+}
+
+
+/* ********************** /reserve/withdraw ********************** */
+
+/**
+ * @brief A Withdraw Sign Handle
+ */
+struct TALER_MINT_ReserveWithdrawHandle
+{
+
+ /**
+ * The connection to mint this request handle will use
+ */
+ struct TALER_MINT_Handle *mint;
+
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * JSON encoding of the request to POST.
+ */
+ char *json_enc;
+
+ /**
+ * Handle for the request.
+ */
+ struct MAC_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_MINT_ReserveWithdrawResultCallback cb;
+
+ /**
+ * Key used to blind the value.
+ */
+ const struct TALER_DenominationBlindingKey *blinding_key;
+
+ /**
+ * Denomination key we are withdrawing.
+ */
+ const struct TALER_MINT_DenomPublicKey *pk;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Download buffer
+ */
+ struct MAC_DownloadBuffer db;
+
+ /**
+ * Hash of the public key of the coin we are signing.
+ */
+ struct GNUNET_HashCode c_hash;
+
+ /**
+ * Public key of the reserve we are withdrawing from.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+};
+
+
+/**
+ * We got a 200 OK response for the /reserve/withdraw operation.
+ * Extract the coin's signature and return it to the caller.
+ * The signature we get from the mint 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 wsh operation handle
+ * @param json reply from the mint
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
+ */
+static int
+reserve_withdraw_ok (struct TALER_MINT_ReserveWithdrawHandle *wsh,
+ json_t *json)
+{
+ struct GNUNET_CRYPTO_rsa_Signature *blind_sig;
+ struct GNUNET_CRYPTO_rsa_Signature *sig;
+ struct TALER_DenominationSignature dsig;
+ struct MAJ_Specification spec[] = {
+ MAJ_spec_rsa_signature ("ev_sig", &blind_sig),
+ MAJ_spec_end
+ };
+
+ if (GNUNET_OK !=
+ MAJ_parse_json (json,
+ spec))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ sig = GNUNET_CRYPTO_rsa_unblind (blind_sig,
+ wsh->blinding_key->rsa_blinding_key,
+ wsh->pk->key.rsa_public_key);
+ GNUNET_CRYPTO_rsa_signature_free (blind_sig);
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_rsa_verify (&wsh->c_hash,
+ sig,
+ wsh->pk->key.rsa_public_key))
+ {
+ GNUNET_break_op (0);
+ GNUNET_CRYPTO_rsa_signature_free (sig);
+ return GNUNET_SYSERR;
+ }
+ /* signature is valid, return it to the application */
+ dsig.rsa_signature = sig;
+ wsh->cb (wsh->cb_cls,
+ MHD_HTTP_OK,
+ &dsig,
+ json);
+ /* make sure callback isn't called again after return */
+ wsh->cb = NULL;
+ GNUNET_CRYPTO_rsa_signature_free (sig);
+ return GNUNET_OK;
+}
+
+
+/**
+ * We got a 402 PAYMENT REQUIRED response for the /reserve/withdraw operation.
+ * Check the signatures on the withdraw transactions in the provided
+ * history and that the balances add up. We don't do anything directly
+ * with the information, as the JSON will be returned to the application.
+ * However, our job is ensuring that the mint followed the protocol, and
+ * this in particular means checking all of the signatures in the history.
+ *
+ * @param wsh operation handle
+ * @param json reply from the mint
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
+ */
+static int
+reserve_withdraw_payment_required (struct TALER_MINT_ReserveWithdrawHandle *wsh,
+ json_t *json)
+{
+ struct TALER_Amount balance;
+ struct TALER_Amount balance_from_history;
+ struct TALER_Amount requested_amount;
+ json_t *history;
+ size_t len;
+ struct MAJ_Specification spec[] = {
+ MAJ_spec_amount ("balance", &balance),
+ MAJ_spec_end
+ };
+
+ if (GNUNET_OK !=
+ MAJ_parse_json (json,
+ spec))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ history = json_object_get (json,
+ "history");
+ if (NULL == history)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ /* go over transaction history and compute
+ total incoming and outgoing amounts */
+ len = json_array_size (history);
+ {
+ struct TALER_MINT_ReserveHistory rhistory[len];
+
+ if (GNUNET_OK !=
+ parse_reserve_history (history,
+ &wsh->reserve_pub,
+ balance.currency,
+ &balance_from_history,
+ len,
+ rhistory))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ }
+
+ if (0 !=
+ TALER_amount_cmp (&balance_from_history,
+ &balance))
+ {
+ /* mint cannot add up balances!? */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ /* Compute how much we expected to charge to the reserve */
+ if (GNUNET_OK !=
+ TALER_amount_add (&requested_amount,
+ &wsh->pk->value,
+ &wsh->pk->fee_withdraw))
+ {
+ /* Overflow here? Very strange, our CPU must be fried... */
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ /* Check that funds were really insufficient */
+ if (0 >= TALER_amount_cmp (&requested_amount,
+ &balance))
+ {
+ /* Requested amount is smaller or equal to reported balance,
+ so this should not have failed. */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /reserve/withdraw request.
+ *
+ * @param cls the `struct TALER_MINT_ReserveWithdrawHandle`
+ * @param eh curl handle of the request that finished
+ */
+static void
+handle_reserve_withdraw_finished (void *cls,
+ CURL *eh)
+{
+ struct TALER_MINT_ReserveWithdrawHandle *wsh = cls;
+ long response_code;
+ json_t *json;
+
+ wsh->job = NULL;
+ json = MAC_download_get_result (&wsh->db,
+ eh,
+ &response_code);
+ switch (response_code)
+ {
+ case 0:
+ break;
+ case MHD_HTTP_OK:
+ if (GNUNET_OK !=
+ reserve_withdraw_ok (wsh,
+ json))
+ {
+ GNUNET_break_op (0);
+ response_code = 0;
+ }
+ break;
+ case MHD_HTTP_BAD_REQUEST:
+ /* This should never happen, either us or the mint is buggy
+ (or API version conflict); just pass JSON reply to the application */
+ break;
+ case MHD_HTTP_PAYMENT_REQUIRED:
+ /* The mint says that the reserve has insufficient funds;
+ check the signatures in the history... */
+ if (GNUNET_OK !=
+ reserve_withdraw_payment_required (wsh,
+ json))
+ {
+ GNUNET_break_op (0);
+ response_code = 0;
+ }
+ break;
+ case MHD_HTTP_UNAUTHORIZED:
+ GNUNET_break (0);
+ /* Nothing really to verify, mint 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:
+ /* Nothing really to verify, the mint 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. */
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry, but this API
+ leaves this to the application */
+ break;
+ default:
+ /* unexpected response code */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u\n",
+ response_code);
+ GNUNET_break (0);
+ response_code = 0;
+ break;
+ }
+ if (NULL != wsh->cb)
+ wsh->cb (wsh->cb_cls,
+ response_code,
+ NULL,
+ json);
+ json_decref (json);
+ TALER_MINT_reserve_withdraw_cancel (wsh);
+}
+
+
+/**
+ * Withdraw a coin from the mint using a /reserve/withdraw request. Note
+ * that to ensure that no money is lost in case of hardware failures,
+ * the caller must have committed (most of) the arguments to disk
+ * before calling, and be ready to repeat the request with the same
+ * arguments in case of failures.
+ *
+ * @param mint the mint handle; the mint must be ready to operate
+ * @param pk kind of coin to create
+ * @param reserve_priv private key of the reserve to withdraw from
+ * @param coin_priv where to store the coin's private key,
+ * caller must have committed this value to disk before the call (with @a pk)
+ * @param blinding_key where to store the coin's blinding key
+ * caller must have committed this value to disk before the call (with @a pk)
+ * @param res_cb the callback to call when the final result for this request is available
+ * @param res_cb_cls closure for the above callback
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR
+ * if the inputs are invalid (i.e. denomination key not with this mint).
+ * In this case, the callback is not called.
+ */
+struct TALER_MINT_ReserveWithdrawHandle *
+TALER_MINT_reserve_withdraw (struct TALER_MINT_Handle *mint,
+ const struct TALER_MINT_DenomPublicKey *pk,
+ const struct TALER_ReservePrivateKeyP *reserve_priv,
+ const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+ const struct TALER_DenominationBlindingKey *blinding_key,
+ TALER_MINT_ReserveWithdrawResultCallback res_cb,
+ void *res_cb_cls)
+{
+ struct TALER_MINT_ReserveWithdrawHandle *wsh;
+ struct TALER_WithdrawRequestPS req;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_MINT_Context *ctx;
+ struct TALER_Amount amount_with_fee;
+ char *coin_ev;
+ size_t coin_ev_size;
+ json_t *withdraw_obj;
+ CURL *eh;
+
+ wsh = GNUNET_new (struct TALER_MINT_ReserveWithdrawHandle);
+ wsh->mint = mint;
+ wsh->cb = res_cb;
+ wsh->cb_cls = res_cb_cls;
+ wsh->pk = pk;
+
+ GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
+ &coin_pub.eddsa_pub);
+ GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
+ &wsh->c_hash);
+ coin_ev_size = GNUNET_CRYPTO_rsa_blind (&wsh->c_hash,
+ blinding_key->rsa_blinding_key,
+ pk->key.rsa_public_key,
+ &coin_ev);
+ GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
+ &wsh->reserve_pub.eddsa_pub);
+ req.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
+ req.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
+ req.reserve_pub = wsh->reserve_pub;
+ if (GNUNET_OK !=
+ TALER_amount_add (&amount_with_fee,
+ &pk->fee_withdraw,
+ &pk->value))
+ {
+ /* mint gave us denomination keys that overflow like this!? */
+ GNUNET_break_op (0);
+ GNUNET_free (coin_ev);
+ GNUNET_free (wsh);
+ return NULL;
+ }
+ TALER_amount_hton (&req.amount_with_fee,
+ &amount_with_fee);
+ TALER_amount_hton (&req.withdraw_fee,
+ &pk->fee_withdraw);
+ GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key,
+ &req.h_denomination_pub);
+ GNUNET_CRYPTO_hash (coin_ev,
+ coin_ev_size,
+ &req.h_coin_envelope);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
+ &req.purpose,
+ &reserve_sig.eddsa_signature));
+ withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */
+ " s:o, s:o}",/* reserve_pub and reserve_sig */
+ "denom_pub", TALER_json_from_rsa_public_key (pk->key.rsa_public_key),
+ "coin_ev", TALER_json_from_data (coin_ev,
+ coin_ev_size),
+ "reserve_pub", TALER_json_from_data (&wsh->reserve_pub,
+ sizeof (struct TALER_ReservePublicKeyP)),
+ "reserve_sig", TALER_json_from_data (&reserve_sig,
+ sizeof (reserve_sig)));
+ GNUNET_free (coin_ev);
+
+ wsh->blinding_key = blinding_key;
+ wsh->url = MAH_path_to_url (mint, "/reserve/withdraw");
+
+ eh = curl_easy_init ();
+ GNUNET_assert (NULL != (wsh->json_enc =
+ json_dumps (withdraw_obj,
+ JSON_COMPACT)));
+ json_decref (withdraw_obj);
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ wsh->url));
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_POSTFIELDS,
+ wsh->json_enc));
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_POSTFIELDSIZE,
+ strlen (wsh->json_enc)));
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_WRITEFUNCTION,
+ &MAC_download_cb));
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_WRITEDATA,
+ &wsh->db));
+ ctx = MAH_handle_to_context (mint);
+ wsh->job = MAC_job_add (ctx,
+ eh,
+ GNUNET_YES,
+ &handle_reserve_withdraw_finished,
+ wsh);
+ return wsh;
+}
+
+
+/**
+ * Cancel a withdraw status request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param sign the withdraw sign request handle
+ */
+void
+TALER_MINT_reserve_withdraw_cancel (struct TALER_MINT_ReserveWithdrawHandle *sign)
+{
+ if (NULL != sign->job)
+ {
+ MAC_job_cancel (sign->job);
+ sign->job = NULL;
+ }
+ GNUNET_free_non_null (sign->db.buf);
+ GNUNET_free (sign->url);
+ GNUNET_free (sign->json_enc);
+ GNUNET_free (sign);
+}
+
+
+/* end of mint_api_reserve.c */
diff --git a/src/mint-lib/mint_api_withdraw.c b/src/mint-lib/mint_api_withdraw.c
@@ -1,927 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
-
- 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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_withdraw.c
- * @brief Implementation of the /withdraw requests of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/* ********************** /withdraw/status ********************** */
-
-/**
- * @brief A Withdraw Status Handle
- */
-struct TALER_MINT_WithdrawStatusHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_WithdrawStatusResultCallback cb;
-
- /**
- * Public key of the reserve we are querying.
- */
- struct TALER_ReservePublicKeyP reserve_pub;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
-};
-
-
-/**
- * Parse history given in JSON format and return it in binary
- * format.
- *
- * @param[in] history JSON array with the history
- * @param reserve_pub public key of the reserve to inspect
- * @param currency currency we expect the balance to be in
- * @param[out] balance final balance
- * @param history_length number of entries in @a history
- * @param[out] rhistory array of length @a history_length, set to the
- * parsed history entries
- * @return #GNUNET_OK if history was valid and @a rhistory and @a balance
- * were set,
- * #GNUNET_SYSERR if there was a protocol violation in @a history
- */
-static int
-parse_reserve_history (json_t *history,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const char *currency,
- struct TALER_Amount *balance,
- unsigned int history_length,
- struct TALER_MINT_ReserveHistory *rhistory)
-{
- struct GNUNET_HashCode uuid[history_length];
- unsigned int uuid_off;
- struct TALER_Amount total_in;
- struct TALER_Amount total_out;
- size_t off;
-
- TALER_amount_get_zero (currency,
- &total_in);
- TALER_amount_get_zero (currency,
- &total_out);
- uuid_off = 0;
- for (off=0;off<history_length;off++)
- {
- json_t *transaction;
- struct TALER_Amount amount;
- const char *type;
- struct MAJ_Specification hist_spec[] = {
- MAJ_spec_string ("type", &type),
- MAJ_spec_amount ("amount",
- &amount),
- /* 'wire' and 'signature' are optional depending on 'type'! */
- MAJ_spec_end
- };
-
- transaction = json_array_get (history,
- off);
- if (GNUNET_OK !=
- MAJ_parse_json (transaction,
- hist_spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rhistory[off].amount = amount;
-
- if (0 == strcasecmp (type,
- "DEPOSIT"))
- {
- json_t *wire;
-
- rhistory[off].type = TALER_MINT_RTT_DEPOSIT;
- if (GNUNET_OK !=
- TALER_amount_add (&total_in,
- &total_in,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad mint! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- wire = json_object_get (transaction,
- "wire");
- /* check 'wire' is a JSON object (no need to check wireformat,
- but we do at least expect "some" JSON object here) */
- if ( (NULL == wire) ||
- (! json_is_object (wire)) )
- {
- /* not even a JSON 'wire' specification, not acceptable */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rhistory[off].details.wire_in_details = wire;
- /* end type==DEPOSIT */
- }
- else if (0 == strcasecmp (type,
- "WITHDRAW"))
- {
- struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
- const struct TALER_WithdrawRequestPS *withdraw_purpose;
- struct TALER_Amount amount_from_purpose;
- struct MAJ_Specification withdraw_spec[] = {
- MAJ_spec_eddsa_signed_purpose ("signature",
- &purpose,
- &reserve_pub->eddsa_pub),
- MAJ_spec_end
- };
- unsigned int i;
-
- rhistory[off].type = TALER_MINT_RTT_WITHDRAWAL;
- if (GNUNET_OK !=
- MAJ_parse_json (transaction,
- withdraw_spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* Check that the signature actually signed a withdraw request */
- if ( (ntohl (purpose->purpose) != TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW) ||
- (ntohl (purpose->size) != sizeof (struct TALER_WithdrawRequestPS)) )
- {
- GNUNET_break_op (0);
- MAJ_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- withdraw_purpose = (const struct TALER_WithdrawRequestPS *) purpose;
- TALER_amount_ntoh (&amount_from_purpose,
- &withdraw_purpose->amount_with_fee);
- if (0 != TALER_amount_cmp (&amount,
- &amount_from_purpose))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- rhistory[off].details.out_authorization_sig = json_object_get (transaction,
- "signature");
- /* Check check that the same withdraw transaction
- isn't listed twice by the mint. We use the
- "uuid" array to remember the hashes of all
- purposes, and compare the hashes to find
- duplicates. */
- GNUNET_CRYPTO_hash (withdraw_purpose,
- ntohl (withdraw_purpose->purpose.size),
- &uuid[uuid_off]);
- for (i=0;i<uuid_off;i++)
- {
- if (0 == memcmp (&uuid[uuid_off],
- &uuid[i],
- sizeof (struct GNUNET_HashCode)))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- }
- uuid_off++;
-
- if (GNUNET_OK !=
- TALER_amount_add (&total_out,
- &total_out,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad mint! */
- GNUNET_break_op (0);
- MAJ_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- /* end type==WITHDRAW */
- }
- else
- {
- /* unexpected 'type', protocol incompatibility, complain! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
-
- /* check balance = total_in - total_out < withdraw-amount */
- if (GNUNET_SYSERR ==
- TALER_amount_subtract (balance,
- &total_in,
- &total_out))
- {
- /* total_in < total_out, why did the mint ever allow this!? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /withdraw/status request.
- *
- * @param cls the `struct TALER_MINT_WithdrawStatusHandle`
- * @param eh curl handle of the request that finished
- */
-static void
-handle_withdraw_status_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_WithdrawStatusHandle *wsh = cls;
- long response_code;
- json_t *json;
-
- wsh->job = NULL;
- json = MAC_download_get_result (&wsh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- /* TODO: move into separate function... */
- json_t *history;
- unsigned int len;
- struct TALER_Amount balance;
- struct TALER_Amount balance_from_history;
- struct MAJ_Specification spec[] = {
- MAJ_spec_amount ("balance", &balance),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- history = json_object_get (json,
- "history");
- if (NULL == history)
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- len = json_array_size (history);
- {
- struct TALER_MINT_ReserveHistory rhistory[len];
-
- if (GNUNET_OK !=
- parse_reserve_history (history,
- &wsh->reserve_pub,
- balance.currency,
- &balance_from_history,
- len,
- rhistory))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- if (0 !=
- TALER_amount_cmp (&balance_from_history,
- &balance))
- {
- /* mint cannot add up balances!? */
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- wsh->cb (wsh->cb_cls,
- response_code,
- json,
- &balance,
- len,
- rhistory);
- wsh->cb = NULL;
- }
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the application */
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- break;
- default:
- /* unexpected response code */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (NULL != wsh->cb)
- wsh->cb (wsh->cb_cls,
- response_code,
- json,
- NULL,
- 0, NULL);
- json_decref (json);
- TALER_MINT_withdraw_status_cancel (wsh);
-}
-
-
-/**
- * Submit a request to obtain the transaction history of a reserve
- * from the mint. Note that while we return the full response to the
- * caller for further processing, we do already verify that the
- * response is well-formed (i.e. that signatures included in the
- * response are all valid and add up to the balance). If the mint's
- * reply is not well-formed, we return an HTTP status code of zero to
- * @a cb.
- *
- * @param mint the mint handle; the mint must be ready to operate
- * @param reserve_pub public key of the reserve to inspect
- * @param cb the callback to call when a reply for this request is available
- * @param cb_cls closure for the above callback
- * @return a handle for this request; NULL if the inputs are invalid (i.e.
- * signatures fail to verify). In this case, the callback is not called.
- */
-struct TALER_MINT_WithdrawStatusHandle *
-TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- TALER_MINT_WithdrawStatusResultCallback cb,
- void *cb_cls)
-{
- struct TALER_MINT_WithdrawStatusHandle *wsh;
- struct TALER_MINT_Context *ctx;
- CURL *eh;
- char *pub_str;
- char *arg_str;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
- pub_str = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
- sizeof (struct TALER_ReservePublicKeyP));
- GNUNET_asprintf (&arg_str,
- "/withdraw/status?reserve_pub=%s",
- pub_str);
- GNUNET_free (pub_str);
- wsh = GNUNET_new (struct TALER_MINT_WithdrawStatusHandle);
- wsh->mint = mint;
- wsh->cb = cb;
- wsh->cb_cls = cb_cls;
- wsh->reserve_pub = *reserve_pub;
- wsh->url = MAH_path_to_url (mint,
- arg_str);
- GNUNET_free (arg_str);
-
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- wsh->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &wsh->db));
- ctx = MAH_handle_to_context (mint);
- wsh->job = MAC_job_add (ctx,
- eh,
- GNUNET_NO,
- &handle_withdraw_status_finished,
- wsh);
- return wsh;
-}
-
-
-/**
- * Cancel a withdraw status request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param wsh the withdraw status request handle
- */
-void
-TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh)
-{
- if (NULL != wsh->job)
- {
- MAC_job_cancel (wsh->job);
- wsh->job = NULL;
- }
- GNUNET_free_non_null (wsh->db.buf);
- GNUNET_free (wsh->url);
- GNUNET_free (wsh);
-}
-
-
-/* ********************** /withdraw/sign ********************** */
-
-/**
- * @brief A Withdraw Sign Handle
- */
-struct TALER_MINT_WithdrawSignHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_WithdrawSignResultCallback cb;
-
- /**
- * Key used to blind the value.
- */
- const struct TALER_DenominationBlindingKey *blinding_key;
-
- /**
- * Denomination key we are withdrawing.
- */
- const struct TALER_MINT_DenomPublicKey *pk;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * Hash of the public key of the coin we are signing.
- */
- struct GNUNET_HashCode c_hash;
-
- /**
- * Public key of the reserve we are withdrawing from.
- */
- struct TALER_ReservePublicKeyP reserve_pub;
-
-};
-
-
-/**
- * We got a 200 OK response for the /withdraw/sign operation.
- * Extract the coin's signature and return it to the caller.
- * The signature we get from the mint 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 wsh operation handle
- * @param json reply from the mint
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static int
-withdraw_sign_ok (struct TALER_MINT_WithdrawSignHandle *wsh,
- json_t *json)
-{
- struct GNUNET_CRYPTO_rsa_Signature *blind_sig;
- struct GNUNET_CRYPTO_rsa_Signature *sig;
- struct TALER_DenominationSignature dsig;
- struct MAJ_Specification spec[] = {
- MAJ_spec_rsa_signature ("ev_sig", &blind_sig),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- sig = GNUNET_CRYPTO_rsa_unblind (blind_sig,
- wsh->blinding_key->rsa_blinding_key,
- wsh->pk->key.rsa_public_key);
- GNUNET_CRYPTO_rsa_signature_free (blind_sig);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_rsa_verify (&wsh->c_hash,
- sig,
- wsh->pk->key.rsa_public_key))
- {
- GNUNET_break_op (0);
- GNUNET_CRYPTO_rsa_signature_free (sig);
- return GNUNET_SYSERR;
- }
- /* signature is valid, return it to the application */
- dsig.rsa_signature = sig;
- wsh->cb (wsh->cb_cls,
- MHD_HTTP_OK,
- &dsig,
- json);
- /* make sure callback isn't called again after return */
- wsh->cb = NULL;
- GNUNET_CRYPTO_rsa_signature_free (sig);
- return GNUNET_OK;
-}
-
-
-/**
- * We got a 402 PAYMENT REQUIRED response for the /withdraw/sign operation.
- * Check the signatures on the withdraw transactions in the provided
- * history and that the balances add up. We don't do anything directly
- * with the information, as the JSON will be returned to the application.
- * However, our job is ensuring that the mint followed the protocol, and
- * this in particular means checking all of the signatures in the history.
- *
- * @param wsh operation handle
- * @param json reply from the mint
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static int
-withdraw_sign_payment_required (struct TALER_MINT_WithdrawSignHandle *wsh,
- json_t *json)
-{
- struct TALER_Amount balance;
- struct TALER_Amount balance_from_history;
- struct TALER_Amount requested_amount;
- json_t *history;
- size_t len;
- struct MAJ_Specification spec[] = {
- MAJ_spec_amount ("balance", &balance),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- history = json_object_get (json,
- "history");
- if (NULL == history)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* go over transaction history and compute
- total incoming and outgoing amounts */
- len = json_array_size (history);
- {
- struct TALER_MINT_ReserveHistory rhistory[len];
-
- if (GNUNET_OK !=
- parse_reserve_history (history,
- &wsh->reserve_pub,
- balance.currency,
- &balance_from_history,
- len,
- rhistory))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
-
- if (0 !=
- TALER_amount_cmp (&balance_from_history,
- &balance))
- {
- /* mint cannot add up balances!? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* Compute how much we expected to charge to the reserve */
- if (GNUNET_OK !=
- TALER_amount_add (&requested_amount,
- &wsh->pk->value,
- &wsh->pk->fee_withdraw))
- {
- /* Overflow here? Very strange, our CPU must be fried... */
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- /* Check that funds were really insufficient */
- if (0 >= TALER_amount_cmp (&requested_amount,
- &balance))
- {
- /* Requested amount is smaller or equal to reported balance,
- so this should not have failed. */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /withdraw/sign request.
- *
- * @param cls the `struct TALER_MINT_WithdrawSignHandle`
- * @param eh curl handle of the request that finished
- */
-static void
-handle_withdraw_sign_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_WithdrawSignHandle *wsh = cls;
- long response_code;
- json_t *json;
-
- wsh->job = NULL;
- json = MAC_download_get_result (&wsh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- withdraw_sign_ok (wsh,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_PAYMENT_REQUIRED:
- /* The mint says that the reserve has insufficient funds;
- check the signatures in the history... */
- if (GNUNET_OK !=
- withdraw_sign_payment_required (wsh,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- GNUNET_break (0);
- /* Nothing really to verify, mint 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:
- /* Nothing really to verify, the mint 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. */
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- break;
- default:
- /* unexpected response code */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (NULL != wsh->cb)
- wsh->cb (wsh->cb_cls,
- response_code,
- NULL,
- json);
- json_decref (json);
- TALER_MINT_withdraw_sign_cancel (wsh);
-}
-
-
-/**
- * Withdraw a coin from the mint using a /withdraw/sign request. Note
- * that to ensure that no money is lost in case of hardware failures,
- * the caller must have committed (most of) the arguments to disk
- * before calling, and be ready to repeat the request with the same
- * arguments in case of failures.
- *
- * @param mint the mint handle; the mint must be ready to operate
- * @param pk kind of coin to create
- * @param reserve_priv private key of the reserve to withdraw from
- * @param coin_priv where to store the coin's private key,
- * caller must have committed this value to disk before the call (with @a pk)
- * @param blinding_key where to store the coin's blinding key
- * caller must have committed this value to disk before the call (with @a pk)
- * @param res_cb the callback to call when the final result for this request is available
- * @param res_cb_cls closure for the above callback
- * @return #GNUNET_OK on success, #GNUNET_SYSERR
- * if the inputs are invalid (i.e. denomination key not with this mint).
- * In this case, the callback is not called.
- */
-struct TALER_MINT_WithdrawSignHandle *
-TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
- const struct TALER_MINT_DenomPublicKey *pk,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_DenominationBlindingKey *blinding_key,
- TALER_MINT_WithdrawSignResultCallback res_cb,
- void *res_cb_cls)
-{
- struct TALER_MINT_WithdrawSignHandle *wsh;
- struct TALER_WithdrawRequestPS req;
- struct TALER_ReserveSignatureP reserve_sig;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_MINT_Context *ctx;
- struct TALER_Amount amount_with_fee;
- char *coin_ev;
- size_t coin_ev_size;
- json_t *withdraw_obj;
- CURL *eh;
-
- wsh = GNUNET_new (struct TALER_MINT_WithdrawSignHandle);
- wsh->mint = mint;
- wsh->cb = res_cb;
- wsh->cb_cls = res_cb_cls;
- wsh->pk = pk;
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
- GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
- &wsh->c_hash);
- coin_ev_size = GNUNET_CRYPTO_rsa_blind (&wsh->c_hash,
- blinding_key->rsa_blinding_key,
- pk->key.rsa_public_key,
- &coin_ev);
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
- &wsh->reserve_pub.eddsa_pub);
- req.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
- req.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
- req.reserve_pub = wsh->reserve_pub;
- if (GNUNET_OK !=
- TALER_amount_add (&amount_with_fee,
- &pk->fee_withdraw,
- &pk->value))
- {
- /* mint gave us denomination keys that overflow like this!? */
- GNUNET_break_op (0);
- GNUNET_free (coin_ev);
- GNUNET_free (wsh);
- return NULL;
- }
- TALER_amount_hton (&req.amount_with_fee,
- &amount_with_fee);
- TALER_amount_hton (&req.withdraw_fee,
- &pk->fee_withdraw);
- GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key,
- &req.h_denomination_pub);
- GNUNET_CRYPTO_hash (coin_ev,
- coin_ev_size,
- &req.h_coin_envelope);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
- &req.purpose,
- &reserve_sig.eddsa_signature));
- withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */
- " s:o, s:o}",/* reserve_pub and reserve_sig */
- "denom_pub", TALER_json_from_rsa_public_key (pk->key.rsa_public_key),
- "coin_ev", TALER_json_from_data (coin_ev,
- coin_ev_size),
- "reserve_pub", TALER_json_from_data (&wsh->reserve_pub,
- sizeof (struct TALER_ReservePublicKeyP)),
- "reserve_sig", TALER_json_from_data (&reserve_sig,
- sizeof (reserve_sig)));
- GNUNET_free (coin_ev);
-
- wsh->blinding_key = blinding_key;
- wsh->url = MAH_path_to_url (mint, "/withdraw/sign");
-
- eh = curl_easy_init ();
- GNUNET_assert (NULL != (wsh->json_enc =
- json_dumps (withdraw_obj,
- JSON_COMPACT)));
- json_decref (withdraw_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- wsh->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- wsh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (wsh->json_enc)));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &wsh->db));
- ctx = MAH_handle_to_context (mint);
- wsh->job = MAC_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_withdraw_sign_finished,
- wsh);
- return wsh;
-}
-
-
-/**
- * Cancel a withdraw status request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param sign the withdraw sign request handle
- */
-void
-TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign)
-{
- if (NULL != sign->job)
- {
- MAC_job_cancel (sign->job);
- sign->job = NULL;
- }
- GNUNET_free_non_null (sign->db.buf);
- GNUNET_free (sign->url);
- GNUNET_free (sign->json_enc);
- GNUNET_free (sign);
-}
-
-
-/* end of mint_api_withdraw.c */
diff --git a/src/mint-lib/test_mint_api.c b/src/mint-lib/test_mint_api.c
@@ -131,7 +131,7 @@ struct MeltDetails
const char *amount;
/**
- * Reference to withdraw_sign operations for coin to
+ * Reference to reserve_withdraw operations for coin to
* be used for the /refresh/melt operation.
*/
const char *coin_ref;
@@ -243,14 +243,14 @@ struct Command
/**
* Set to the API's handle during the operation.
*/
- struct TALER_MINT_WithdrawStatusHandle *wsh;
+ struct TALER_MINT_ReserveStatusHandle *wsh;
/**
* Expected reserve balance.
*/
const char *expected_balance;
- } withdraw_status;
+ } reserve_status;
/**
* Information for a #OC_WITHDRAW_SIGN command.
@@ -296,9 +296,9 @@ struct Command
/**
* Withdraw handle (while operation is running).
*/
- struct TALER_MINT_WithdrawSignHandle *wsh;
+ struct TALER_MINT_ReserveWithdrawHandle *wsh;
- } withdraw_sign;
+ } reserve_withdraw;
/**
* Information for a #OC_DEPOSIT command.
@@ -312,7 +312,7 @@ struct Command
const char *amount;
/**
- * Reference to a withdraw_sign operation for a coin to
+ * Reference to a reserve_withdraw operation for a coin to
* be used for the /deposit operation.
*/
const char *coin_ref;
@@ -649,8 +649,8 @@ compare_admin_add_incoming_history (const struct TALER_MINT_ReserveHistory *h,
* @return #GNUNET_OK if they match, #GNUNET_SYSERR if not
*/
static int
-compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
- const struct Command *cmd)
+compare_reserve_withdraw_history (const struct TALER_MINT_ReserveHistory *h,
+ const struct Command *cmd)
{
struct TALER_Amount amount;
struct TALER_Amount amount_with_fee;
@@ -661,12 +661,12 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
return GNUNET_SYSERR;
}
GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (cmd->details.withdraw_sign.amount,
+ TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
&amount));
GNUNET_assert (GNUNET_OK ==
TALER_amount_add (&amount_with_fee,
&amount,
- &cmd->details.withdraw_sign.pk->fee_withdraw));
+ &cmd->details.reserve_withdraw.pk->fee_withdraw));
if (0 != TALER_amount_cmp (&amount_with_fee,
&h->amount))
{
@@ -678,7 +678,7 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
/**
- * Function called with the result of a /withdraw/status request.
+ * Function called with the result of a /reserve/status request.
*
* @param cls closure with the interpreter state
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
@@ -689,12 +689,12 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
* @param history detailed transaction history, NULL on error
*/
static void
-withdraw_status_cb (void *cls,
- unsigned int http_status,
- json_t *json,
- const struct TALER_Amount *balance,
- unsigned int history_length,
- const struct TALER_MINT_ReserveHistory *history)
+reserve_status_cb (void *cls,
+ unsigned int http_status,
+ json_t *json,
+ const struct TALER_Amount *balance,
+ unsigned int history_length,
+ const struct TALER_MINT_ReserveHistory *history)
{
struct InterpreterState *is = cls;
struct Command *cmd = &is->commands[is->ip];
@@ -703,7 +703,7 @@ withdraw_status_cb (void *cls,
unsigned int j;
struct TALER_Amount amount;
- cmd->details.withdraw_status.wsh = NULL;
+ cmd->details.reserve_status.wsh = NULL;
if (cmd->expected_response_code != http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -727,10 +727,10 @@ withdraw_status_cb (void *cls,
{
case OC_ADMIN_ADD_INCOMING:
if ( ( (NULL != rel->label) &&
- (0 == strcmp (cmd->details.withdraw_status.reserve_reference,
+ (0 == strcmp (cmd->details.reserve_status.reserve_reference,
rel->label) ) ) ||
( (NULL != rel->details.admin_add_incoming.reserve_reference) &&
- (0 == strcmp (cmd->details.withdraw_status.reserve_reference,
+ (0 == strcmp (cmd->details.reserve_status.reserve_reference,
rel->details.admin_add_incoming.reserve_reference) ) ) )
{
if (GNUNET_OK !=
@@ -745,11 +745,11 @@ withdraw_status_cb (void *cls,
}
break;
case OC_WITHDRAW_SIGN:
- if (0 == strcmp (cmd->details.withdraw_status.reserve_reference,
- rel->details.withdraw_sign.reserve_reference))
+ if (0 == strcmp (cmd->details.reserve_status.reserve_reference,
+ rel->details.reserve_withdraw.reserve_reference))
{
if (GNUNET_OK !=
- compare_withdraw_sign_history (&history[j],
+ compare_reserve_withdraw_history (&history[j],
rel))
{
GNUNET_break (0);
@@ -770,10 +770,10 @@ withdraw_status_cb (void *cls,
fail (is);
return;
}
- if (NULL != cmd->details.withdraw_status.expected_balance)
+ if (NULL != cmd->details.reserve_status.expected_balance)
{
GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (cmd->details.withdraw_status.expected_balance,
+ TALER_string_to_amount (cmd->details.reserve_status.expected_balance,
&amount));
if (0 != TALER_amount_cmp (&amount,
balance))
@@ -796,7 +796,7 @@ withdraw_status_cb (void *cls,
/**
- * Function called upon completion of our /withdraw/sign request.
+ * Function called upon completion of our /reserve/withdraw request.
*
* @param cls closure with the interpreter state
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
@@ -805,15 +805,15 @@ withdraw_status_cb (void *cls,
* @param full_response full response from the mint (for logging, in case of errors)
*/
static void
-withdraw_sign_cb (void *cls,
- unsigned int http_status,
- const struct TALER_DenominationSignature *sig,
- json_t *full_response)
+reserve_withdraw_cb (void *cls,
+ unsigned int http_status,
+ const struct TALER_DenominationSignature *sig,
+ json_t *full_response)
{
struct InterpreterState *is = cls;
struct Command *cmd = &is->commands[is->ip];
- cmd->details.withdraw_sign.wsh = NULL;
+ cmd->details.reserve_withdraw.wsh = NULL;
if (cmd->expected_response_code != http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -834,7 +834,7 @@ withdraw_sign_cb (void *cls,
fail (is);
return;
}
- cmd->details.withdraw_sign.sig.rsa_signature
+ cmd->details.reserve_withdraw.sig.rsa_signature
= GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
break;
case MHD_HTTP_PAYMENT_REQUIRED:
@@ -1309,44 +1309,44 @@ interpreter_run (void *cls,
return;
case OC_WITHDRAW_STATUS:
GNUNET_assert (NULL !=
- cmd->details.withdraw_status.reserve_reference);
+ cmd->details.reserve_status.reserve_reference);
ref = find_command (is,
- cmd->details.withdraw_status.reserve_reference);
+ cmd->details.reserve_status.reserve_reference);
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
GNUNET_CRYPTO_eddsa_key_get_public (&ref->details.admin_add_incoming.reserve_priv.eddsa_priv,
&reserve_pub.eddsa_pub);
- cmd->details.withdraw_status.wsh
- = TALER_MINT_withdraw_status (mint,
- &reserve_pub,
- &withdraw_status_cb,
- is);
+ cmd->details.reserve_status.wsh
+ = TALER_MINT_reserve_status (mint,
+ &reserve_pub,
+ &reserve_status_cb,
+ is);
trigger_context_task ();
return;
case OC_WITHDRAW_SIGN:
GNUNET_assert (NULL !=
- cmd->details.withdraw_sign.reserve_reference);
+ cmd->details.reserve_withdraw.reserve_reference);
ref = find_command (is,
- cmd->details.withdraw_sign.reserve_reference);
+ cmd->details.reserve_withdraw.reserve_reference);
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
- if (NULL != cmd->details.withdraw_sign.amount)
+ if (NULL != cmd->details.reserve_withdraw.amount)
{
if (GNUNET_OK !=
- TALER_string_to_amount (cmd->details.withdraw_sign.amount,
+ TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
&amount))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %u\n",
- cmd->details.withdraw_sign.amount,
+ cmd->details.reserve_withdraw.amount,
is->ip);
fail (is);
return;
}
- cmd->details.withdraw_sign.pk = find_pk (is->keys,
- &amount);
+ cmd->details.reserve_withdraw.pk = find_pk (is->keys,
+ &amount);
}
- if (NULL == cmd->details.withdraw_sign.pk)
+ if (NULL == cmd->details.reserve_withdraw.pk)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to determine denomination key at %u\n",
@@ -1360,22 +1360,22 @@ interpreter_run (void *cls,
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
priv = GNUNET_CRYPTO_eddsa_key_create ();
- cmd->details.withdraw_sign.coin_priv.eddsa_priv = *priv;
+ cmd->details.reserve_withdraw.coin_priv.eddsa_priv = *priv;
GNUNET_free (priv);
}
- GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.withdraw_sign.coin_priv.eddsa_priv,
+ GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.reserve_withdraw.coin_priv.eddsa_priv,
&coin_pub.eddsa_pub);
- cmd->details.withdraw_sign.blinding_key.rsa_blinding_key
- = GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.withdraw_sign.pk->key.rsa_public_key));
- cmd->details.withdraw_sign.wsh
- = TALER_MINT_withdraw_sign (mint,
- cmd->details.withdraw_sign.pk,
- &ref->details.admin_add_incoming.reserve_priv,
- &cmd->details.withdraw_sign.coin_priv,
- &cmd->details.withdraw_sign.blinding_key,
- &withdraw_sign_cb,
- is);
- if (NULL == cmd->details.withdraw_sign.wsh)
+ cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key
+ = GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.reserve_withdraw.pk->key.rsa_public_key));
+ cmd->details.reserve_withdraw.wsh
+ = TALER_MINT_reserve_withdraw (mint,
+ cmd->details.reserve_withdraw.pk,
+ &ref->details.admin_add_incoming.reserve_priv,
+ &cmd->details.reserve_withdraw.coin_priv,
+ &cmd->details.reserve_withdraw.blinding_key,
+ &reserve_withdraw_cb,
+ is);
+ if (NULL == cmd->details.reserve_withdraw.wsh)
{
GNUNET_break (0);
fail (is);
@@ -1404,9 +1404,9 @@ interpreter_run (void *cls,
switch (ref->oc)
{
case OC_WITHDRAW_SIGN:
- coin_priv = &ref->details.withdraw_sign.coin_priv;
- coin_pk = ref->details.withdraw_sign.pk;
- coin_pk_sig = &ref->details.withdraw_sign.sig;
+ coin_priv = &ref->details.reserve_withdraw.coin_priv;
+ coin_pk = ref->details.reserve_withdraw.pk;
+ coin_pk_sig = &ref->details.reserve_withdraw.sig;
break;
case OC_REFRESH_REVEAL:
{
@@ -1549,7 +1549,7 @@ interpreter_run (void *cls,
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
- melt_privs[i] = ref->details.withdraw_sign.coin_priv;
+ melt_privs[i] = ref->details.reserve_withdraw.coin_priv;
if (GNUNET_OK !=
TALER_string_to_amount (md->amount,
&melt_amounts[i]))
@@ -1561,8 +1561,8 @@ interpreter_run (void *cls,
fail (is);
return;
}
- melt_sigs[i] = ref->details.withdraw_sign.sig;
- melt_pks[i] = *ref->details.withdraw_sign.pk;
+ melt_sigs[i] = ref->details.reserve_withdraw.sig;
+ melt_pks[i] = *ref->details.reserve_withdraw.pk;
}
for (i=0;i<num_fresh_coins;i++)
{
@@ -1572,7 +1572,7 @@ interpreter_run (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %u\n",
- cmd->details.withdraw_sign.amount,
+ cmd->details.reserve_withdraw.amount,
is->ip);
fail (is);
return;
@@ -1639,7 +1639,7 @@ interpreter_run (void *cls,
/* find melt command */
ref = find_command (is,
ref->details.refresh_reveal.melt_ref);
- /* find withdraw_sign command */
+ /* find reserve_withdraw command */
{
unsigned int idx;
const struct MeltDetails *md;
@@ -1658,7 +1658,7 @@ interpreter_run (void *cls,
/* finally, use private key from withdraw sign command */
cmd->details.refresh_link.rlh
= TALER_MINT_refresh_link (mint,
- &ref->details.withdraw_sign.coin_priv,
+ &ref->details.reserve_withdraw.coin_priv,
&link_cb,
is);
if (NULL == cmd->details.refresh_link.rlh)
@@ -1724,35 +1724,35 @@ do_shutdown (void *cls,
}
break;
case OC_WITHDRAW_STATUS:
- if (NULL != cmd->details.withdraw_status.wsh)
+ if (NULL != cmd->details.reserve_status.wsh)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Command %u (%s) did not complete\n",
i,
cmd->label);
- TALER_MINT_withdraw_status_cancel (cmd->details.withdraw_status.wsh);
- cmd->details.withdraw_status.wsh = NULL;
+ TALER_MINT_reserve_status_cancel (cmd->details.reserve_status.wsh);
+ cmd->details.reserve_status.wsh = NULL;
}
break;
case OC_WITHDRAW_SIGN:
- if (NULL != cmd->details.withdraw_sign.wsh)
+ if (NULL != cmd->details.reserve_withdraw.wsh)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Command %u (%s) did not complete\n",
i,
cmd->label);
- TALER_MINT_withdraw_sign_cancel (cmd->details.withdraw_sign.wsh);
- cmd->details.withdraw_sign.wsh = NULL;
+ TALER_MINT_reserve_withdraw_cancel (cmd->details.reserve_withdraw.wsh);
+ cmd->details.reserve_withdraw.wsh = NULL;
}
- if (NULL != cmd->details.withdraw_sign.sig.rsa_signature)
+ if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
{
- GNUNET_CRYPTO_rsa_signature_free (cmd->details.withdraw_sign.sig.rsa_signature);
- cmd->details.withdraw_sign.sig.rsa_signature = NULL;
+ GNUNET_CRYPTO_rsa_signature_free (cmd->details.reserve_withdraw.sig.rsa_signature);
+ cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
}
- if (NULL != cmd->details.withdraw_sign.blinding_key.rsa_blinding_key)
+ if (NULL != cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key)
{
- GNUNET_CRYPTO_rsa_blinding_key_free (cmd->details.withdraw_sign.blinding_key.rsa_blinding_key);
- cmd->details.withdraw_sign.blinding_key.rsa_blinding_key = NULL;
+ GNUNET_CRYPTO_rsa_blinding_key_free (cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key);
+ cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key = NULL;
}
break;
case OC_DEPOSIT:
@@ -2018,15 +2018,15 @@ run (void *cls,
{ .oc = OC_WITHDRAW_SIGN,
.label = "withdraw-coin-1",
.expected_response_code = MHD_HTTP_OK,
- .details.withdraw_sign.reserve_reference = "create-reserve-1",
- .details.withdraw_sign.amount = "EUR:5" },
+ .details.reserve_withdraw.reserve_reference = "create-reserve-1",
+ .details.reserve_withdraw.amount = "EUR:5" },
/* Check that deposit and withdraw operation are in history, and
that the balance is now at zero */
{ .oc = OC_WITHDRAW_STATUS,
.label = "withdraw-status-1",
.expected_response_code = MHD_HTTP_OK,
- .details.withdraw_status.reserve_reference = "create-reserve-1",
- .details.withdraw_status.expected_balance = "EUR:0" },
+ .details.reserve_status.reserve_reference = "create-reserve-1",
+ .details.reserve_status.expected_balance = "EUR:0" },
/* Try to deposit the 5 EUR coin (in full) */
{ .oc = OC_DEPOSIT,
.label = "deposit-simple",
@@ -2041,8 +2041,8 @@ run (void *cls,
{ .oc = OC_WITHDRAW_SIGN,
.label = "withdraw-coin-2",
.expected_response_code = MHD_HTTP_PAYMENT_REQUIRED,
- .details.withdraw_sign.reserve_reference = "create-reserve-1",
- .details.withdraw_sign.amount = "EUR:5" },
+ .details.reserve_withdraw.reserve_reference = "create-reserve-1",
+ .details.reserve_withdraw.amount = "EUR:5" },
/* Try to double-spend the 5 EUR coin with different wire details */
{ .oc = OC_DEPOSIT,
@@ -2086,8 +2086,8 @@ run (void *cls,
{ .oc = OC_WITHDRAW_SIGN,
.label = "refresh-withdraw-coin-1",
.expected_response_code = MHD_HTTP_OK,
- .details.withdraw_sign.reserve_reference = "refresh-create-reserve-1",
- .details.withdraw_sign.amount = "EUR:5" },
+ .details.reserve_withdraw.reserve_reference = "refresh-create-reserve-1",
+ .details.reserve_withdraw.amount = "EUR:5" },
/* Try to partially spend (deposit) 1 EUR of the 5 EUR coin (in full)
(merchant would receive EUR:0.99 due to 1 ct deposit fee) */
{ .oc = OC_DEPOSIT,
diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am
@@ -18,7 +18,7 @@ taler_mint_httpd_SOURCES = \
taler-mint-httpd_mhd.c taler-mint-httpd_mhd.h \
taler-mint-httpd_admin.c taler-mint-httpd_admin.h \
taler-mint-httpd_deposit.c taler-mint-httpd_deposit.h \
- taler-mint-httpd_withdraw.c taler-mint-httpd_withdraw.h \
+ taler-mint-httpd_reserve.c taler-mint-httpd_reserve.h \
taler-mint-httpd_wire.c taler-mint-httpd_wire.h \
taler-mint-httpd_refresh.c taler-mint-httpd_refresh.h
taler_mint_httpd_LDADD = \
diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c
@@ -30,7 +30,7 @@
#include "taler-mint-httpd_mhd.h"
#include "taler-mint-httpd_admin.h"
#include "taler-mint-httpd_deposit.h"
-#include "taler-mint-httpd_withdraw.h"
+#include "taler-mint-httpd_reserve.h"
#include "taler-mint-httpd_wire.h"
#include "taler-mint-httpd_refresh.h"
#include "taler-mint-httpd_keystate.h"
@@ -190,17 +190,17 @@ handle_mhd_request (void *cls,
&TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
/* Withdrawing coins / interaction with reserves */
- { "/withdraw/status", MHD_HTTP_METHOD_GET, "application/json",
+ { "/reserve/status", MHD_HTTP_METHOD_GET, "application/json",
NULL, 0,
- &TMH_WITHDRAW_handler_withdraw_status, MHD_HTTP_OK },
- { "/withdraw/status", NULL, "text/plain",
+ &TMH_RESERVE_handler_reserve_status, MHD_HTTP_OK },
+ { "/reserve/status", NULL, "text/plain",
"Only GET is allowed", 0,
&TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
- { "/withdraw/sign", MHD_HTTP_METHOD_POST, "application/json",
+ { "/reserve/withdraw", MHD_HTTP_METHOD_POST, "application/json",
NULL, 0,
- &TMH_WITHDRAW_handler_withdraw_sign, MHD_HTTP_OK },
- { "/withdraw/sign", NULL, "text/plain",
+ &TMH_RESERVE_handler_reserve_withdraw, MHD_HTTP_OK },
+ { "/reserve/withdraw", NULL, "text/plain",
"Only POST is allowed", 0,
&TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c
@@ -203,7 +203,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
/**
- * Execute a /withdraw/status. Given the public key of a reserve,
+ * Execute a /reserve/status. Given the public key of a reserve,
* return the associated transaction history.
*
* @param connection the MHD connection to handle
@@ -211,8 +211,8 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
* @return MHD result code
*/
int
-TMH_DB_execute_withdraw_status (struct MHD_Connection *connection,
- const struct TALER_ReservePublicKeyP *reserve_pub)
+TMH_DB_execute_reserve_status (struct MHD_Connection *connection,
+ const struct TALER_ReservePublicKeyP *reserve_pub)
{
struct TALER_MINTDB_Session *session;
struct TALER_MINTDB_ReserveHistory *rh;
@@ -233,7 +233,7 @@ TMH_DB_execute_withdraw_status (struct MHD_Connection *connection,
"{s:s, s:s}",
"error", "Reserve not found",
"parameter", "withdraw_pub");
- res = TMH_RESPONSE_reply_withdraw_status_success (connection,
+ res = TMH_RESPONSE_reply_reserve_status_success (connection,
rh);
TMH_plugin->free_reserve_history (TMH_plugin->cls,
rh);
@@ -242,7 +242,7 @@ TMH_DB_execute_withdraw_status (struct MHD_Connection *connection,
/**
- * Execute a "/withdraw/sign". Given a reserve and a properly signed
+ * Execute a "/reserve/withdraw". Given a reserve and a properly signed
* request to withdraw a coin, check the balance of the reserve and
* if it is sufficient, store the request and return the signed
* blinded envelope.
@@ -256,12 +256,12 @@ TMH_DB_execute_withdraw_status (struct MHD_Connection *connection,
* @return MHD result code
*/
int
-TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection,
- const struct TALER_ReservePublicKeyP *reserve,
- const struct TALER_DenominationPublicKey *denomination_pub,
- const char *blinded_msg,
- size_t blinded_msg_len,
- const struct TALER_ReserveSignatureP *signature)
+TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
+ const struct TALER_ReservePublicKeyP *reserve,
+ const struct TALER_DenominationPublicKey *denomination_pub,
+ const char *blinded_msg,
+ size_t blinded_msg_len,
+ const struct TALER_ReserveSignatureP *signature)
{
struct TALER_MINTDB_Session *session;
struct TALER_MINTDB_ReserveHistory *rh;
@@ -303,7 +303,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection,
/* Don't sign again if we have already signed the coin */
if (GNUNET_YES == res)
{
- res = TMH_RESPONSE_reply_withdraw_sign_success (connection,
+ res = TMH_RESPONSE_reply_reserve_withdraw_success (connection,
&collectable);
GNUNET_CRYPTO_rsa_signature_free (collectable.sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (collectable.denom_pub.rsa_public_key);
@@ -431,7 +431,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection,
TMH_KS_release (key_state);
TMH_plugin->rollback (TMH_plugin->cls,
session);
- res = TMH_RESPONSE_reply_withdraw_sign_insufficient_funds (connection,
+ res = TMH_RESPONSE_reply_reserve_withdraw_insufficient_funds (connection,
rh);
TMH_plugin->free_reserve_history (TMH_plugin->cls,
rh);
@@ -475,10 +475,10 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection,
TMH_plugin->commit (TMH_plugin->cls,
session))
{
- TALER_LOG_WARNING ("/withdraw/sign transaction commit failed\n");
+ TALER_LOG_WARNING ("/reserve/withdraw transaction commit failed\n");
return TMH_RESPONSE_reply_commit_error (connection);
}
- res = TMH_RESPONSE_reply_withdraw_sign_success (connection,
+ res = TMH_RESPONSE_reply_reserve_withdraw_success (connection,
&collectable);
GNUNET_CRYPTO_rsa_signature_free (sig);
return res;
diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h
@@ -41,7 +41,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
/**
- * Execute a "/withdraw/status". Given the public key of a reserve,
+ * Execute a "/reserve/status". Given the public key of a reserve,
* return the associated transaction history.
*
* @param connection the MHD connection to handle
@@ -49,12 +49,12 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
* @return MHD result code
*/
int
-TMH_DB_execute_withdraw_status (struct MHD_Connection *connection,
- const struct TALER_ReservePublicKeyP *reserve_pub);
+TMH_DB_execute_reserve_status (struct MHD_Connection *connection,
+ const struct TALER_ReservePublicKeyP *reserve_pub);
/**
- * Execute a "/withdraw/sign". Given a reserve and a properly signed
+ * Execute a "/reserve/withdraw". Given a reserve and a properly signed
* request to withdraw a coin, check the balance of the reserve and
* if it is sufficient, store the request and return the signed
* blinded envelope.
@@ -68,12 +68,12 @@ TMH_DB_execute_withdraw_status (struct MHD_Connection *connection,
* @return MHD result code
*/
int
-TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection,
- const struct TALER_ReservePublicKeyP *reserve,
- const struct TALER_DenominationPublicKey *denomination_pub,
- const char *blinded_msg,
- size_t blinded_msg_len,
- const struct TALER_ReserveSignatureP *signature);
+TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
+ const struct TALER_ReservePublicKeyP *reserve,
+ const struct TALER_DenominationPublicKey *denomination_pub,
+ const char *blinded_msg,
+ size_t blinded_msg_len,
+ const struct TALER_ReserveSignatureP *signature);
/**
diff --git a/src/mint/taler-mint-httpd_keystate.h b/src/mint/taler-mint-httpd_keystate.h
@@ -65,7 +65,7 @@ TMH_KS_release (struct TMH_KS_StateHandle *key_state);
enum TMH_KS_DenominationKeyUse {
/**
- * The key is to be used for a /withdraw/sign or /refresh (mint)
+ * The key is to be used for a /reserve/withdraw or /refresh (mint)
* operation.
*/
TMH_KS_DKU_WITHDRAW,
diff --git a/src/mint/taler-mint-httpd_reserve.c b/src/mint/taler-mint-httpd_reserve.c
@@ -0,0 +1,185 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014,2015 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-mint-httpd_reserve.c
+ * @brief Handle /reserve/ requests
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <jansson.h>
+#include "taler-mint-httpd_reserve.h"
+#include "taler-mint-httpd_parsing.h"
+#include "taler-mint-httpd_responses.h"
+#include "taler-mint-httpd_keystate.h"
+
+
+/**
+ * Handle a "/reserve/status" request. Parses the
+ * given "reserve_pub" argument (which should contain the
+ * EdDSA public key of a reserve) and then respond with the
+ * status of the reserve.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_RESERVE_handler_reserve_status (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ struct TALER_ReservePublicKeyP reserve_pub;
+ int res;
+
+ res = TMH_PARSE_mhd_request_arg_data (connection,
+ "reserve_pub",
+ &reserve_pub,
+ sizeof (struct TALER_ReservePublicKeyP));
+ if (GNUNET_SYSERR == res)
+ return MHD_NO; /* internal error */
+ if (GNUNET_NO == res)
+ return MHD_YES; /* parse error */
+ return TMH_DB_execute_reserve_status (connection,
+ &reserve_pub);
+}
+
+
+/**
+ * Handle a "/reserve/withdraw" request. Parses the "reserve_pub"
+ * EdDSA key of the reserve and the requested "denom_pub" which
+ * specifies the key/value of the coin to be withdrawn, and checks
+ * that the signature "reserve_sig" makes this a valid withdrawl
+ * request from the specified reserve. If so, the envelope
+ * with the blinded coin "coin_ev" is passed down to execute the
+ * withdrawl operation.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_RESERVE_handler_reserve_withdraw (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ json_t *root;
+ struct TALER_WithdrawRequestPS wsrd;
+ int res;
+ struct TALER_DenominationPublicKey denomination_pub;
+ char *blinded_msg;
+ size_t blinded_msg_len;
+ struct TALER_Amount amount;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount fee_withdraw;
+ struct TALER_ReserveSignatureP signature;
+ struct TALER_MINTDB_DenominationKeyIssueInformation *dki;
+ struct TMH_KS_StateHandle *ks;
+
+ struct TMH_PARSE_FieldSpecification spec[] = {
+ TMH_PARSE_member_variable ("coin_ev",
+ (void **) &blinded_msg,
+ &blinded_msg_len),
+ TMH_PARSE_member_fixed ("reserve_pub",
+ &wsrd.reserve_pub),
+ TMH_PARSE_member_fixed ("reserve_sig",
+ &signature),
+ TMH_PARSE_member_denomination_public_key ("denom_pub",
+ &denomination_pub),
+ TMH_PARSE_MEMBER_END
+ };
+
+ res = TMH_PARSE_post_json (connection,
+ connection_cls,
+ upload_data,
+ upload_data_size,
+ &root);
+ if (GNUNET_SYSERR == res)
+ return MHD_NO;
+ if ( (GNUNET_NO == res) || (NULL == root) )
+ return MHD_YES;
+ res = TMH_PARSE_json_data (connection,
+ root,
+ spec);
+ json_decref (root);
+ if (GNUNET_OK != res)
+ return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+ ks = TMH_KS_acquire ();
+ dki = TMH_KS_denomination_key_lookup (ks,
+ &denomination_pub,
+ TMH_KS_DKU_WITHDRAW);
+ if (NULL == dki)
+ {
+ TMH_PARSE_release_data (spec);
+ return TMH_RESPONSE_reply_arg_unknown (connection,
+ "denom_pub");
+ }
+ TALER_amount_ntoh (&amount,
+ &dki->issue.properties.value);
+ TALER_amount_ntoh (&fee_withdraw,
+ &dki->issue.properties.fee_withdraw);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_add (&amount_with_fee,
+ &amount,
+ &fee_withdraw));
+ TALER_amount_hton (&wsrd.amount_with_fee,
+ &amount_with_fee);
+ TALER_amount_hton (&wsrd.withdraw_fee,
+ &fee_withdraw);
+ TMH_KS_release (ks);
+ /* verify signature! */
+ wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
+ wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
+
+ GNUNET_CRYPTO_rsa_public_key_hash (denomination_pub.rsa_public_key,
+ &wsrd.h_denomination_pub);
+ GNUNET_CRYPTO_hash (blinded_msg,
+ blinded_msg_len,
+ &wsrd.h_coin_envelope);
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
+ &wsrd.purpose,
+ &signature.eddsa_signature,
+ &wsrd.reserve_pub.eddsa_pub))
+ {
+ TALER_LOG_WARNING ("Client supplied invalid signature for /reserve/withdraw request\n");
+ TMH_PARSE_release_data (spec);
+ return TMH_RESPONSE_reply_signature_invalid (connection,
+ "reserve_sig");
+ }
+ res = TMH_DB_execute_reserve_withdraw (connection,
+ &wsrd.reserve_pub,
+ &denomination_pub,
+ blinded_msg,
+ blinded_msg_len,
+ &signature);
+ TMH_PARSE_release_data (spec);
+ return res;
+}
+
+/* end of taler-mint-httpd_reserve.c */
diff --git a/src/mint/taler-mint-httpd_reserve.h b/src/mint/taler-mint-httpd_reserve.h
@@ -0,0 +1,73 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-mint-httpd_reserve.h
+ * @brief Handle /reserve/ requests
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MINT_HTTPD_RESERVE_H
+#define TALER_MINT_HTTPD_RESERVE_H
+
+#include <microhttpd.h>
+#include "taler-mint-httpd.h"
+
+/**
+ * Handle a "/reserve/status" request. Parses the
+ * given "reserve_pub" argument (which should contain the
+ * EdDSA public key of a reserve) and then respond with the
+ * status of the reserve.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_RESERVE_handler_reserve_status (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+/**
+ * Handle a "/reserve/withdraw" request. Parses the "reserve_pub"
+ * EdDSA key of the reserve and the requested "denom_pub" which
+ * specifies the key/value of the coin to be withdrawn, and checks
+ * that the signature "reserve_sig" makes this a valid withdrawl
+ * request from the specified reserve. If so, the envelope
+ * with the blinded coin "coin_ev" is passed down to execute the
+ * withdrawl operation.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_RESERVE_handler_reserve_withdraw (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+#endif
diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c
@@ -630,8 +630,8 @@ compile_reserve_history (const struct TALER_MINTDB_ReserveHistory *rh,
* @return MHD result code
*/
int
-TMH_RESPONSE_reply_withdraw_status_success (struct MHD_Connection *connection,
- const struct TALER_MINTDB_ReserveHistory *rh)
+TMH_RESPONSE_reply_reserve_status_success (struct MHD_Connection *connection,
+ const struct TALER_MINTDB_ReserveHistory *rh)
{
json_t *json_balance;
json_t *json_history;
@@ -654,15 +654,15 @@ TMH_RESPONSE_reply_withdraw_status_success (struct MHD_Connection *connection,
/**
* Send reserve status information to client with the
* message that we have insufficient funds for the
- * requested /withdraw/sign operation.
+ * requested /reserve/withdraw operation.
*
* @param connection connection to the client
* @param rh reserve history to return
* @return MHD result code
*/
int
-TMH_RESPONSE_reply_withdraw_sign_insufficient_funds (struct MHD_Connection *connection,
- const struct TALER_MINTDB_ReserveHistory *rh)
+TMH_RESPONSE_reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection,
+ const struct TALER_MINTDB_ReserveHistory *rh)
{
json_t *json_balance;
json_t *json_history;
@@ -691,7 +691,7 @@ TMH_RESPONSE_reply_withdraw_sign_insufficient_funds (struct MHD_Connection *conn
* @return MHD result code
*/
int
-TMH_RESPONSE_reply_withdraw_sign_success (struct MHD_Connection *connection,
+TMH_RESPONSE_reply_reserve_withdraw_success (struct MHD_Connection *connection,
const struct TALER_MINTDB_CollectableBlindcoin *collectable)
{
json_t *sig_json;
diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h
@@ -245,22 +245,22 @@ TMH_RESPONSE_reply_deposit_insufficient_funds (struct MHD_Connection *connection
* @return MHD result code
*/
int
-TMH_RESPONSE_reply_withdraw_status_success (struct MHD_Connection *connection,
- const struct TALER_MINTDB_ReserveHistory *rh);
+TMH_RESPONSE_reply_reserve_status_success (struct MHD_Connection *connection,
+ const struct TALER_MINTDB_ReserveHistory *rh);
/**
* Send reserve status information to client with the
* message that we have insufficient funds for the
- * requested /withdraw/sign operation.
+ * requested /reserve/withdraw operation.
*
* @param connection connection to the client
* @param rh reserve history to return
* @return MHD result code
*/
int
-TMH_RESPONSE_reply_withdraw_sign_insufficient_funds (struct MHD_Connection *connection,
- const struct TALER_MINTDB_ReserveHistory *rh);
+TMH_RESPONSE_reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection,
+ const struct TALER_MINTDB_ReserveHistory *rh);
/**
@@ -271,8 +271,8 @@ TMH_RESPONSE_reply_withdraw_sign_insufficient_funds (struct MHD_Connection *conn
* @return MHD result code
*/
int
-TMH_RESPONSE_reply_withdraw_sign_success (struct MHD_Connection *connection,
- const struct TALER_MINTDB_CollectableBlindcoin *collectable);
+TMH_RESPONSE_reply_reserve_withdraw_success (struct MHD_Connection *connection,
+ const struct TALER_MINTDB_CollectableBlindcoin *collectable);
/**
diff --git a/src/mint/taler-mint-httpd_withdraw.c b/src/mint/taler-mint-httpd_withdraw.c
@@ -1,180 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014,2015 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-mint-httpd_withdraw.c
- * @brief Handle /withdraw/ requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include "taler-mint-httpd_withdraw.h"
-#include "taler-mint-httpd_parsing.h"
-#include "taler-mint-httpd_responses.h"
-#include "taler-mint-httpd_keystate.h"
-
-
-/**
- * Handle a "/withdraw/status" request. Parses the
- * given "reserve_pub" argument (which should contain the
- * EdDSA public key of a reserve) and then respond with the
- * status of the reserve.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-TMH_WITHDRAW_handler_withdraw_status (struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
-{
- struct TALER_ReservePublicKeyP reserve_pub;
- int res;
-
- res = TMH_PARSE_mhd_request_arg_data (connection,
- "reserve_pub",
- &reserve_pub,
- sizeof (struct TALER_ReservePublicKeyP));
- if (GNUNET_SYSERR == res)
- return MHD_NO; /* internal error */
- if (GNUNET_NO == res)
- return MHD_YES; /* parse error */
- return TMH_DB_execute_withdraw_status (connection,
- &reserve_pub);
-}
-
-
-/**
- * Handle a "/withdraw/sign" request. Parses the "reserve_pub"
- * EdDSA key of the reserve and the requested "denom_pub" which
- * specifies the key/value of the coin to be withdrawn, and checks
- * that the signature "reserve_sig" makes this a valid withdrawl
- * request from the specified reserve. If so, the envelope
- * with the blinded coin "coin_ev" is passed down to execute the
- * withdrawl operation.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-TMH_WITHDRAW_handler_withdraw_sign (struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
-{
- json_t *root;
- struct TALER_WithdrawRequestPS wsrd;
- int res;
- struct TALER_DenominationPublicKey denomination_pub;
- char *blinded_msg;
- size_t blinded_msg_len;
- struct TALER_Amount amount;
- struct TALER_Amount amount_with_fee;
- struct TALER_Amount fee_withdraw;
- struct TALER_ReserveSignatureP signature;
- struct TALER_MINTDB_DenominationKeyIssueInformation *dki;
- struct TMH_KS_StateHandle *ks;
-
- struct TMH_PARSE_FieldSpecification spec[] = {
- TMH_PARSE_member_variable ("coin_ev", (void **) &blinded_msg, &blinded_msg_len),
- TMH_PARSE_member_fixed ("reserve_pub", &wsrd.reserve_pub),
- TMH_PARSE_member_fixed ("reserve_sig", &signature),
- TMH_PARSE_member_denomination_public_key ("denom_pub", &denomination_pub),
- TMH_PARSE_MEMBER_END
- };
-
- res = TMH_PARSE_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &root);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) || (NULL == root) )
- return MHD_YES;
- res = TMH_PARSE_json_data (connection,
- root,
- spec);
- json_decref (root);
- if (GNUNET_OK != res)
- return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
- ks = TMH_KS_acquire ();
- dki = TMH_KS_denomination_key_lookup (ks,
- &denomination_pub,
- TMH_KS_DKU_WITHDRAW);
- if (NULL == dki)
- {
- TMH_PARSE_release_data (spec);
- return TMH_RESPONSE_reply_arg_unknown (connection,
- "denom_pub");
- }
- TALER_amount_ntoh (&amount,
- &dki->issue.properties.value);
- TALER_amount_ntoh (&fee_withdraw,
- &dki->issue.properties.fee_withdraw);
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_add (&amount_with_fee,
- &amount,
- &fee_withdraw));
- TALER_amount_hton (&wsrd.amount_with_fee,
- &amount_with_fee);
- TALER_amount_hton (&wsrd.withdraw_fee,
- &fee_withdraw);
- TMH_KS_release (ks);
- /* verify signature! */
- wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
- wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
-
- GNUNET_CRYPTO_rsa_public_key_hash (denomination_pub.rsa_public_key,
- &wsrd.h_denomination_pub);
- GNUNET_CRYPTO_hash (blinded_msg,
- blinded_msg_len,
- &wsrd.h_coin_envelope);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
- &wsrd.purpose,
- &signature.eddsa_signature,
- &wsrd.reserve_pub.eddsa_pub))
- {
- TALER_LOG_WARNING ("Client supplied invalid signature for /withdraw/sign request\n");
- TMH_PARSE_release_data (spec);
- return TMH_RESPONSE_reply_signature_invalid (connection,
- "reserve_sig");
- }
- res = TMH_DB_execute_withdraw_sign (connection,
- &wsrd.reserve_pub,
- &denomination_pub,
- blinded_msg,
- blinded_msg_len,
- &signature);
- TMH_PARSE_release_data (spec);
- return res;
-}
-
-/* end of taler-mint-httpd_withdraw.c */
diff --git a/src/mint/taler-mint-httpd_withdraw.h b/src/mint/taler-mint-httpd_withdraw.h
@@ -1,73 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-mint-httpd_withdraw.h
- * @brief Handle /withdraw/ requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#ifndef TALER_MINT_HTTPD_WITHDRAW_H
-#define TALER_MINT_HTTPD_WITHDRAW_H
-
-#include <microhttpd.h>
-#include "taler-mint-httpd.h"
-
-/**
- * Handle a "/withdraw/status" request. Parses the
- * given "reserve_pub" argument (which should contain the
- * EdDSA public key of a reserve) and then respond with the
- * status of the reserve.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-TMH_WITHDRAW_handler_withdraw_status (struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
-
-
-/**
- * Handle a "/withdraw/sign" request. Parses the "reserve_pub"
- * EdDSA key of the reserve and the requested "denom_pub" which
- * specifies the key/value of the coin to be withdrawn, and checks
- * that the signature "reserve_sig" makes this a valid withdrawl
- * request from the specified reserve. If so, the envelope
- * with the blinded coin "coin_ev" is passed down to execute the
- * withdrawl operation.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-TMH_WITHDRAW_handler_withdraw_sign (struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
-
-#endif
diff --git a/src/mintdb/perf_taler_mintdb.c b/src/mintdb/perf_taler_mintdb.c
@@ -287,28 +287,28 @@ main (int argc, char ** argv)
PERF_TALER_MINTDB_INIT_CMD_DEBUG ("End of transaction loading"),
PERF_TALER_MINTDB_INIT_CMD_GET_TIME ("27 - start"),
- PERF_TALER_MINTDB_INIT_CMD_LOOP ("27 - /withdraw/sign",
+ PERF_TALER_MINTDB_INIT_CMD_LOOP ("27 - /reserve/withdraw",
NB_WITHDRAW_SAVE),
PERF_TALER_MINTDB_INIT_CMD_LOAD_ARRAY ("27 - reserve",
- "27 - /withdraw/sign",
+ "27 - /reserve/withdraw",
"02 - save reserve"),
PERF_TALER_MINTDB_INIT_CMD_LOAD_ARRAY ("27 - dki",
- "27 - /withdraw/sign",
+ "27 - /reserve/withdraw",
"01 - save denomination"),
PERF_TALER_MINTDB_INIT_CMD_WITHDRAW_SIGN ("",
"27 - dki",
"27 - reserve"),
PERF_TALER_MINTDB_INIT_CMD_END_LOOP ("",
- "27 - /withdraw/sign"),
+ "27 - /reserve/withdraw"),
PERF_TALER_MINTDB_INIT_CMD_GET_TIME ("27 - end"),
PERF_TALER_MINTDB_INIT_CMD_GAUGER ("",
"27 - start",
"27 - end",
"POSTGRES",
- "Number of /withdraw/sign per second",
+ "Number of /reserve/withdraw per second",
"item/sec",
NB_WITHDRAW_SAVE),
- PERF_TALER_MINTDB_INIT_CMD_DEBUG ("End of /withdraw/sign"),
+ PERF_TALER_MINTDB_INIT_CMD_DEBUG ("End of /reserve/withdraw"),
PERF_TALER_MINTDB_INIT_CMD_GET_TIME ("28 - start"),
PERF_TALER_MINTDB_INIT_CMD_LOOP ("28 - /deposit",
diff --git a/src/mintdb/perf_taler_mintdb_interpreter.h b/src/mintdb/perf_taler_mintdb_interpreter.h
@@ -363,7 +363,7 @@
/**
- * The /withdraw/sign api call
+ * The /reserve/withdraw api call
*
* Exposes #PERF_TALER_MINTDB_COIN
*
diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c
@@ -593,7 +593,7 @@ postgres_prepare (PGconn *db_conn)
1, NULL);
/* Used in #postgres_insert_withdraw_info() to store
the signature of a blinded coin with the blinded coin's
- details before returning it during /withdraw/sign. We store
+ details before returning it during /reserve/withdraw. We store
the coin's denomination information (public key, signature)
and the blinded message as well as the reserve that the coin
is being withdrawn from and the signature of the message
@@ -616,9 +616,9 @@ postgres_prepare (PGconn *db_conn)
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);",
12, NULL);
/* Used in #postgres_get_withdraw_info() to
- locate the response for a /withdraw/sign request
+ locate the response for a /reserve/withdraw request
using the hash of the blinded message. Used to
- make sure /withdraw/sign requests are idempotent. */
+ make sure /reserve/withdraw requests are idempotent. */
PREPARE ("get_withdraw_info",
"SELECT"
" denom_pub"
@@ -636,7 +636,7 @@ postgres_prepare (PGconn *db_conn)
" WHERE h_blind_ev=$1",
1, NULL);
/* Used during #postgres_get_reserve_history() to
- obtain all of the /withdraw/sign operations that
+ obtain all of the /reserve/withdraw operations that
have been performed on a given reserve. (i.e. to
demonstrate double-spending) */
PREPARE ("get_reserves_out",
@@ -1502,7 +1502,7 @@ postgres_reserves_in_insert (void *cls,
/**
- * Locate the response for a /withdraw/sign request under the
+ * Locate the response for a /reserve/withdraw request under the
* key of the hash of the blinded message.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state