aboutsummaryrefslogtreecommitdiff
path: root/src/mint
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-09-21 14:36:18 +0200
committerChristian Grothoff <christian@grothoff.org>2015-09-21 14:36:18 +0200
commit93a84d5e5aee9df869ac9e78a88c294d6311a9ef (patch)
tree060813cef751493abfa6c6417ed15031aec4842b /src/mint
parent70c28e53d0615bc6694ea2339a739d387f8d8691 (diff)
retry transactions on serialization/dead-lock failures (#3990)
Diffstat (limited to 'src/mint')
-rw-r--r--src/mint/taler-mint-httpd_db.c466
-rwxr-xr-xsrc/mint/test_taler_mint_httpd_afl.sh33
2 files changed, 305 insertions, 194 deletions
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c
index 021a3155d..da656abc2 100644
--- a/src/mint/taler-mint-httpd_db.c
+++ b/src/mint/taler-mint-httpd_db.c
@@ -24,6 +24,67 @@
#include "taler-mint-httpd_responses.h"
#include "taler-mint-httpd_keystate.h"
+/**
+ * How often should we retry a transaction before giving up
+ * (for transactions resulting in serialization/dead locks only).
+ */
+#define MAX_TRANSACTION_COMMIT_RETRIES 3
+
+/**
+ * Code to begin a transaction, must be inline as we define a block
+ * that ends with #COMMIT_TRANSACTION() within which we perform a number
+ * of retries. Note that this code may call "return" internally, so
+ * it must be called within a function where any cleanup will be done
+ * by the caller. Furthermore, the function's return value must
+ * match that of a #TMH_RESPONSE_reply_internal_db_error() status code.
+ *
+ * @param session session handle
+ * @param connection connection handle
+ */
+#define START_TRANSACTION(session,connection) \
+{ /* start new scope, will be ended by COMMIT_TRANSACTION() */\
+ unsigned int transaction_retries = 0; \
+ int transaction_commit_result; \
+transaction_start_label: /* we will use goto for retries */ \
+ if (GNUNET_OK != \
+ TMH_plugin->start (TMH_plugin->cls, \
+ session)) \
+ { \
+ GNUNET_break (0); \
+ return TMH_RESPONSE_reply_internal_db_error (connection); \
+ }
+
+/**
+ * Code to conclude a transaction, dual to #START_TRANSACTION(). Note
+ * that this code may call "return" internally, so it must be called
+ * within a function where any cleanup will be done by the caller.
+ * Furthermore, the function's return value must match that of a
+ * #TMH_RESPONSE_reply_internal_db_error() status code.
+ *
+ * @param session session handle
+ * @param connection connection handle
+ */
+#define COMMIT_TRANSACTION(session,connection) \
+ transaction_commit_result = \
+ TMH_plugin->commit (TMH_plugin->cls, \
+ session); \
+ if (GNUNET_SYSERR == transaction_commit_result) \
+ { \
+ TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \
+ return TMH_RESPONSE_reply_commit_error (connection); \
+ } \
+ if (GNUNET_NO == transaction_commit_result) \
+ { \
+ TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \
+ if (transaction_retries++ <= MAX_TRANSACTION_COMMIT_RETRIES) \
+ goto transaction_start_label; \
+ TALER_LOG_WARNING ("Transaction commit failed %u times in %s\n", \
+ transaction_retries, \
+ __FUNCTION__); \
+ return TMH_RESPONSE_reply_commit_error (connection); \
+ } \
+} /* end of scope opened by BEGIN_TRANSACTION */
+
/**
* Calculate the total value of all transactions performed.
@@ -130,13 +191,8 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
&dki->issue.properties.value);
TMH_KS_release (mks);
- if (GNUNET_OK !=
- TMH_plugin->start (TMH_plugin->cls,
- session))
- {
- GNUNET_break (0);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
+ START_TRANSACTION (session, connection);
+
/* fee for THIS transaction */
spent = deposit->amount_with_fee;
/* add cost of all previous transactions */
@@ -179,13 +235,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
return TMH_RESPONSE_reply_internal_db_error (connection);
}
- if (GNUNET_OK !=
- TMH_plugin->commit (TMH_plugin->cls,
- session))
- {
- TALER_LOG_WARNING ("/deposit transaction commit failed\n");
- return TMH_RESPONSE_reply_commit_error (connection);
- }
+ COMMIT_TRANSACTION(session, connection);
GNUNET_assert (GNUNET_OK ==
TALER_amount_subtract (&amount_without_fee,
&deposit->amount_with_fee,
@@ -242,35 +292,36 @@ TMH_DB_execute_reserve_status (struct MHD_Connection *connection,
/**
- * 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.
+ * Try to execute /reserve/withdraw transaction.
*
- * @param connection the MHD connection to handle
- * @param reserve public key of the reserve
+ * @param connection request we are handling
+ * @param session database session we are using
+ * @param reserve reserve to withdraw from
* @param denomination_pub public key of the denomination requested
+ * @param dki denomination to withdraw
* @param blinded_msg blinded message to be signed
* @param blinded_msg_len number of bytes in @a blinded_msg
* @param signature signature over the withdraw request, to be stored in DB
+ * @param denom_sig[out] where to write the resulting signature
+ * (used to release memory in case of transaction failure
* @return MHD result code
*/
-int
-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)
+static int
+execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
+ struct TALER_MINTDB_Session *session,
+ struct TMH_KS_StateHandle *key_state,
+ const struct TALER_ReservePublicKeyP *reserve,
+ const struct TALER_DenominationPublicKey *denomination_pub,
+ const struct TALER_MINTDB_DenominationKeyIssueInformation *dki,
+ const char *blinded_msg,
+ size_t blinded_msg_len,
+ const struct TALER_ReserveSignatureP *signature,
+ struct TALER_DenominationSignature *denom_sig)
{
- struct TALER_MINTDB_Session *session;
struct TALER_MINTDB_ReserveHistory *rh;
const struct TALER_MINTDB_ReserveHistory *pos;
- struct TMH_KS_StateHandle *key_state;
- struct TALER_MINTDB_CollectableBlindcoin collectable;
- struct TALER_MINTDB_DenominationKeyIssueInformation *dki;
struct TALER_MINTDB_DenominationKeyIssueInformation *tdki;
- struct GNUNET_CRYPTO_rsa_Signature *sig;
+ struct TALER_MINTDB_CollectableBlindcoin collectable;
struct TALER_Amount amount_required;
struct TALER_Amount deposit_total;
struct TALER_Amount withdraw_total;
@@ -280,60 +331,8 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
struct GNUNET_HashCode h_blind;
int res;
- GNUNET_CRYPTO_hash (blinded_msg,
- blinded_msg_len,
- &h_blind);
-
- if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls,
- TMH_test_mode)))
- {
- GNUNET_break (0);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
- res = TMH_plugin->get_withdraw_info (TMH_plugin->cls,
- session,
- &h_blind,
- &collectable);
- if (GNUNET_SYSERR == res)
- {
- GNUNET_break (0);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
-
- /* Don't sign again if we have already signed the coin */
- if (GNUNET_YES == res)
- {
- 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);
- return res;
- }
- GNUNET_assert (GNUNET_NO == res);
-
/* Check if balance is sufficient */
- key_state = TMH_KS_acquire ();
- dki = TMH_KS_denomination_key_lookup (key_state,
- denomination_pub,
- TMH_KS_DKU_WITHDRAW);
- if (NULL == dki)
- {
- TMH_KS_release (key_state);
- return TMH_RESPONSE_reply_json_pack (connection,
- MHD_HTTP_NOT_FOUND,
- "{s:s}",
- "error",
- "Denomination not found");
- }
- if (GNUNET_OK !=
- TMH_plugin->start (TMH_plugin->cls,
- session))
- {
- GNUNET_break (0);
- TMH_KS_release (key_state);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
-
+ START_TRANSACTION (session, connection);
rh = TMH_plugin->get_reserve_history (TMH_plugin->cls,
session,
reserve);
@@ -341,7 +340,6 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
{
TMH_plugin->rollback (TMH_plugin->cls,
session);
- TMH_KS_release (key_state);
return TMH_RESPONSE_reply_arg_unknown (connection,
"reserve_pub");
}
@@ -359,7 +357,6 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
{
TMH_plugin->rollback (TMH_plugin->cls,
session);
- TMH_KS_release (key_state);
return TMH_RESPONSE_reply_internal_db_error (connection);
}
@@ -380,7 +377,6 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
{
TMH_plugin->rollback (TMH_plugin->cls,
session);
- TMH_KS_release (key_state);
return TMH_RESPONSE_reply_internal_db_error (connection);
}
res |= 1;
@@ -401,7 +397,6 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
{
TMH_plugin->rollback (TMH_plugin->cls,
session);
- TMH_KS_release (key_state);
return TMH_RESPONSE_reply_internal_db_error (connection);
}
res |= 2;
@@ -428,11 +423,10 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
if (0 < TALER_amount_cmp (&amount_required,
&balance))
{
- TMH_KS_release (key_state);
TMH_plugin->rollback (TMH_plugin->cls,
session);
res = TMH_RESPONSE_reply_reserve_withdraw_insufficient_funds (connection,
- rh);
+ rh);
TMH_plugin->free_reserve_history (TMH_plugin->cls,
rh);
return res;
@@ -441,11 +435,11 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
rh);
/* Balance is good, sign the coin! */
- sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv.rsa_private_key,
- blinded_msg,
- blinded_msg_len);
- TMH_KS_release (key_state);
- if (NULL == sig)
+ denom_sig->rsa_signature
+ = GNUNET_CRYPTO_rsa_sign (dki->denom_priv.rsa_private_key,
+ blinded_msg,
+ blinded_msg_len);
+ if (NULL == denom_sig->rsa_signature)
{
GNUNET_break (0);
TMH_plugin->rollback (TMH_plugin->cls,
@@ -453,7 +447,7 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
return TMH_RESPONSE_reply_internal_error (connection,
"Internal error");
}
- collectable.sig.rsa_signature = sig;
+ collectable.sig = *denom_sig;
collectable.denom_pub = *denomination_pub;
collectable.amount_with_fee = amount_required;
collectable.withdraw_fee = fee_withdraw;
@@ -466,21 +460,105 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
&collectable))
{
GNUNET_break (0);
- GNUNET_CRYPTO_rsa_signature_free (sig);
TMH_plugin->rollback (TMH_plugin->cls,
session);
return TMH_RESPONSE_reply_internal_db_error (connection);
}
- if (GNUNET_OK !=
- TMH_plugin->commit (TMH_plugin->cls,
- session))
+ COMMIT_TRANSACTION (session, connection);
+
+ return TMH_RESPONSE_reply_reserve_withdraw_success (connection,
+ &collectable);
+}
+
+
+
+/**
+ * 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.
+ *
+ * @param connection the MHD connection to handle
+ * @param reserve public key of the reserve
+ * @param denomination_pub public key of the denomination requested
+ * @param blinded_msg blinded message to be signed
+ * @param blinded_msg_len number of bytes in @a blinded_msg
+ * @param signature signature over the withdraw request, to be stored in DB
+ * @return MHD result code
+ */
+int
+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 TMH_KS_StateHandle *key_state;
+ struct TALER_MINTDB_DenominationKeyIssueInformation *dki;
+ struct TALER_MINTDB_CollectableBlindcoin collectable;
+ struct TALER_DenominationSignature denom_sig;
+ struct GNUNET_HashCode h_blind;
+ int res;
+
+ GNUNET_CRYPTO_hash (blinded_msg,
+ blinded_msg_len,
+ &h_blind);
+
+ if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls,
+ TMH_test_mode)))
+ {
+ GNUNET_break (0);
+ return TMH_RESPONSE_reply_internal_db_error (connection);
+ }
+ res = TMH_plugin->get_withdraw_info (TMH_plugin->cls,
+ session,
+ &h_blind,
+ &collectable);
+ if (GNUNET_SYSERR == res)
+ {
+ GNUNET_break (0);
+ return TMH_RESPONSE_reply_internal_db_error (connection);
+ }
+
+ /* Don't sign again if we have already signed the coin */
+ if (GNUNET_YES == res)
{
- TALER_LOG_WARNING ("/reserve/withdraw transaction commit failed\n");
- return TMH_RESPONSE_reply_commit_error (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);
+ return res;
}
- res = TMH_RESPONSE_reply_reserve_withdraw_success (connection,
- &collectable);
- GNUNET_CRYPTO_rsa_signature_free (sig);
+ GNUNET_assert (GNUNET_NO == res);
+
+ key_state = TMH_KS_acquire ();
+ dki = TMH_KS_denomination_key_lookup (key_state,
+ denomination_pub,
+ TMH_KS_DKU_WITHDRAW);
+ if (NULL == dki)
+ {
+ TMH_KS_release (key_state);
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_NOT_FOUND,
+ "{s:s}",
+ "error",
+ "Denomination not found");
+ }
+ denom_sig.rsa_signature = NULL;
+ res = execute_reserve_withdraw_transaction (connection,
+ session,
+ key_state,
+ reserve,
+ denomination_pub,
+ dki,
+ blinded_msg,
+ blinded_msg_len,
+ signature,
+ &denom_sig);
+ GNUNET_CRYPTO_rsa_signature_free (denom_sig.rsa_signature);
+ TMH_KS_release (key_state);
return res;
}
@@ -633,13 +711,7 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
GNUNET_break (0);
return TMH_RESPONSE_reply_internal_db_error (connection);
}
- if (GNUNET_OK !=
- TMH_plugin->start (TMH_plugin->cls,
- session))
- {
- GNUNET_break (0);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
+ START_TRANSACTION (session, connection);
res = TMH_plugin->get_refresh_session (TMH_plugin->cls,
session,
session_hash,
@@ -741,13 +813,7 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
}
}
- if (GNUNET_OK !=
- TMH_plugin->commit (TMH_plugin->cls,
- session))
- {
- TALER_LOG_WARNING ("/refresh/melt transaction commit failed\n");
- return TMH_RESPONSE_reply_commit_error (connection);
- }
+ COMMIT_TRANSACTION (session, connection);
return TMH_RESPONSE_reply_refresh_melt_success (connection,
session_hash,
refresh_session.noreveal_index);
@@ -1038,10 +1104,10 @@ refresh_mint_coin (struct MHD_Connection *connection,
}
if (GNUNET_OK !=
TMH_plugin->insert_refresh_out (TMH_plugin->cls,
- session,
- session_hash,
- coin_off,
- &ev_sig))
+ session,
+ session_hash,
+ coin_off,
+ &ev_sig))
{
GNUNET_break (0);
GNUNET_CRYPTO_rsa_signature_free (ev_sig.rsa_signature);
@@ -1052,6 +1118,74 @@ refresh_mint_coin (struct MHD_Connection *connection,
/**
+ * The client request was well-formed, now execute the DB transaction
+ * of a "/refresh/reveal" operation. We use the @a ev_sigs and
+ * @a commit_coins to clean up resources after this function returns
+ * as we might experience retries of the database transaction.
+ *
+ * @param connection the MHD connection to handle
+ * @param session database session
+ * @param session_hash hash identifying the refresh session
+ * @param refresh_session information about the refresh operation we are doing
+ * @param denom_pubs array of "num_newcoins" denomination keys for the new coins
+ * @param ev_sigs[out] where to store generated signatures for the new coins,
+ * array of length "num_newcoins", memory released by the
+ * caller
+ * @param commit_coins[out] array of length "num_newcoins" to be used for
+ * information about the new coins from the commitment.
+ * @return MHD result code
+ */
+static int
+execute_refresh_reveal_transaction (struct MHD_Connection *connection,
+ struct TALER_MINTDB_Session *session,
+ const struct GNUNET_HashCode *session_hash,
+ struct TALER_MINTDB_RefreshSession *refresh_session,
+ struct TALER_MINTDB_RefreshMelt *melts,
+ struct TALER_DenominationPublicKey *denom_pubs,
+ struct TALER_DenominationSignature *ev_sigs,
+ struct TALER_MINTDB_RefreshCommitCoin *commit_coins)
+{
+ unsigned int j;
+ struct TMH_KS_StateHandle *key_state;
+
+ START_TRANSACTION (session, connection);
+ if (GNUNET_OK !=
+ TMH_plugin->get_refresh_commit_coins (TMH_plugin->cls,
+ session,
+ session_hash,
+ refresh_session->noreveal_index,
+ refresh_session->num_newcoins,
+ commit_coins))
+ {
+ GNUNET_break (0);
+ return TMH_RESPONSE_reply_internal_db_error (connection);
+ }
+ key_state = TMH_KS_acquire ();
+ for (j=0;j<refresh_session->num_newcoins;j++)
+ {
+ if (NULL == ev_sigs[j].rsa_signature) /* could be non-NULL during retries */
+ ev_sigs[j] = refresh_mint_coin (connection,
+ session,
+ session_hash,
+ key_state,
+ &denom_pubs[j],
+ &commit_coins[j],
+ j);
+ if (NULL == ev_sigs[j].rsa_signature)
+ {
+ TMH_KS_release (key_state);
+ return TMH_RESPONSE_reply_internal_db_error (connection);
+ }
+ }
+ TMH_KS_release (key_state);
+ COMMIT_TRANSACTION (session, connection);
+ return TMH_RESPONSE_reply_refresh_reveal_success (connection,
+ refresh_session->num_newcoins,
+ ev_sigs);
+}
+
+
+/**
* Execute a "/refresh/reveal". The client is revealing to us the
* transfer keys for @a #TALER_CNC_KAPPA-1 sets of coins. Verify that the
* revealed transfer keys would allow linkage to the blinded coins,
@@ -1074,7 +1208,6 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
int res;
struct TALER_MINTDB_Session *session;
struct TALER_MINTDB_RefreshSession refresh_session;
- struct TMH_KS_StateHandle *key_state;
struct TALER_MINTDB_RefreshMelt *melts;
struct TALER_DenominationPublicKey *denom_pubs;
struct TALER_DenominationSignature *ev_sigs;
@@ -1164,82 +1297,27 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
GNUNET_free (melts);
/* Client request OK, start transaction */
- if (GNUNET_OK !=
- TMH_plugin->start (TMH_plugin->cls,
- session))
- {
- GNUNET_break (0);
- for (j=0;j<refresh_session.num_newcoins;j++)
- GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
- GNUNET_free (denom_pubs);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
-
commit_coins = GNUNET_malloc (refresh_session.num_newcoins *
sizeof (struct TALER_MINTDB_RefreshCommitCoin));
- if (GNUNET_OK !=
- TMH_plugin->get_refresh_commit_coins (TMH_plugin->cls,
- session,
- session_hash,
- refresh_session.noreveal_index,
- refresh_session.num_newcoins,
- commit_coins))
- {
- GNUNET_break (0);
- GNUNET_free (commit_coins);
- for (j=0;j<refresh_session.num_newcoins;j++)
- GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
- GNUNET_free (denom_pubs);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
ev_sigs = GNUNET_malloc (refresh_session.num_newcoins *
sizeof (struct TALER_DenominationSignature));
- key_state = TMH_KS_acquire ();
- for (j=0;j<refresh_session.num_newcoins;j++)
- {
- ev_sigs[j] = refresh_mint_coin (connection,
- session,
- session_hash,
- key_state,
- &denom_pubs[j],
- &commit_coins[j],
- j);
- if (NULL == ev_sigs[j].rsa_signature)
- {
- TMH_KS_release (key_state);
- for (i=0;i<j;i++)
- GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i].rsa_signature);
- GNUNET_free (ev_sigs);
- for (j=0;j<refresh_session.num_newcoins;j++)
- GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
- GNUNET_free (denom_pubs);
- GNUNET_free (commit_coins);
- return TMH_RESPONSE_reply_internal_db_error (connection);
- }
- }
- TMH_KS_release (key_state);
- for (j=0;j<refresh_session.num_newcoins;j++)
- GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
- GNUNET_free (denom_pubs);
- GNUNET_free (commit_coins);
-
- if (GNUNET_OK !=
- TMH_plugin->commit (TMH_plugin->cls,
- session))
- {
- TALER_LOG_WARNING ("/refresh/reveal transaction commit failed\n");
- for (i=0;i<refresh_session.num_newcoins;i++)
- GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i].rsa_signature);
- GNUNET_free (ev_sigs);
- return TMH_RESPONSE_reply_commit_error (connection);
- }
-
- res = TMH_RESPONSE_reply_refresh_reveal_success (connection,
- refresh_session.num_newcoins,
- ev_sigs);
+ res = execute_refresh_reveal_transaction (connection,
+ session,
+ session_hash,
+ &refresh_session,
+ melts,
+ denom_pubs,
+ ev_sigs,
+ commit_coins);
for (i=0;i<refresh_session.num_newcoins;i++)
+ if (NULL != ev_sigs[i].rsa_signature)
GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i].rsa_signature);
+ for (j=0;j<refresh_session.num_newcoins;j++)
+ if (NULL != denom_pubs[j].rsa_public_key)
+ GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
GNUNET_free (ev_sigs);
+ GNUNET_free (denom_pubs);
+ GNUNET_free (commit_coins);
return res;
}
diff --git a/src/mint/test_taler_mint_httpd_afl.sh b/src/mint/test_taler_mint_httpd_afl.sh
new file mode 100755
index 000000000..62ad43610
--- /dev/null
+++ b/src/mint/test_taler_mint_httpd_afl.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# This file is part of TALER
+# Copyright (C) 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/>
+#
+#
+# This script uses 'curl' to POST various ill-formed requests to the
+# taler-mint-httpd. Basically, the goal is to make sure that the
+# HTTP server survives (and produces the 'correct' error code).
+#
+# We read the JSON snippets from afl-tests/
+#
+# Setup keys.
+taler-mint-keyup -d test-mint-home -m test-mint-home/master.priv
+# Run test...
+for n in afl-tests/*.req
+do
+ echo -n "Test $n"
+ taler-mint-httpd -d test-mint-home/ -t 1 -f $n -C > /dev/null || { echo "FAIL!"; exit 1; }
+ echo "OK"
+done
+exit 0