summaryrefslogtreecommitdiff
path: root/src/exchange-lib/exchange_api_reserve.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange-lib/exchange_api_reserve.c')
-rw-r--r--src/exchange-lib/exchange_api_reserve.c218
1 files changed, 157 insertions, 61 deletions
diff --git a/src/exchange-lib/exchange_api_reserve.c b/src/exchange-lib/exchange_api_reserve.c
index ef505d87d..c0f77219b 100644
--- a/src/exchange-lib/exchange_api_reserve.c
+++ b/src/exchange-lib/exchange_api_reserve.c
@@ -967,97 +967,57 @@ handle_reserve_withdraw_finished (void *cls,
/**
- * Withdraw a coin from the exchange 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.
+ * Helper function for #TALER_EXCHANGE_reserve_withdraw2() and
+ * #TALER_EXCHANGE_reserve_withdraw().
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param pk kind of coin to create
- * @param reserve_priv private key of the reserve to withdraw from
+ * @param reserve_sig signature from the reserve authorizing the withdrawal
+ * @param reserve_pub public key of the reserve to withdraw from
* @param ps secrets of the planchet
* caller must have committed this value to disk before the call (with @a pk)
+ * @param pd planchet details matching @a ps
* @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 handle for the operation on success, NULL on error, i.e.
+ * @param res_cb_cls closure for @a res_cb
+ * @return NULL
* if the inputs are invalid (i.e. denomination key not with this exchange).
* In this case, the callback is not called.
*/
struct TALER_EXCHANGE_ReserveWithdrawHandle *
-TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_EXCHANGE_DenomPublicKey *pk,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_PlanchetSecretsP *ps,
- TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
- void *res_cb_cls)
+reserve_withdraw_internal (struct TALER_EXCHANGE_Handle *exchange,
+ const struct TALER_EXCHANGE_DenomPublicKey *pk,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_PlanchetSecretsP *ps,
+ const struct TALER_PlanchetDetail *pd,
+ TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
+ void *res_cb_cls)
{
struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
- struct TALER_WithdrawRequestPS req;
- struct TALER_ReserveSignatureP reserve_sig;
struct GNUNET_CURL_Context *ctx;
- struct TALER_Amount amount_with_fee;
json_t *withdraw_obj;
CURL *eh;
- struct TALER_PlanchetDetail pd;
- if (GNUNET_OK !=
- TALER_planchet_prepare (&pk->key,
- ps,
- &pd))
- {
- GNUNET_break_op (0);
- return NULL;
- }
wsh = GNUNET_new (struct TALER_EXCHANGE_ReserveWithdrawHandle);
wsh->exchange = exchange;
wsh->cb = res_cb;
wsh->cb_cls = res_cb_cls;
wsh->pk = pk;
- wsh->c_hash = pd.c_hash;
- 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))
- {
- /* exchange gave us denomination keys that overflow like this!? */
- GNUNET_break_op (0);
- GNUNET_free (pd.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);
- req.h_denomination_pub = pd.denom_pub_hash;
- GNUNET_CRYPTO_hash (pd.coin_ev,
- pd.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));
+ wsh->reserve_pub = *reserve_pub;
+ wsh->c_hash = pd->c_hash;
withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */
" s:o, s:o}",/* reserve_pub and reserve_sig */
"denom_pub", GNUNET_JSON_from_rsa_public_key (pk->key.rsa_public_key),
- "coin_ev", GNUNET_JSON_from_data (pd.coin_ev,
- pd.coin_ev_size),
- "reserve_pub", GNUNET_JSON_from_data_auto (&wsh->reserve_pub),
- "reserve_sig", GNUNET_JSON_from_data_auto (&reserve_sig));
- GNUNET_free (pd.coin_ev);
+ "coin_ev", GNUNET_JSON_from_data (pd->coin_ev,
+ pd->coin_ev_size),
+ "reserve_pub", GNUNET_JSON_from_data_auto (reserve_pub),
+ "reserve_sig", GNUNET_JSON_from_data_auto (reserve_sig));
if (NULL == withdraw_obj)
{
GNUNET_break (0);
return NULL;
}
-
wsh->ps = *ps;
wsh->url = MAH_path_to_url (exchange, "/reserve/withdraw");
@@ -1089,6 +1049,142 @@ TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
/**
+ * Withdraw a coin from the exchange 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 exchange the exchange handle; the exchange must be ready to operate
+ * @param pk kind of coin to create
+ * @param reserve_priv private key of the reserve to withdraw from
+ * @param ps secrets of the planchet
+ * 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 handle for the operation on success, NULL on error, i.e.
+ * if the inputs are invalid (i.e. denomination key not with this exchange).
+ * In this case, the callback is not called.
+ */
+struct TALER_EXCHANGE_ReserveWithdrawHandle *
+TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
+ const struct TALER_EXCHANGE_DenomPublicKey *pk,
+ const struct TALER_ReservePrivateKeyP *reserve_priv,
+ const struct TALER_PlanchetSecretsP *ps,
+ TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
+ void *res_cb_cls)
+{
+ struct TALER_Amount amount_with_fee;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_WithdrawRequestPS req;
+ struct TALER_PlanchetDetail pd;
+ struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
+
+ GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
+ &reserve_pub.eddsa_pub);
+ GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
+ &req.reserve_pub.eddsa_pub);
+ req.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
+ req.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
+ if (GNUNET_OK !=
+ TALER_amount_add (&amount_with_fee,
+ &pk->fee_withdraw,
+ &pk->value))
+ {
+ /* exchange gave us denomination keys that overflow like this!? */
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ TALER_amount_hton (&req.amount_with_fee,
+ &amount_with_fee);
+ TALER_amount_hton (&req.withdraw_fee,
+ &pk->fee_withdraw);
+ req.h_denomination_pub = pd.denom_pub_hash;
+ if (GNUNET_OK !=
+ TALER_planchet_prepare (&pk->key,
+ ps,
+ &pd))
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ GNUNET_CRYPTO_hash (pd.coin_ev,
+ pd.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));
+ wsh = reserve_withdraw_internal (exchange,
+ pk,
+ &reserve_sig,
+ &req.reserve_pub,
+ ps,
+ &pd,
+ res_cb,
+ res_cb_cls);
+ GNUNET_free (pd.coin_ev);
+ return wsh;
+}
+
+
+/**
+ * Withdraw a coin from the exchange using a /reserve/withdraw
+ * request. This API is typically used by a wallet to withdraw a tip
+ * where the reserve's signature was created by the merchant already.
+ *
+ * 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 exchange the exchange handle; the exchange must be ready to operate
+ * @param pk kind of coin to create
+ * @param reserve_sig signature from the reserve authorizing the withdrawal
+ * @param reserve_pub public key of the reserve to withdraw from
+ * @param ps secrets of the planchet
+ * 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 @a res_cb
+ * @return NULL
+ * if the inputs are invalid (i.e. denomination key not with this exchange).
+ * In this case, the callback is not called.
+ */
+struct TALER_EXCHANGE_ReserveWithdrawHandle *
+TALER_EXCHANGE_reserve_withdraw2 (struct TALER_EXCHANGE_Handle *exchange,
+ const struct TALER_EXCHANGE_DenomPublicKey *pk,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_PlanchetSecretsP *ps,
+ TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
+ void *res_cb_cls)
+{
+ struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
+ struct TALER_PlanchetDetail pd;
+
+ if (GNUNET_OK !=
+ TALER_planchet_prepare (&pk->key,
+ ps,
+ &pd))
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ wsh = reserve_withdraw_internal (exchange,
+ pk,
+ reserve_sig,
+ reserve_pub,
+ ps,
+ &pd,
+ res_cb,
+ res_cb_cls);
+ GNUNET_free (pd.coin_ev);
+ return wsh;
+}
+
+
+/**
* Cancel a withdraw status request. This function cannot be used
* on a request handle if a response is already served for it.
*