gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-exchange] branch master updated (39db1ae -> 87e1654)


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated (39db1ae -> 87e1654)
Date: Tue, 20 Jun 2017 23:20:54 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a change to branch master
in repository exchange.

    from 39db1ae  address #5010 for /refresh/link
     new 0530964  fixing #5010 for /refresh/reveal
     new 87e1654  incomplete work on fixing #5010 for /refresh/melt

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/exchange/taler-exchange-httpd_refresh_melt.c   | 583 ++++++++----------
 src/exchange/taler-exchange-httpd_refresh_reveal.c | 674 ++++++++++-----------
 src/exchangedb/plugin_exchangedb_postgres.c        | 333 ++++------
 src/exchangedb/test_exchangedb.c                   |  45 +-
 src/include/taler_error_codes.h                    |  16 -
 src/include/taler_exchangedb_plugin.h              |  33 +-
 6 files changed, 699 insertions(+), 985 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c 
b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 1c4e5e8..71f5a99 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -32,94 +32,6 @@
 
 
 /**
- * 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 #TEH_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;                       \
-  enum GNUNET_DB_QueryStatus transaction_commit_result;       \
-transaction_start_label: /* we will use goto for retries */   \
-  if (GNUNET_OK !=                                            \
-      TEH_plugin->start (TEH_plugin->cls,                     \
-                         session))                            \
-  {                                                           \
-    GNUNET_break (0);                                         \
-    return TEH_RESPONSE_reply_internal_db_error (connection, \
-                                                TALER_EC_DB_START_FAILED);     
     \
-  }
-
-/**
- * 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
- * #TEH_RESPONSE_reply_internal_db_error() status code.
- *
- * @param session session handle
- * @param connection connection handle
- */
-#define COMMIT_TRANSACTION(session,connection)                             \
-  transaction_commit_result =                                              \
-    TEH_plugin->commit (TEH_plugin->cls,                                   \
-                        session);                                          \
-  if (GNUNET_DB_STATUS_HARD_ERROR == transaction_commit_result)            \
-  {                                                                        \
-    TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \
-    return TEH_RESPONSE_reply_commit_error (connection, \
-                                           TALER_EC_DB_COMMIT_FAILED_HARD); \
-  }                                                       \
-  if (GNUNET_DB_STATUS_SOFT_ERROR == 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 TEH_RESPONSE_reply_commit_error (connection, \
-                                           
TALER_EC_DB_COMMIT_FAILED_ON_RETRY);                                \
-  }                                                                        \
-} /* end of scope opened by BEGIN_TRANSACTION */
-
-
-/**
- * Code to include to retry a transaction, must only be used in between
- * #START_TRANSACTION and #COMMIT_TRANSACTION.
- *
- * @param session session handle
- * @param connection connection handle
- */
-#define RETRY_TRANSACTION(session,connection)                                  
  \
-  do {                                                                         
  \
-    TEH_plugin->rollback (TEH_plugin->cls,                                     
  \
-                          session);                                            
  \
-    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 TEH_RESPONSE_reply_commit_error (connection,                        
  \
-                                           
TALER_EC_DB_COMMIT_FAILED_ON_RETRY); \
-  } while (0)
-
-
-
-
-/**
  * @brief Details about a melt operation of an individual coin.
  */
 struct TEH_DB_MeltDetails
@@ -238,6 +150,56 @@ reply_refresh_melt_success (struct MHD_Connection 
*connection,
 
 
 /**
+ * Context for the /refresh/melt operation.
+ */
+struct RefreshMeltContext
+{
+
+  /**
+   * Array of denominations of the fresh coins.
+   */
+  struct TALER_DenominationPublicKey *denom_pubs;
+
+  /**
+   * Number of new coins to be generated in the melt.
+   * Size of the @e denom_pubs array.
+   */
+  unsigned int num_newcoins;
+
+  /**
+   * Details about the coin to be melted.
+   */
+  struct TEH_DB_MeltDetails coin_melt_details;
+
+  /**
+   * Set to the session hash once the @e hash_context has finished.
+   */ 
+  struct GNUNET_HashCode session_hash;
+
+  /**
+   * Hash operation used to calculate the session hash.
+   */
+  struct GNUNET_HashContext *hash_context;
+
+  /**
+   * Committments to the blinded envelopes for the fresh coins.
+   */
+  struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin[TALER_CNC_KAPPA];
+
+  /**
+   * Commmittments to the transfer public keys.
+   */
+  struct TALER_TransferPublicKeyP transfer_pub[TALER_CNC_KAPPA];
+
+  /**
+   * Initialized during #refresh_melt_transaction().
+   */
+  struct TALER_EXCHANGEDB_RefreshSession refresh_session;
+
+};
+
+
+/**
  * Parse coin melt requests from a JSON object and write them to
  * the database.
  *
@@ -341,136 +303,102 @@ refresh_check_melt (struct MHD_Connection *connection,
  * required value left and if so, store that they have been
  * melted and confirm the melting operation to the client.
  *
- * @param connection the MHD connection to handle
- * @param session_hash hash code of the session the coins are melted into
- * @param num_new_denoms number of entries in @a denom_pubs, size of 
y-dimension of @a commit_coin array
- * @param denom_pubs public keys of the coins we want to withdraw in the end
- * @param coin_melt_detail signature and (residual) value of the respective 
coin should be melted
- * @param commit_coin 2d array of coin commitments (what the exchange is to 
sign
- *                    once the "/refres/reveal" of cut and choose is done),
- *                    x-dimension must be #TALER_CNC_KAPPA
- * @param transfer_pubs array of transfer public keys (what the exchange is
- *                    to return via "/refresh/link" to enable linkage in the
- *                    future) of length #TALER_CNC_KAPPA
- * @return MHD result code
+ * If it returns a non-error code, the transaction logic MUST
+ * NOT queue a MHD response.  IF it returns an hard error, the
+ * transaction logic MUST queue a MHD response and set @a mhd_ret.  IF
+ * it returns the soft error code, the function MAY be called again to
+ * retry and MUST not queue a MHD response.
+ *
+ * @param cls our `struct RefreshMeltContext`
+ * @param connection MHD request which triggered the transaction
+ * @param session database session to use
+ * @param[out] mhd_ret set to MHD response status for @a connection,
+ *             if transaction failed (!)
+ * @return transaction status
  */
-static int
-execute_refresh_melt (struct MHD_Connection *connection,
-                     const struct GNUNET_HashCode *session_hash,
-                     unsigned int num_new_denoms,
-                     const struct TALER_DenominationPublicKey *denom_pubs,
-                     const struct TEH_DB_MeltDetails *coin_melt_detail,
-                     struct TALER_EXCHANGEDB_RefreshCommitCoin *const* 
commit_coin,
-                     const struct TALER_TransferPublicKeyP *transfer_pubs)
+static enum GNUNET_DB_QueryStatus
+refresh_melt_transaction (void *cls,
+                         struct MHD_Connection *connection,
+                         struct TALER_EXCHANGEDB_Session *session,
+                         int *mhd_ret)
 {
+  struct RefreshMeltContext *rmc = cls;
   struct TEH_KS_StateHandle *key_state;
-  struct TALER_EXCHANGEDB_RefreshSession refresh_session;
-  struct TALER_EXCHANGEDB_Session *session;
+  enum GNUNET_DB_QueryStatus qs;
   int res;
 
-  if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
+  qs = TEH_plugin->get_refresh_session (TEH_plugin->cls,
+                                       session,
+                                       &rmc->session_hash,
+                                       &rmc->refresh_session);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
-    GNUNET_break (0);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                TALER_EC_DB_SETUP_FAILED);
+    *mhd_ret = reply_refresh_melt_success (connection,
+                                          &rmc->session_hash,
+                                          rmc->refresh_session.noreveal_index);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  START_TRANSACTION (session, connection);
-  res = TEH_plugin->get_refresh_session (TEH_plugin->cls,
-                                         session,
-                                         session_hash,
-                                         &refresh_session);
-  if (GNUNET_YES == res)
+  if (0 > qs)
   {
-    TEH_plugin->rollback (TEH_plugin->cls,
-                          session);
-    res = reply_refresh_melt_success (connection,
-                                     session_hash,
-                                     refresh_session.noreveal_index);
-    return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
-  }
-  if (GNUNET_SYSERR == res)
-  {
-    TEH_plugin->rollback (TEH_plugin->cls,
-                          session);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
+    if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+      *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                      
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
+    return qs;
   }
 
   /* store 'global' session data */
-  refresh_session.num_newcoins = num_new_denoms;
-  refresh_session.noreveal_index
+  rmc->refresh_session.num_newcoins = rmc->num_newcoins;
+  rmc->refresh_session.noreveal_index
     = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
                                TALER_CNC_KAPPA);
+
   key_state = TEH_KS_acquire ();
   if (GNUNET_OK !=
       (res = refresh_check_melt (connection,
-                                 session,
-                                 key_state,
-                                 session_hash,
-                                 coin_melt_detail,
-                                 &refresh_session.melt)))
+                                session,
+                                key_state,
+                                &rmc->session_hash,
+                                &rmc->coin_melt_details,
+                                &rmc->refresh_session.melt)))
   {
     TEH_KS_release (key_state);
-    TEH_plugin->rollback (TEH_plugin->cls,
-                          session);
-    return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+    *mhd_ret = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+    return GNUNET_DB_STATUS_HARD_ERROR;    
   }
   TEH_KS_release (key_state);
 
-  if (GNUNET_OK !=
-      (res = TEH_plugin->create_refresh_session (TEH_plugin->cls,
-                                                 session,
-                                                 session_hash,
-                                                 &refresh_session)))
-  {
-    TEH_plugin->rollback (TEH_plugin->cls,
-                          session);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                
TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR);
-  }
-
-  /* store requested new denominations */
-  if (GNUNET_OK !=
-      TEH_plugin->insert_refresh_order (TEH_plugin->cls,
-                                        session,
-                                        session_hash,
-                                        num_new_denoms,
-                                        denom_pubs))
+  if ( (0 >=
+       (qs = TEH_plugin->create_refresh_session (TEH_plugin->cls,
+                                                 session,
+                                                 &rmc->session_hash,
+                                                 &rmc->refresh_session))) ||
+       (0 >=
+       (qs = TEH_plugin->insert_refresh_order (TEH_plugin->cls,
+                                               session,
+                                               &rmc->session_hash,
+                                               rmc->num_newcoins,
+                                               rmc->denom_pubs))) ||
+       (0 >=
+       (qs = TEH_plugin->insert_refresh_commit_coins (TEH_plugin->cls,
+                                                      session,
+                                                      &rmc->session_hash,
+                                                      rmc->num_newcoins,
+                                                      
rmc->commit_coin[rmc->refresh_session.noreveal_index]))) ||
+       (0 >=
+       (qs = TEH_plugin->insert_refresh_transfer_public_key (TEH_plugin->cls,
+                                                             session,
+                                                             
&rmc->session_hash,
+                                                             
&rmc->transfer_pub[rmc->refresh_session.noreveal_index]))) )
   {
-    TEH_plugin->rollback (TEH_plugin->cls,
-                          session);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                
TALER_EC_REFRESH_MELT_DB_STORE_ORDER_ERROR);
-  }
-
-  if (GNUNET_OK !=
-      TEH_plugin->insert_refresh_commit_coins (TEH_plugin->cls,
-                                               session,
-                                               session_hash,
-                                               num_new_denoms,
-                                               
commit_coin[refresh_session.noreveal_index]))
-  {
-    TEH_plugin->rollback (TEH_plugin->cls,
-                          session);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                
TALER_EC_REFRESH_MELT_DB_STORE_ORDER_ERROR);
-  }
-  if (GNUNET_OK !=
-      TEH_plugin->insert_refresh_transfer_public_key (TEH_plugin->cls,
-                                                      session,
-                                                      session_hash,
-                                                      
&transfer_pubs[refresh_session.noreveal_index]))
-  {
-    TEH_plugin->rollback (TEH_plugin->cls,
-                          session);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                
TALER_EC_REFRESH_MELT_DB_STORE_TRANSFER_ERROR);
+    if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+    {
+      *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                      
TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    return qs;
   }
-
-  COMMIT_TRANSACTION (session, connection);
-  return reply_refresh_melt_success (connection,
-                                    session_hash,
-                                    refresh_session.noreveal_index);
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -480,27 +408,15 @@ execute_refresh_melt (struct MHD_Connection *connection,
  * and then hand things of to execute the melt operation.
  *
  * @param connection the MHD connection to handle
- * @param num_new_denoms number of coins to be created, size of y-dimension of 
@a commit_link array
- * @param denom_pubs array of @a num_new_denoms keys
- * @param coin_melt_details melting details
- * @param session_hash hash over the data that the client commits to
- * @param commit_coin 2d array of coin commitments (what the exchange is to 
sign
- *                    once the "/refres/reveal" of cut and choose is done)
- * @param transfer_pubs array of transfer public keys (which the exchange is
- *                    to return via "/refresh/link" to enable linkage in the
- *                    future) of length #TALER_CNC_KAPPA
+ * @param[out] mhd_ret set on failure to return value for MHD
+ * @param rmc information about the melt to process
  * @return MHD result code
  */
 static int
-handle_refresh_melt_binary (struct MHD_Connection *connection,
-                            unsigned int num_new_denoms,
-                            const struct TALER_DenominationPublicKey 
*denom_pubs,
-                            const struct TEH_DB_MeltDetails *coin_melt_details,
-                            const struct GNUNET_HashCode *session_hash,
-                            struct TALER_EXCHANGEDB_RefreshCommitCoin *const* 
commit_coin,
-                            const struct TALER_TransferPublicKeyP 
*transfer_pubs)
+refresh_melt_prepare (struct MHD_Connection *connection,
+                     int *mhd_ret,
+                     struct RefreshMeltContext *rmc)
 {
-  unsigned int i;
   struct TEH_KS_StateHandle *key_state;
   struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk;
   struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
@@ -513,24 +429,25 @@ handle_refresh_melt_binary (struct MHD_Connection 
*connection,
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "/refresh/melt request for session %s\n",
-              GNUNET_h2s (session_hash));
-
+              GNUNET_h2s (&rmc->session_hash));
+  
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_get_zero (TEH_exchange_currency_string,
                                         &total_cost));
   key_state = TEH_KS_acquire ();
-  for (i=0;i<num_new_denoms;i++)
+  for (unsigned int i=0;i<rmc->num_newcoins;i++)
   {
     dk = TEH_KS_denomination_key_lookup (key_state,
-                                         &denom_pubs[i],
+                                         &rmc->denom_pubs[i],
                                          TEH_KS_DKU_WITHDRAW);
     if (NULL == dk)
     {
       GNUNET_break_op (0);
       TEH_KS_release (key_state);
-      return TEH_RESPONSE_reply_arg_invalid (connection,
-                                            
TALER_EC_REFRESH_MELT_FRESH_DENOMINATION_KEY_NOT_FOUND,
-                                             "new_denoms");
+      *mhd_ret = TEH_RESPONSE_reply_arg_invalid (connection,
+                                                
TALER_EC_REFRESH_MELT_FRESH_DENOMINATION_KEY_NOT_FOUND,
+                                                "new_denoms");
+      return GNUNET_SYSERR;
     }
     dki = &dk->issue;
     TALER_amount_ntoh (&value,
@@ -548,35 +465,38 @@ handle_refresh_melt_binary (struct MHD_Connection 
*connection,
     {
       GNUNET_break_op (0);
       TEH_KS_release (key_state);
-      return TEH_RESPONSE_reply_internal_error (connection,
-                                               
TALER_EC_REFRESH_MELT_COST_CALCULATION_OVERFLOW,
-                                                "cost calculation failure");
+      *mhd_ret = TEH_RESPONSE_reply_internal_error (connection,
+                                                   
TALER_EC_REFRESH_MELT_COST_CALCULATION_OVERFLOW,
+                                                   "cost calculation failure");
+      return GNUNET_SYSERR;
     }
   }
 
   dk = TEH_KS_denomination_key_lookup (key_state,
-                                       &coin_melt_details->coin_info.denom_pub,
+                                       
&rmc->coin_melt_details.coin_info.denom_pub,
                                        TEH_KS_DKU_DEPOSIT);
   if (NULL == dk)
   {
     GNUNET_break (0);
-    return TEH_RESPONSE_reply_arg_unknown (connection,
-                                          
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
-                                          "denom_pub");
+    *mhd_ret = TEH_RESPONSE_reply_arg_unknown (connection,
+                                              
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
+                                              "denom_pub");
+    return GNUNET_SYSERR;
   }
   dki = &dk->issue;
   TALER_amount_ntoh (&fee_melt,
                      &dki->properties.fee_refresh);
   if (GNUNET_OK !=
       TALER_amount_subtract (&total_melt,
-                             &coin_melt_details->melt_amount_with_fee,
+                             &rmc->coin_melt_details.melt_amount_with_fee,
                              &fee_melt))
   {
     GNUNET_break_op (0);
     TEH_KS_release (key_state);
-    return TEH_RESPONSE_reply_external_error (connection,
-                                             
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION,
-                                              "Melt contribution below melting 
fee");
+    *mhd_ret = TEH_RESPONSE_reply_external_error (connection,
+                                                 
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION,
+                                                 "Melt contribution below 
melting fee");
+    return GNUNET_SYSERR;
   }
   TEH_KS_release (key_state);
   if (0 !=
@@ -586,19 +506,17 @@ handle_refresh_melt_binary (struct MHD_Connection 
*connection,
     GNUNET_break_op (0);
     /* We require total value of coins being melted and
        total value of coins being generated to match! */
-    return TEH_RESPONSE_reply_json_pack (connection,
-                                         MHD_HTTP_BAD_REQUEST,
-                                         "{s:s, s:I}",
-                                         "error", "value mismatch",
-                                        "code", (json_int_t) 
TALER_EC_REFRESH_MELT_FEES_MISSMATCH);
+    *mhd_ret = TEH_RESPONSE_reply_json_pack (connection,
+                                            MHD_HTTP_BAD_REQUEST,
+                                            "{s:s, s:I}",
+                                            "error", "value mismatch",
+                                            "code", (json_int_t) 
TALER_EC_REFRESH_MELT_FEES_MISSMATCH);
+    return GNUNET_SYSERR;
   }
-  return execute_refresh_melt (connection,
-                              session_hash,
-                              num_new_denoms,
-                              denom_pubs,
-                              coin_melt_details,
-                              commit_coin,
-                              transfer_pubs);
+  return TEH_DB_run_transaction (connection,
+                                mhd_ret,
+                                &refresh_melt_transaction,
+                                rmc);
 }
 
 
@@ -754,14 +672,11 @@ free_commit_coins (struct 
TALER_EXCHANGEDB_RefreshCommitCoin **commit_coin,
                    unsigned int kappa,
                    unsigned int num_new_coins)
 {
-  unsigned int i;
-  unsigned int j;
-
-  for (i=0;i<kappa;i++)
+  for (unsigned int i=0;i<kappa;i++)
   {
     if (NULL == commit_coin[i])
       break;
-    for (j=0;j<num_new_coins;j++)
+    for (unsigned int j=0;j<num_new_coins;j++)
       GNUNET_free_non_null (commit_coin[i][j].coin_ev);
     GNUNET_free (commit_coin[i]);
   }
@@ -769,6 +684,33 @@ free_commit_coins (struct 
TALER_EXCHANGEDB_RefreshCommitCoin **commit_coin,
 
 
 /**
+ * Cleanup state kept in the @a rmc.
+ *
+ * @param rmc state to clean up; does not free @a rmc itself
+ */
+static void
+cleanup_rmc (struct RefreshMeltContext *rmc)
+{
+  free_commit_coins (rmc->commit_coin,
+                     TALER_CNC_KAPPA,
+                     rmc->num_newcoins);
+  if (NULL != rmc->coin_melt_details.coin_info.denom_pub.rsa_public_key)
+    GNUNET_CRYPTO_rsa_public_key_free 
(rmc->coin_melt_details.coin_info.denom_pub.rsa_public_key);
+  if (NULL != rmc->coin_melt_details.coin_info.denom_sig.rsa_signature)
+    GNUNET_CRYPTO_rsa_signature_free 
(rmc->coin_melt_details.coin_info.denom_sig.rsa_signature);
+  if (NULL != rmc->denom_pubs)
+  {
+    for (unsigned int j=0;j<rmc->num_newcoins;j++)
+      if (NULL != rmc->denom_pubs[j].rsa_public_key)
+        GNUNET_CRYPTO_rsa_public_key_free (rmc->denom_pubs[j].rsa_public_key);
+    GNUNET_free (rmc->denom_pubs);
+  }
+  if (NULL != rmc->hash_context)
+    GNUNET_CRYPTO_hash_context_abort (rmc->hash_context);
+}
+
+
+/**
  * Handle a "/refresh/melt" request after the first parsing has happened.
  * We now need to validate the coins being melted and the session signature
  * and then hand things of to execute the melt operation.  This function
@@ -790,24 +732,20 @@ handle_refresh_melt_json (struct MHD_Connection 
*connection,
                           const json_t *coin_evs)
 {
   int res;
-  unsigned int i;
-  unsigned int j;
-  struct TALER_DenominationPublicKey *denom_pubs;
-  unsigned int num_newcoins;
-  struct TEH_DB_MeltDetails coin_melt_details;
-  struct GNUNET_HashCode session_hash;
-  struct GNUNET_HashContext *hash_context;
-  struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin[TALER_CNC_KAPPA];
-  struct TALER_TransferPublicKeyP transfer_pub[TALER_CNC_KAPPA];
+  int mhd_ret;
+  struct RefreshMeltContext rmc;
 
+  memset (&rmc,
+         0,
+         sizeof (rmc));
   /* For the signature check, we hash most of the inputs together
      (except for the signatures on the coins). */
-  hash_context = GNUNET_CRYPTO_hash_context_start ();
+  rmc.hash_context = GNUNET_CRYPTO_hash_context_start ();
 
-  for (i = 0; i < TALER_CNC_KAPPA; i++)
+  for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
   {
     struct GNUNET_JSON_Specification trans_spec[] = {
-      GNUNET_JSON_spec_fixed_auto (NULL, &transfer_pub[i]),
+      GNUNET_JSON_spec_fixed_auto (NULL, &rmc.transfer_pub[i]),
       GNUNET_JSON_spec_end ()
     };
 
@@ -818,40 +756,43 @@ handle_refresh_melt_json (struct MHD_Connection 
*connection,
     if (GNUNET_OK != res)
     {
       GNUNET_break_op (0);
-      res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
-      goto cleanup_hc;
+      mhd_ret = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+      cleanup_rmc (&rmc);
+      return mhd_ret;
     }
-    GNUNET_CRYPTO_hash_context_read (hash_context,
-                                     &transfer_pub[i],
+    GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
+                                     &rmc.transfer_pub[i],
                                      sizeof (struct TALER_TransferPublicKeyP));
   }
 
 
-  num_newcoins = json_array_size (new_denoms);
-  denom_pubs = GNUNET_new_array (num_newcoins,
-                                 struct TALER_DenominationPublicKey);
-  for (i=0;i<num_newcoins;i++)
+  rmc.num_newcoins = json_array_size (new_denoms);
+  rmc.denom_pubs = GNUNET_new_array (rmc.num_newcoins,
+                                    struct TALER_DenominationPublicKey);
+  for (unsigned int i=0;i<rmc.num_newcoins;i++)
   {
     char *buf;
     size_t buf_size;
     struct GNUNET_JSON_Specification spec[] = {
       TALER_JSON_spec_denomination_public_key (NULL,
-                                               &denom_pubs[i]),
+                                               &rmc.denom_pubs[i]),
       GNUNET_JSON_spec_end ()
     };
 
     res = TEH_PARSE_json_array (connection,
                                 new_denoms,
                                 spec,
-                                i, -1);
+                                i,
+                               -1);
     if (GNUNET_OK != res)
     {
-      res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-      goto cleanup_denoms;
+      mhd_ret = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+      cleanup_rmc (&rmc);
+      return mhd_ret;
     }
-    buf_size = GNUNET_CRYPTO_rsa_public_key_encode 
(denom_pubs[i].rsa_public_key,
+    buf_size = GNUNET_CRYPTO_rsa_public_key_encode 
(rmc.denom_pubs[i].rsa_public_key,
                                                     &buf);
-    GNUNET_CRYPTO_hash_context_read (hash_context,
+    GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
                                      buf,
                                      buf_size);
     GNUNET_free (buf);
@@ -863,35 +804,33 @@ handle_refresh_melt_json (struct MHD_Connection 
*connection,
 
     res = get_coin_public_info (connection,
                                 melt_coin,
-                                &coin_melt_details);
+                                &rmc.coin_melt_details);
     if (GNUNET_OK != res)
     {
       GNUNET_break_op (0);
-      res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-      goto cleanup_melt_details;
+      mhd_ret = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+      cleanup_rmc (&rmc);
+      return mhd_ret;
     }
     TALER_amount_hton (&melt_amount,
-                       &coin_melt_details.melt_amount_with_fee);
-    GNUNET_CRYPTO_hash_context_read (hash_context,
-                                     &coin_melt_details.coin_info.coin_pub,
+                       &rmc.coin_melt_details.melt_amount_with_fee);
+    GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
+                                     &rmc.coin_melt_details.coin_info.coin_pub,
                                      sizeof (struct 
TALER_CoinSpendPublicKeyP));
-    GNUNET_CRYPTO_hash_context_read (hash_context,
+    GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
                                      &melt_amount,
                                      sizeof (struct TALER_AmountNBO));
   }
 
   /* parse JSON arrays into binary arrays and hash everything
      together for the signature check */
-  memset (commit_coin,
-          0,
-          sizeof (commit_coin));
-  for (i = 0; i < TALER_CNC_KAPPA; i++)
+  for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
   {
-    commit_coin[i] = GNUNET_new_array (num_newcoins,
-                                       struct 
TALER_EXCHANGEDB_RefreshCommitCoin);
-    for (j = 0; j < num_newcoins; j++)
+    rmc.commit_coin[i] = GNUNET_new_array (rmc.num_newcoins,
+                                          struct 
TALER_EXCHANGEDB_RefreshCommitCoin);
+    for (unsigned int j = 0; j < rmc.num_newcoins; j++)
     {
-      struct TALER_EXCHANGEDB_RefreshCommitCoin *rcc = &commit_coin[i][j];
+      struct TALER_EXCHANGEDB_RefreshCommitCoin *rcc = &rmc.commit_coin[i][j];
       struct GNUNET_JSON_Specification coin_spec[] = {
         GNUNET_JSON_spec_varsize (NULL,
                                   (void **) &rcc->coin_ev,
@@ -902,63 +841,52 @@ handle_refresh_melt_json (struct MHD_Connection 
*connection,
       res = TEH_PARSE_json_array (connection,
                                   coin_evs,
                                   coin_spec,
-                                  i, j, -1);
+                                  i,
+                                 j,
+                                 -1);
       if (GNUNET_OK != res)
       {
         GNUNET_break_op (0);
-        res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
-        goto cleanup;
+        mhd_ret = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+        cleanup_rmc (&rmc);
+       return mhd_ret;
       }
 
-      GNUNET_CRYPTO_hash_context_read (hash_context,
+      GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
                                        rcc->coin_ev,
                                        rcc->coin_ev_size);
     }
   }
 
-  GNUNET_CRYPTO_hash_context_finish (hash_context,
-                                     &session_hash);
-  hash_context = NULL;
+  GNUNET_CRYPTO_hash_context_finish (rmc.hash_context,
+                                     &rmc.session_hash);
+  rmc.hash_context = NULL;
   /* verify signature on coins to melt */
   res = verify_coin_public_info (connection,
-                                 &session_hash,
-                                 &coin_melt_details);
+                                 &rmc.session_hash,
+                                 &rmc.coin_melt_details);
   if (GNUNET_OK != res)
   {
     GNUNET_break_op (0);
-    res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-    goto cleanup;
+    mhd_ret = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+    cleanup_rmc (&rmc);
+    return mhd_ret;
   }
 
-  /* execute commit */
-  res = handle_refresh_melt_binary (connection,
-                                    num_newcoins,
-                                    denom_pubs,
-                                    &coin_melt_details,
-                                    &session_hash,
-                                    commit_coin,
-                                    transfer_pub);
- cleanup:
-  free_commit_coins (commit_coin,
-                     TALER_CNC_KAPPA,
-                     num_newcoins);
- cleanup_melt_details:
-  if (NULL != coin_melt_details.coin_info.denom_pub.rsa_public_key)
-    GNUNET_CRYPTO_rsa_public_key_free 
(coin_melt_details.coin_info.denom_pub.rsa_public_key);
-  if (NULL != coin_melt_details.coin_info.denom_sig.rsa_signature)
-    GNUNET_CRYPTO_rsa_signature_free 
(coin_melt_details.coin_info.denom_sig.rsa_signature);
- cleanup_denoms:
-  if (NULL != denom_pubs)
+  /* prepare commit */
+  if (GNUNET_OK !=
+      refresh_melt_prepare (connection,
+                           &mhd_ret,
+                           &rmc))
   {
-    for (j=0;j<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 (denom_pubs);
+    cleanup_rmc (&rmc);
+    return mhd_ret;
   }
- cleanup_hc:
-  if (NULL != hash_context)
-    GNUNET_CRYPTO_hash_context_abort (hash_context);
-  return res;
+  mhd_ret = reply_refresh_melt_success (connection,
+                                       &rmc.session_hash,
+                                       rmc.refresh_session.noreveal_index);
+  cleanup_rmc (&rmc);
+  return mhd_ret;
 }
 
 
@@ -1003,7 +931,8 @@ TEH_REFRESH_handler_refresh_melt (struct 
TEH_RequestHandler *rh,
                              &root);
   if (GNUNET_SYSERR == res)
     return MHD_NO;
-  if ( (GNUNET_NO == res) || (NULL == root) )
+  if ( (GNUNET_NO == res) ||
+       (NULL == root) )
     return MHD_YES;
 
   res = TEH_PARSE_json_data (connection,
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c 
b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index 05422a8..cfb2b68 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -32,95 +32,6 @@
 
 
 /**
- * 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 #TEH_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;                       \
-  enum GNUNET_DB_QueryStatus transaction_commit_result;       \
-transaction_start_label: /* we will use goto for retries */   \
-  if (GNUNET_OK !=                                            \
-      TEH_plugin->start (TEH_plugin->cls,                     \
-                         session))                            \
-  {                                                           \
-    GNUNET_break (0);                                         \
-    return TEH_RESPONSE_reply_internal_db_error (connection, \
-                                                TALER_EC_DB_START_FAILED);     
     \
-  }
-
-/**
- * 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
- * #TEH_RESPONSE_reply_internal_db_error() status code.
- *
- * @param session session handle
- * @param connection connection handle
- */
-#define COMMIT_TRANSACTION(session,connection)                             \
-  transaction_commit_result =                                              \
-    TEH_plugin->commit (TEH_plugin->cls,                                   \
-                        session);                                          \
-  if (GNUNET_DB_STATUS_HARD_ERROR == transaction_commit_result)            \
-  {                                                                        \
-    TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \
-    return TEH_RESPONSE_reply_commit_error (connection, \
-                                           TALER_EC_DB_COMMIT_FAILED_HARD); \
-  }                                                       \
-  if (GNUNET_DB_STATUS_SOFT_ERROR == 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 TEH_RESPONSE_reply_commit_error (connection, \
-                                           
TALER_EC_DB_COMMIT_FAILED_ON_RETRY);                                \
-  }                                                                        \
-} /* end of scope opened by BEGIN_TRANSACTION */
-
-
-/**
- * Code to include to retry a transaction, must only be used in between
- * #START_TRANSACTION and #COMMIT_TRANSACTION.
- *
- * @param session session handle
- * @param connection connection handle
- */
-#define RETRY_TRANSACTION(session,connection)                                  
  \
-  do {                                                                         
  \
-    TEH_plugin->rollback (TEH_plugin->cls,                                     
  \
-                          session);                                            
  \
-    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 TEH_RESPONSE_reply_commit_error (connection,                        
  \
-                                           
TALER_EC_DB_COMMIT_FAILED_ON_RETRY); \
-  } while (0)
-
-
-
-
-
-/**
  * Send a response for "/refresh/reveal".
  *
  * @param connection the connection to send the response to
@@ -133,14 +44,15 @@ reply_refresh_reveal_success (struct MHD_Connection 
*connection,
                              unsigned int num_newcoins,
                              const struct TALER_DenominationSignature *sigs)
 {
-  int newcoin_index;
   json_t *root;
   json_t *obj;
   json_t *list;
   int ret;
 
   list = json_array ();
-  for (newcoin_index = 0; newcoin_index < num_newcoins; newcoin_index++)
+  for (unsigned int newcoin_index = 0;
+       newcoin_index < num_newcoins;
+       newcoin_index++)
   {
     obj = json_object ();
     json_object_set_new (obj,
@@ -182,11 +94,10 @@ reply_refresh_reveal_missmatch (struct MHD_Connection 
*connection,
 {
   json_t *info_new;
   json_t *info_commit_k;
-  unsigned int i;
 
   info_new = json_array ();
   info_commit_k = json_array ();
-  for (i=0;i<session->num_newcoins;i++)
+  for (unsigned int i=0;i<session->num_newcoins;i++)
   {
     const struct TALER_EXCHANGEDB_RefreshCommitCoin *cc;
     json_t *cc_json;
@@ -220,7 +131,6 @@ reply_refresh_reveal_missmatch (struct MHD_Connection 
*connection,
 }
 
 
-
 /**
  * Check if the given @a transfer_privs correspond to an honest
  * commitment for the given session.
@@ -253,14 +163,13 @@ check_commitment (struct MHD_Connection *connection,
                   struct GNUNET_HashContext *hash_context)
 {
   struct TALER_TransferSecretP transfer_secret;
-  unsigned int j;
 
   TALER_link_reveal_transfer_secret (transfer_priv,
                                      &melt->coin.coin_pub,
                                      &transfer_secret);
 
   /* Check that the commitments for all new coins were correct */
-  for (j = 0; j < num_newcoins; j++)
+  for (unsigned int j = 0; j < num_newcoins; j++)
   {
     struct TALER_FreshCoinP fc;
     struct TALER_CoinSpendPublicKeyP coin_pub;
@@ -301,6 +210,58 @@ check_commitment (struct MHD_Connection *connection,
 
 
 /**
+ * State for a /refresh/reveal operation.
+ */
+struct RevealContext
+{
+
+  /**
+   * Hash of the refresh session.
+   */
+  const struct GNUNET_HashCode *session_hash;
+
+  /**
+   * Database session used to execute the transaction.
+   */
+  struct TALER_EXCHANGEDB_Session *session;
+
+  /**
+   * Session state from the database.
+   */
+  struct TALER_EXCHANGEDB_RefreshSession refresh_session;
+
+  /**
+   * Array of denomination public keys used for the refresh.
+   */
+  struct TALER_DenominationPublicKey *denom_pubs;
+
+  /**
+   * Envelopes with the signatures to be returned.
+   */
+  struct TALER_DenominationSignature *ev_sigs;
+
+  /**
+   * Commitment data from the DB giving data about original
+   * commitments, in particular the blinded envelopes (for
+   * index gamma).
+   */
+  struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins;
+
+  /**
+   * Transfer public key associated with the gamma value
+   * selected by the exchange.
+   */
+  struct TALER_TransferPublicKeyP gamma_tp;
+
+  /**
+   * Transfer private keys revealed to us.
+   */
+  struct TALER_TransferPrivateKeyP transfer_privs[TALER_CNC_KAPPA - 1];
+
+};
+
+
+/**
  * Exchange a coin as part of a refresh operation.  Obtains the
  * envelope from the database and performs the signing operation.
  *
@@ -311,19 +272,21 @@ check_commitment (struct MHD_Connection *connection,
  * @param denom_pub denomination key for the coin to create
  * @param commit_coin the coin that was committed
  * @param coin_off number of the coin
- * @return NULL on error, otherwise signature over the coin
+ * @param[out] ev_sig set to signature over the coin upon success
+ * @return database transaction status
  */
-static struct TALER_DenominationSignature
+static enum GNUNET_DB_QueryStatus
 refresh_exchange_coin (struct MHD_Connection *connection,
                        struct TALER_EXCHANGEDB_Session *session,
                        const struct GNUNET_HashCode *session_hash,
                        struct TEH_KS_StateHandle *key_state,
                        const struct TALER_DenominationPublicKey *denom_pub,
                        const struct TALER_EXCHANGEDB_RefreshCommitCoin 
*commit_coin,
-                       unsigned int coin_off)
+                       unsigned int coin_off,
+                      struct TALER_DenominationSignature *ev_sig)
 {
   struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
-  struct TALER_DenominationSignature ev_sig;
+  enum GNUNET_DB_QueryStatus qs;
 
   dki = TEH_KS_denomination_key_lookup (key_state,
                                         denom_pub,
@@ -331,105 +294,91 @@ refresh_exchange_coin (struct MHD_Connection *connection,
   if (NULL == dki)
   {
     GNUNET_break (0);
-    ev_sig.rsa_signature = NULL;
-    return ev_sig;
+    ev_sig->rsa_signature = NULL;
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  if (GNUNET_OK ==
-      TEH_plugin->get_refresh_out (TEH_plugin->cls,
-                                   session,
-                                   session_hash,
-                                   coin_off,
-                                   &ev_sig))
+  qs = TEH_plugin->get_refresh_out (TEH_plugin->cls,
+                                   session,
+                                   session_hash,
+                                   coin_off,
+                                   ev_sig);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Returning cached reply for /refresh/reveal signature\n");
-    return ev_sig;
+    return qs;
   }
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
+    return qs;
 
-  ev_sig.rsa_signature
+  ev_sig->rsa_signature
     = GNUNET_CRYPTO_rsa_sign_blinded (dki->denom_priv.rsa_private_key,
                                       commit_coin->coin_ev,
                                       commit_coin->coin_ev_size);
-  if (NULL == ev_sig.rsa_signature)
+  if (NULL == ev_sig->rsa_signature)
   {
     GNUNET_break (0);
-    return ev_sig;
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  if (GNUNET_SYSERR ==
-      TEH_plugin->insert_refresh_out (TEH_plugin->cls,
-                                      session,
-                                      session_hash,
-                                      coin_off,
-                                      &ev_sig))
+  qs = TEH_plugin->insert_refresh_out (TEH_plugin->cls,
+                                      session,
+                                      session_hash,
+                                      coin_off,
+                                      ev_sig);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
-    GNUNET_break (0);
-    GNUNET_CRYPTO_rsa_signature_free (ev_sig.rsa_signature);
-    ev_sig.rsa_signature = NULL;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    if (NULL != ev_sig->rsa_signature)
+    {
+      GNUNET_CRYPTO_rsa_signature_free (ev_sig->rsa_signature);
+      ev_sig->rsa_signature = NULL;
+    }
   }
-
-  return ev_sig;
+  return qs;
 }
 
 
 /**
- * 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.
+ * Cleanup state of the transaction stored in @a rc.
  *
- * @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[out] ev_sigs where to store generated signatures for the new coins,
- *                     array of length "num_newcoins", memory released by the
- *                     caller
- * @param[out] commit_coins array of length "num_newcoins" to be used for
- *                     information about the new coins from the commitment.
- * @return MHD result code
+ * @param rc context to clean up
  */
-static int
-execute_refresh_reveal_transaction (struct MHD_Connection *connection,
-                                    struct TALER_EXCHANGEDB_Session *session,
-                                    const struct GNUNET_HashCode *session_hash,
-                                    const struct 
TALER_EXCHANGEDB_RefreshSession *refresh_session,
-                                    const struct TALER_DenominationPublicKey 
*denom_pubs,
-                                    struct TALER_DenominationSignature 
*ev_sigs,
-                                    struct TALER_EXCHANGEDB_RefreshCommitCoin 
*commit_coins)
+static void
+cleanup_rc (struct RevealContext *rc)
 {
-  unsigned int j;
-  struct TEH_KS_StateHandle *key_state;
-  int ret;
-
-  START_TRANSACTION (session, connection);
-  key_state = TEH_KS_acquire ();
-  for (j=0;j<refresh_session->num_newcoins;j++)
+  if (NULL != rc->denom_pubs)
   {
-    if (NULL == ev_sigs[j].rsa_signature) /* could be non-NULL during retries 
*/
-      ev_sigs[j] = refresh_exchange_coin (connection,
-                                          session,
-                                          session_hash,
-                                          key_state,
-                                          &denom_pubs[j],
-                                          &commit_coins[j],
-                                          j);
-    if (NULL == ev_sigs[j].rsa_signature)
-    {
-      TEH_plugin->rollback (TEH_plugin->cls,
-                            session);
-      ret = TEH_RESPONSE_reply_internal_db_error (connection,
-                                                 
TALER_EC_REFRESH_REVEAL_SIGNING_ERROR);
-      goto cleanup;
-    }
+    for (unsigned int i=0;i<rc->refresh_session.num_newcoins;i++)
+      if (NULL != rc->denom_pubs[i].rsa_public_key)
+       GNUNET_CRYPTO_rsa_public_key_free (rc->denom_pubs[i].rsa_public_key);
+    GNUNET_free (rc->denom_pubs);
+    rc->denom_pubs = NULL;
+  }
+  if (NULL != rc->commit_coins)
+  {
+    for (unsigned int j=0;j<rc->refresh_session.num_newcoins;j++)
+      GNUNET_free_non_null (rc->commit_coins[j].coin_ev);
+    GNUNET_free (rc->commit_coins);
+    rc->commit_coins = NULL;
+  }
+  if (NULL != rc->ev_sigs)
+  {
+    for (unsigned int j=0;j<rc->refresh_session.num_newcoins;j++)
+      if (NULL != rc->ev_sigs[j].rsa_signature)
+       GNUNET_CRYPTO_rsa_signature_free (rc->ev_sigs[j].rsa_signature);
+    GNUNET_free (rc->ev_sigs);
+    rc->ev_sigs = NULL;
+  }
+  if (NULL != rc->refresh_session.melt.coin.denom_sig.rsa_signature)
+  {
+    GNUNET_CRYPTO_rsa_signature_free 
(rc->refresh_session.melt.coin.denom_sig.rsa_signature);
+    rc->refresh_session.melt.coin.denom_sig.rsa_signature = NULL;
+  }
+  if (NULL != rc->refresh_session.melt.coin.denom_pub.rsa_public_key)
+  {
+    GNUNET_CRYPTO_rsa_public_key_free 
(rc->refresh_session.melt.coin.denom_pub.rsa_public_key);
+    rc->refresh_session.melt.coin.denom_pub.rsa_public_key = NULL;
   }
-  COMMIT_TRANSACTION (session, connection);
-  ret = reply_refresh_reveal_success (connection,
-                                     refresh_session->num_newcoins,
-                                     ev_sigs);
- cleanup:
-  TEH_KS_release (key_state);
-  return ret;
 }
 
 
@@ -440,94 +389,98 @@ execute_refresh_reveal_transaction (struct MHD_Connection 
*connection,
  * and if so, return the signed coins for corresponding to the set of
  * coins that was not chosen.
  *
- * @param connection the MHD connection to handle
- * @param session_hash hash identifying the refresh session
- * @param transfer_privs array with the revealed transfer keys,
- *                      length must be #TALER_CNC_KAPPA - 1
- * @return MHD result code
+ * IF it returns a non-error code, the transaction logic MUST
+ * NOT queue a MHD response.  IF it returns an hard error, the
+ * transaction logic MUST queue a MHD response and set @a mhd_ret.  IF
+ * it returns the soft error code, the function MAY be called again to
+ * retry and MUST not queue a MHD response.
+ *
+ * @param cls closure of type `struct RevealContext`
+ * @param connection MHD request which triggered the transaction
+ * @param session database session to use
+ * @param[out] mhd_ret set to MHD response status for @a connection,
+ *             if transaction failed (!)
+ * @return transaction status
  */
-static int
-execute_refresh_reveal (struct MHD_Connection *connection,
-                       const struct GNUNET_HashCode *session_hash,
-                       struct TALER_TransferPrivateKeyP *transfer_privs)
+static enum GNUNET_DB_QueryStatus
+refresh_reveal_transaction (void *cls,
+                           struct MHD_Connection *connection,
+                           struct TALER_EXCHANGEDB_Session *session,
+                           int *mhd_ret)
 {
-  int res;
-  struct TALER_EXCHANGEDB_Session *session;
-  struct TALER_EXCHANGEDB_RefreshSession refresh_session;
-  struct TALER_DenominationPublicKey *denom_pubs;
-  struct TALER_DenominationSignature *ev_sigs;
-  struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins;
-  unsigned int i;
-  unsigned int j;
+  struct RevealContext *rc = cls;
   unsigned int off;
   struct GNUNET_HashContext *hash_context;
   struct GNUNET_HashCode sh_check;
-  int ret;
-  struct TALER_TransferPublicKeyP gamma_tp;
-
-  if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
+  enum GNUNET_DB_QueryStatus qs;
+
+  rc->session = session;
+  qs = TEH_plugin->get_refresh_session (TEH_plugin->cls,
+                                       session,
+                                       rc->session_hash,
+                                       &rc->refresh_session);
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+  {
+    *mhd_ret = TEH_RESPONSE_reply_arg_invalid (connection,
+                                              
TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN,
+                                              "session_hash");
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    return qs;
+  if ( (GNUNET_DB_STATUS_HARD_ERROR == qs) ||
+       (rc->refresh_session.noreveal_index >= TALER_CNC_KAPPA) )
   {
     GNUNET_break (0);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                TALER_EC_DB_SETUP_FAILED);
+    cleanup_rc (rc);
+    *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                    
TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
-
-  res = TEH_plugin->get_refresh_session (TEH_plugin->cls,
-                                         session,
-                                         session_hash,
-                                         &refresh_session);
-  if (GNUNET_NO == res)
-    return TEH_RESPONSE_reply_arg_invalid (connection,
-                                          
TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN,
-                                           "session_hash");
-  if ( (GNUNET_SYSERR == res) ||
-       (refresh_session.noreveal_index >= TALER_CNC_KAPPA) )
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                
TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR);
-  denom_pubs = GNUNET_new_array (refresh_session.num_newcoins,
-                                 struct TALER_DenominationPublicKey);
-  if (GNUNET_OK !=
-      TEH_plugin->get_refresh_order (TEH_plugin->cls,
-                                     session,
-                                     session_hash,
-                                     refresh_session.num_newcoins,
-                                     denom_pubs))
+  rc->denom_pubs = GNUNET_new_array (rc->refresh_session.num_newcoins,
+                                    struct TALER_DenominationPublicKey);
+  qs = TEH_plugin->get_refresh_order (TEH_plugin->cls,
+                                     session,
+                                     rc->session_hash,
+                                     rc->refresh_session.num_newcoins,
+                                     rc->denom_pubs);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
+    cleanup_rc (rc);
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+      return qs;
     GNUNET_break (0);
-    GNUNET_free (denom_pubs);
-    GNUNET_CRYPTO_rsa_signature_free 
(refresh_session.melt.coin.denom_sig.rsa_signature);
-    GNUNET_CRYPTO_rsa_public_key_free 
(refresh_session.melt.coin.denom_pub.rsa_public_key);
-    return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection,
-                                                            
TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR))
-        ? GNUNET_NO : GNUNET_SYSERR;
+    *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                    
TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
   hash_context = GNUNET_CRYPTO_hash_context_start ();
   /* first, iterate over transfer public keys for hash_context */
   off = 0;
-  for (i=0;i<TALER_CNC_KAPPA;i++)
+  for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
   {
-    if (i == refresh_session.noreveal_index)
+    if (i == rc->refresh_session.noreveal_index)
     {
       off = 1;
       /* obtain gamma_tp from db */
-      if (GNUNET_OK !=
-          TEH_plugin->get_refresh_transfer_public_key (TEH_plugin->cls,
-                                                       session,
-                                                       session_hash,
-                                                       &gamma_tp))
+      qs = TEH_plugin->get_refresh_transfer_public_key (TEH_plugin->cls,
+                                                       session,
+                                                       rc->session_hash,
+                                                       &rc->gamma_tp);
+      if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
       {
-        GNUNET_break (0);
-        GNUNET_free (denom_pubs);
-        GNUNET_CRYPTO_rsa_signature_free 
(refresh_session.melt.coin.denom_sig.rsa_signature);
-        GNUNET_CRYPTO_rsa_public_key_free 
(refresh_session.melt.coin.denom_pub.rsa_public_key);
         GNUNET_CRYPTO_hash_context_abort (hash_context);
-        return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection,
-                                                                
TALER_EC_REFRESH_REVEAL_DB_FETCH_TRANSFER_ERROR))
-          ? GNUNET_NO : GNUNET_SYSERR;
+       cleanup_rc (rc);
+       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+         return qs;
+        GNUNET_break (0);
+        *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                        
TALER_EC_REFRESH_REVEAL_DB_FETCH_TRANSFER_ERROR);
+       return GNUNET_DB_STATUS_HARD_ERROR;
       }
       GNUNET_CRYPTO_hash_context_read (hash_context,
-                                       &gamma_tp,
+                                       &rc->gamma_tp,
                                        sizeof (struct 
TALER_TransferPublicKeyP));
     }
     else
@@ -535,7 +488,7 @@ execute_refresh_reveal (struct MHD_Connection *connection,
       /* compute tp from private key */
       struct TALER_TransferPublicKeyP tp;
 
-      GNUNET_CRYPTO_ecdhe_key_get_public (&transfer_privs[i - off].ecdhe_priv,
+      GNUNET_CRYPTO_ecdhe_key_get_public (&rc->transfer_privs[i - 
off].ecdhe_priv,
                                           &tp.ecdhe_pub);
       GNUNET_CRYPTO_hash_context_read (hash_context,
                                        &tp,
@@ -545,38 +498,17 @@ execute_refresh_reveal (struct MHD_Connection *connection,
 
   /* next, add all of the hashes from the denomination keys to the
      hash_context */
+  for (unsigned int i=0;i<rc->refresh_session.num_newcoins;i++)
   {
-    struct TALER_DenominationPublicKey 
denom_pubs[refresh_session.num_newcoins];
-
-    if (GNUNET_OK !=
-        TEH_plugin->get_refresh_order (TEH_plugin->cls,
-                                       session,
-                                       session_hash,
-                                       refresh_session.num_newcoins,
-                                       denom_pubs))
-    {
-      GNUNET_break (0);
-      GNUNET_free (denom_pubs);
-      GNUNET_CRYPTO_rsa_signature_free 
(refresh_session.melt.coin.denom_sig.rsa_signature);
-      GNUNET_CRYPTO_rsa_public_key_free 
(refresh_session.melt.coin.denom_pub.rsa_public_key);
-      GNUNET_CRYPTO_hash_context_abort (hash_context);
-      return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection,
-                                                              
TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR))
-        ? GNUNET_NO : GNUNET_SYSERR;
-    }
-    for (i=0;i<refresh_session.num_newcoins;i++)
-    {
-      char *buf;
-      size_t buf_size;
+    char *buf;
+    size_t buf_size;
 
-      buf_size = GNUNET_CRYPTO_rsa_public_key_encode 
(denom_pubs[i].rsa_public_key,
-                                                      &buf);
-      GNUNET_CRYPTO_hash_context_read (hash_context,
-                                       buf,
-                                       buf_size);
-      GNUNET_free (buf);
-      GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[i].rsa_public_key);
-    }
+    buf_size = GNUNET_CRYPTO_rsa_public_key_encode 
(rc->denom_pubs[i].rsa_public_key,
+                                                   &buf);
+    GNUNET_CRYPTO_hash_context_read (hash_context,
+                                    buf,
+                                    buf_size);
+    GNUNET_free (buf);
   }
 
   /* next, add public key of coin and amount being refreshed */
@@ -584,71 +516,67 @@ execute_refresh_reveal (struct MHD_Connection *connection,
     struct TALER_AmountNBO melt_amountn;
 
     GNUNET_CRYPTO_hash_context_read (hash_context,
-                                     &refresh_session.melt.coin.coin_pub,
+                                     &rc->refresh_session.melt.coin.coin_pub,
                                      sizeof (struct 
TALER_CoinSpendPublicKeyP));
     TALER_amount_hton (&melt_amountn,
-                       &refresh_session.melt.amount_with_fee);
+                       &rc->refresh_session.melt.amount_with_fee);
     GNUNET_CRYPTO_hash_context_read (hash_context,
                                      &melt_amountn,
                                      sizeof (struct TALER_AmountNBO));
   }
 
-  commit_coins = GNUNET_new_array (refresh_session.num_newcoins,
-                                   struct TALER_EXCHANGEDB_RefreshCommitCoin);
+  rc->commit_coins = GNUNET_new_array (rc->refresh_session.num_newcoins,
+                                      struct 
TALER_EXCHANGEDB_RefreshCommitCoin);
   off = 0;
-  for (i=0;i<TALER_CNC_KAPPA;i++)
+  for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
   {
-    if (i == refresh_session.noreveal_index)
+    int res;
+    
+    if (i == rc->refresh_session.noreveal_index)
     {
       off = 1;
       /* obtain commit_coins for the selected gamma value from DB */
-      if (GNUNET_OK !=
-          TEH_plugin->get_refresh_commit_coins (TEH_plugin->cls,
-                                                session,
-                                                session_hash,
-                                                refresh_session.num_newcoins,
-                                                commit_coins))
-      {
-        GNUNET_break (0);
-        GNUNET_free (denom_pubs);
-        GNUNET_CRYPTO_rsa_signature_free 
(refresh_session.melt.coin.denom_sig.rsa_signature);
-        GNUNET_CRYPTO_rsa_public_key_free 
(refresh_session.melt.coin.denom_pub.rsa_public_key);
+      qs = TEH_plugin->get_refresh_commit_coins (TEH_plugin->cls,
+                                                session,
+                                                rc->session_hash,
+                                                
rc->refresh_session.num_newcoins,
+                                                rc->commit_coins);
+      if (0 >= qs)
+      {        
+       cleanup_rc (rc);
         GNUNET_CRYPTO_hash_context_abort (hash_context);
-        return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                    
TALER_EC_REFRESH_REVEAL_DB_FETCH_COMMIT_ERROR);
+       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+         return qs;
+        GNUNET_break (0);
+        *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                        
TALER_EC_REFRESH_REVEAL_DB_FETCH_COMMIT_ERROR);
+       return GNUNET_DB_STATUS_HARD_ERROR;
       }
       /* add envelopes to hash_context */
-      for (j=0;j<refresh_session.num_newcoins;j++)
+      for (unsigned int j=0;j<rc->refresh_session.num_newcoins;j++)
       {
         GNUNET_CRYPTO_hash_context_read (hash_context,
-                                         commit_coins[j].coin_ev,
-                                         commit_coins[j].coin_ev_size);
+                                         rc->commit_coins[j].coin_ev,
+                                         rc->commit_coins[j].coin_ev_size);
       }
       continue;
     }
     if (GNUNET_OK !=
         (res = check_commitment (connection,
                                  session,
-                                 session_hash,
+                                 rc->session_hash,
                                  i,
-                                 &transfer_privs[i - off],
-                                 &refresh_session.melt,
-                                 refresh_session.num_newcoins,
-                                 denom_pubs,
+                                 &rc->transfer_privs[i - off],
+                                 &rc->refresh_session.melt,
+                                 rc->refresh_session.num_newcoins,
+                                 rc->denom_pubs,
                                  hash_context)))
     {
       GNUNET_break_op (0);
-      for (j=0;j<refresh_session.num_newcoins;j++)
-      {
-        GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
-        GNUNET_free (commit_coins[j].coin_ev);
-      }
-      GNUNET_free (commit_coins);
-      GNUNET_free (denom_pubs);
-      GNUNET_CRYPTO_rsa_signature_free 
(refresh_session.melt.coin.denom_sig.rsa_signature);
-      GNUNET_CRYPTO_rsa_public_key_free 
(refresh_session.melt.coin.denom_pub.rsa_public_key);
+      cleanup_rc (rc);
       GNUNET_CRYPTO_hash_context_abort (hash_context);
-      return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+      *mhd_ret = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
   }
 
@@ -656,56 +584,53 @@ execute_refresh_reveal (struct MHD_Connection *connection,
   GNUNET_CRYPTO_hash_context_finish (hash_context,
                                      &sh_check);
   if (0 != memcmp (&sh_check,
-                   session_hash,
+                   rc->session_hash,
                    sizeof (struct GNUNET_HashCode)))
   {
     GNUNET_break_op (0);
-    ret = reply_refresh_reveal_missmatch (connection,
-                                         &refresh_session,
-                                         commit_coins,
-                                         denom_pubs,
-                                         &gamma_tp);
-    for (j=0;j<refresh_session.num_newcoins;j++)
+    *mhd_ret = reply_refresh_reveal_missmatch (connection,
+                                              &rc->refresh_session,
+                                              rc->commit_coins,
+                                              rc->denom_pubs,
+                                              &rc->gamma_tp);
+    cleanup_rc (rc);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  
+  /* Client request OK, sign coins */
+  rc->ev_sigs = GNUNET_new_array (rc->refresh_session.num_newcoins,
+                                 struct TALER_DenominationSignature);
+  {
+    struct TEH_KS_StateHandle *key_state;
+
+    key_state = TEH_KS_acquire ();
+    for (unsigned int j=0;j<rc->refresh_session.num_newcoins;j++)
     {
-      GNUNET_free (commit_coins[j].coin_ev);
-      GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
+      qs = refresh_exchange_coin (connection,
+                                 session,
+                                 rc->session_hash,
+                                 key_state,
+                                 &rc->denom_pubs[j],
+                                 &rc->commit_coins[j],
+                                 j,
+                                 &rc->ev_sigs[j]);
+      if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) ||
+          (NULL == rc->ev_sigs[j].rsa_signature) )
+      {
+       *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                        
TALER_EC_REFRESH_REVEAL_SIGNING_ERROR);
+       qs = GNUNET_DB_STATUS_HARD_ERROR;
+       break;
+      }
     }
-    GNUNET_free (commit_coins);
-    GNUNET_free (denom_pubs);
-    GNUNET_CRYPTO_rsa_signature_free 
(refresh_session.melt.coin.denom_sig.rsa_signature);
-    GNUNET_CRYPTO_rsa_public_key_free 
(refresh_session.melt.coin.denom_pub.rsa_public_key);
-
-    return ret;
+    TEH_KS_release (key_state);
   }
-
-  /* Client request OK, start transaction */
-  ev_sigs = GNUNET_new_array (refresh_session.num_newcoins,
-                              struct TALER_DenominationSignature);
-
-  /* FIXME: might need to store revealed transfer private keys for
-     the auditor for later; should pass them as arguments here! #4792*/
-  res = execute_refresh_reveal_transaction (connection,
-                                            session,
-                                            session_hash,
-                                            &refresh_session,
-                                            denom_pubs,
-                                            ev_sigs,
-                                            commit_coins);
-  for (i=0;i<refresh_session.num_newcoins;i++)
+  if (0 >= qs)
   {
-    if (NULL != ev_sigs[i].rsa_signature)
-      GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i].rsa_signature);
-    GNUNET_free (commit_coins[i].coin_ev);
+    cleanup_rc (rc);
+    return qs;
   }
-  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_CRYPTO_rsa_signature_free 
(refresh_session.melt.coin.denom_sig.rsa_signature);
-  GNUNET_CRYPTO_rsa_public_key_free 
(refresh_session.melt.coin.denom_pub.rsa_public_key);
-  GNUNET_free (ev_sigs);
-  GNUNET_free (denom_pubs);
-  GNUNET_free (commit_coins);
-  return res;
+  return qs;
 }
 
 
@@ -726,37 +651,47 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
                             const struct GNUNET_HashCode *session_hash,
                             const json_t *tp_json)
 {
-  struct TALER_TransferPrivateKeyP transfer_privs[TALER_CNC_KAPPA - 1];
-  unsigned int i;
-  int res;
+  struct RevealContext rc;
+  int mhd_ret;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "reveal request for session %s\n",
               GNUNET_h2s (session_hash));
-
-  res = GNUNET_OK;
-  for (i = 0; i < TALER_CNC_KAPPA - 1; i++)
+  memset (&rc,
+         0,
+         sizeof (rc));
+  rc.session_hash = session_hash;
+  for (unsigned int i = 0; i < TALER_CNC_KAPPA - 1; i++)
   {
     struct GNUNET_JSON_Specification tp_spec[] = {
-      GNUNET_JSON_spec_fixed_auto (NULL, &transfer_privs[i]),
+      GNUNET_JSON_spec_fixed_auto (NULL, &rc.transfer_privs[i]),
       GNUNET_JSON_spec_end ()
     };
+    int res;
 
-    if (GNUNET_OK != res)
-      break;
     res = TEH_PARSE_json_array (connection,
                                 tp_json,
                                 tp_spec,
-                                i, -1);
+                                i,
+                               -1);
     GNUNET_break_op (GNUNET_OK == res);
+    if (GNUNET_OK != res)
+      return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
   }
-  if (GNUNET_OK != res)
-    res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
-  else
-    res = execute_refresh_reveal (connection,
-                                 session_hash,
-                                 transfer_privs);
-  return res;
+  if (GNUNET_OK !=
+      TEH_DB_run_transaction (connection,
+                             &mhd_ret,
+                             &refresh_reveal_transaction,
+                             &rc))
+  {
+    cleanup_rc (&rc);
+    return mhd_ret;
+  }
+  mhd_ret = reply_refresh_reveal_success (connection,
+                                         rc.refresh_session.num_newcoins,
+                                         rc.ev_sigs);
+  cleanup_rc (&rc);
+  return mhd_ret;
 }
 
 
@@ -800,7 +735,8 @@ TEH_REFRESH_handler_refresh_reveal (struct 
TEH_RequestHandler *rh,
                              &root);
   if (GNUNET_SYSERR == res)
     return MHD_NO;
-  if ( (GNUNET_NO == res) || (NULL == root) )
+  if ( (GNUNET_NO == res) ||
+       (NULL == root) )
     return MHD_YES;
 
   res = TEH_PARSE_json_data (connection,
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index b11eec1..592751f 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3099,6 +3099,7 @@ postgres_iterate_matching_deposits (void *cls,
  *           if upon succesfullying retrieving the record data info @a
  *           coin_info
  */
+// FIXME: #5010
 static int
 get_known_coin (void *cls,
                 struct TALER_EXCHANGEDB_Session *session,
@@ -3284,88 +3285,55 @@ postgres_insert_refund (void *cls,
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @param session database handle to use
  * @param session_hash hash over the melt to use to locate the session
- * @param[out] refresh_session where to store the result, can be NULL
- *             to just check if the session exists
- * @return #GNUNET_YES on success,
- *         #GNUNET_NO if not found,
- *         #GNUNET_SYSERR on DB failure
+ * @param[out] refresh_session where to store the result
+ * @return transaction status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_refresh_session (void *cls,
                               struct TALER_EXCHANGEDB_Session *session,
                               const struct GNUNET_HashCode *session_hash,
                               struct TALER_EXCHANGEDB_RefreshSession 
*refresh_session)
 {
-  PGresult *result;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (session_hash),
     GNUNET_PQ_query_param_end
   };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint16 ("num_newcoins",
+                                 &refresh_session->num_newcoins),
+    GNUNET_PQ_result_spec_uint16 ("noreveal_index",
+                                 &refresh_session->noreveal_index),
+    GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+                                         &refresh_session->melt.coin.coin_pub),
+    GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+                                         &refresh_session->melt.coin_sig),
+    TALER_PQ_result_spec_amount ("amount_with_fee",
+                                &refresh_session->melt.amount_with_fee),
+    TALER_PQ_result_spec_amount ("fee_refresh",
+                                &refresh_session->melt.melt_fee),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "get_refresh_session",
-                                    params);
-  if (PGRES_TUPLES_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (0 == PQntuples (result))
-  {
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == PQntuples (result));
-  if (NULL == refresh_session)
-  {
-    /* We're done if the caller is only interested in whether the
-     * session exists or not */
-    PQclear (result);
-    return GNUNET_YES;
-  }
   memset (refresh_session,
           0,
           sizeof (struct TALER_EXCHANGEDB_RefreshSession));
-  {
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint16 ("num_newcoins",
-                                    &refresh_session->num_newcoins),
-      GNUNET_PQ_result_spec_uint16 ("noreveal_index",
-                                    &refresh_session->noreveal_index),
-      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
-                                            
&refresh_session->melt.coin.coin_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
-                                            &refresh_session->melt.coin_sig),
-      TALER_PQ_result_spec_amount ("amount_with_fee",
-                                   &refresh_session->melt.amount_with_fee),
-      TALER_PQ_result_spec_amount ("fee_refresh",
-                                   &refresh_session->melt.melt_fee),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  0))
-    {
-      GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
-    }
-  }
-  PQclear (result);
-  if (GNUNET_OK !=
-      get_known_coin (cls,
-                      session,
-                      &refresh_session->melt.coin.coin_pub,
-                      &refresh_session->melt.coin))
+  qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                "get_refresh_session",
+                                                params,
+                                                rs);
+  if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
+       (GNUNET_OK !=
+       get_known_coin (cls,
+                       session,
+                       &refresh_session->melt.coin.coin_pub,
+                       &refresh_session->melt.coin)) )
   {
     GNUNET_break (0);
-    return GNUNET_SYSERR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
   refresh_session->melt.session_hash = *session_hash;
-  return GNUNET_YES;
+  return qs;
 }
 
 
@@ -3501,69 +3469,49 @@ free_dpk_result (struct TALER_DenominationPublicKey 
*denom_pubs,
  * @param session_hash hash to identify refresh session
  * @param num_newcoins size of the array of the @a denom_pubs array
  * @param denom_pubs where to store the deomination keys
- * @return #GNUNET_OK on success
- *         #GNUNET_SYSERR on internal error
+ * @return transaction status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_refresh_order (void *cls,
                             struct TALER_EXCHANGEDB_Session *session,
                             const struct GNUNET_HashCode *session_hash,
                             uint16_t num_newcoins,
                             struct TALER_DenominationPublicKey *denom_pubs)
-{
-  unsigned int i;
-
-  for (i=0;i<(unsigned int) num_newcoins;i++)
+{ 
+  for (unsigned i=0;i<(unsigned int) num_newcoins;i++)
   {
     uint16_t newcoin_off = (uint16_t) i;
-    PGresult *result;
-
-    {
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_auto_from_type (session_hash),
-        GNUNET_PQ_query_param_uint16 (&newcoin_off),
-        GNUNET_PQ_query_param_end
-      };
-
-      result = GNUNET_PQ_exec_prepared (session->conn,
-                                       "get_refresh_order",
-                                       params);
-    }
-    if (PGRES_TUPLES_OK != PQresultStatus (result))
-    {
-      BREAK_DB_ERR (result, session->conn);
-      PQclear (result);
-      free_dpk_result (denom_pubs, i);
-      return GNUNET_SYSERR;
-    }
-    if (0 == PQntuples (result))
+    enum GNUNET_DB_QueryStatus qs;
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (session_hash),
+      GNUNET_PQ_query_param_uint16 (&newcoin_off),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
+                                           &denom_pubs[i].rsa_public_key),
+      GNUNET_PQ_result_spec_end
+    };
+    
+    qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "get_refresh_order",
+                                                  params,
+                                                  rs);
+    switch (qs)
     {
-      PQclear (result);
-      /* FIXME: may want to distinguish between different error cases! */
+    case GNUNET_DB_STATUS_HARD_ERROR:
+    case GNUNET_DB_STATUS_SOFT_ERROR:
+    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
       free_dpk_result (denom_pubs, i);
-      return GNUNET_SYSERR;
-    }
-    GNUNET_assert (1 == PQntuples (result));
-    {
-      struct GNUNET_PQ_ResultSpec rs[] = {
-        GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                             &denom_pubs[i].rsa_public_key),
-        GNUNET_PQ_result_spec_end
-      };
-      if (GNUNET_OK !=
-          GNUNET_PQ_extract_result (result,
-                                    rs,
-                                    0))
-      {
-        PQclear (result);
-        GNUNET_break (0);
-        free_dpk_result (denom_pubs, i);
-        return GNUNET_SYSERR;
-      }
-      PQclear (result);
+      return qs;
+    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+      break;
+    default:
+      GNUNET_break (0);
+      break;
     }
   }
-  return GNUNET_OK;
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -3639,11 +3587,9 @@ postgres_free_refresh_commit_coins (void *cls,
  * @param session_hash hash to identify refresh session
  * @param num_newcoins size of the @a commit_coins array
  * @param[out] commit_coins array of coin commitments to return
- * @return #GNUNET_OK on success
- *         #GNUNET_NO if not found
- *         #GNUNET_SYSERR on error
+ * @return transaction status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_refresh_commit_coins (void *cls,
                                    struct TALER_EXCHANGEDB_Session *session,
                                    const struct GNUNET_HashCode *session_hash,
@@ -3660,53 +3606,29 @@ postgres_get_refresh_commit_coins (void *cls,
     };
     void *c_buf;
     size_t c_buf_size;
-    PGresult *result;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_variable_size ("coin_ev",
+                                          &c_buf,
+                                          &c_buf_size),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_DB_QueryStatus qs;
 
-    result = GNUNET_PQ_exec_prepared (session->conn,
-                                     "get_refresh_commit_coin",
-                                     params);
-    if (PGRES_TUPLES_OK != PQresultStatus (result))
-    {
-      BREAK_DB_ERR (result, session->conn);
-      PQclear (result);
-      postgres_free_refresh_commit_coins (cls,
-                                          i,
-                                          commit_coins);
-      return GNUNET_SYSERR;
-    }
-    if (0 == PQntuples (result))
+    qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "get_refresh_commit_coin",
+                                                  params,
+                                                  rs);
+    if (0 >= qs)
     {
-      PQclear (result);
       postgres_free_refresh_commit_coins (cls,
                                           i,
                                           commit_coins);
-      return GNUNET_NO;
-    }
-    {
-      struct GNUNET_PQ_ResultSpec rs[] = {
-        GNUNET_PQ_result_spec_variable_size ("coin_ev",
-                                            &c_buf,
-                                            &c_buf_size),
-        GNUNET_PQ_result_spec_end
-      };
-
-      if (GNUNET_YES !=
-          GNUNET_PQ_extract_result (result,
-                                    rs,
-                                    0))
-      {
-        PQclear (result);
-        postgres_free_refresh_commit_coins (cls,
-                                            i,
-                                            commit_coins);
-        return GNUNET_SYSERR;
-      }
+      return qs;
     }
-    PQclear (result);
     commit_coins[i].coin_ev = c_buf;
     commit_coins[i].coin_ev_size = c_buf_size;
   }
-  return GNUNET_YES;
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -3748,11 +3670,9 @@ postgres_insert_refresh_transfer_public_key (void *cls,
  * @param session database connection to use
  * @param session_hash hash to identify refresh session
  * @param[out] tp information to return
- * @return #GNUNET_SYSERR on internal error,
- *         #GNUNET_NO if commitment was not found
- *         #GNUNET_OK on success
+ * @return transaction status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_refresh_transfer_public_key (void *cls,
                                           struct TALER_EXCHANGEDB_Session 
*session,
                                           const struct GNUNET_HashCode 
*session_hash,
@@ -3762,40 +3682,16 @@ postgres_get_refresh_transfer_public_key (void *cls,
     GNUNET_PQ_query_param_auto_from_type (session_hash),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "get_refresh_transfer_public_key",
-                                    params);
-  if (PGRES_TUPLES_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (0 == PQntuples (result))
-  {
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  {
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
-                                            tp),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_YES !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  0))
-    {
-      PQclear (result);
-      return GNUNET_SYSERR;
-    }
-  }
-  PQclear (result);
-  return GNUNET_OK;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
+                                         tp),
+    GNUNET_PQ_result_spec_end
+  };
+  
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  
"get_refresh_transfer_public_key",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -3809,17 +3705,15 @@ postgres_get_refresh_transfer_public_key (void *cls,
  * @param session_hash hash to identify refresh session
  * @param newcoin_index coin index
  * @param ev_sig coin signature
- * @return #GNUNET_OK on success, #GNUNET_NO if we have no such result
- *         #GNUNET_SYSERR on error
+ * @return transaction result status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_refresh_out (void *cls,
                           struct TALER_EXCHANGEDB_Session *session,
                           const struct GNUNET_HashCode *session_hash,
                           uint16_t newcoin_index,
                           struct TALER_DenominationSignature *ev_sig)
 {
-  PGresult *result;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (session_hash),
     GNUNET_PQ_query_param_uint16 (&newcoin_index),
@@ -3831,31 +3725,10 @@ postgres_get_refresh_out (void *cls,
     GNUNET_PQ_result_spec_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "get_refresh_out",
-                                    params);
-  if (PGRES_TUPLES_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (1 != PQntuples (result))
-  {
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result,
-                                rs,
-                                0))
-  {
-    PQclear (result);
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "get_refresh_out",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -3870,11 +3743,9 @@ postgres_get_refresh_out (void *cls,
  * @param session_hash hash to identify refresh session
  * @param newcoin_index coin index
  * @param ev_sig coin signature
- * @return #GNUNET_OK on success
- *         #GNUNET_NO on transient error
- *         #GNUNET_SYSERR on error
+ * @return transaction result status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_refresh_out (void *cls,
                              struct TALER_EXCHANGEDB_Session *session,
                              const struct GNUNET_HashCode *session_hash,
@@ -3888,9 +3759,9 @@ postgres_insert_refresh_out (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  return execute_prepared_non_select (session,
-                                      "insert_refresh_out",
-                                      params);
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "insert_refresh_out",
+                                            params);
 }
 
 
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index df730a0..673d514 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -357,7 +357,7 @@ test_refresh_commit_coins (struct TALER_EXCHANGEDB_Session 
*session,
                                                commit_coins));
   ret_commit_coins = GNUNET_new_array (MELT_NEW_COINS,
                                        struct 
TALER_EXCHANGEDB_RefreshCommitCoin);
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_refresh_commit_coins (plugin->cls,
                                             session,
                                             session_hash,
@@ -410,7 +410,7 @@ test_refresh_commit_links (struct TALER_EXCHANGEDB_Session 
*session,
   unsigned int i;
 
   ret = GNUNET_SYSERR;
-  FAILIF (GNUNET_NO !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->get_refresh_transfer_public_key (plugin->cls,
                                                    session,
                                                    session_hash,
@@ -422,7 +422,7 @@ test_refresh_commit_links (struct TALER_EXCHANGEDB_Session 
*session,
                                                       session,
                                                       session_hash,
                                                       
&rctp[MELT_NOREVEAL_INDEX]));
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_refresh_transfer_public_key (plugin->cls,
                                                    session,
                                                    session_hash,
@@ -572,21 +572,24 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
     meltp->melt_fee = fee_refresh;
   }
 
-  FAILIF (GNUNET_OK != plugin->create_refresh_session (plugin->cls,
-                                                       session,
-                                                       &session_hash,
-                                                       &refresh_session));
-  FAILIF (GNUNET_OK != plugin->get_refresh_session (plugin->cls,
-                                                    session,
-                                                    &session_hash,
-                                                    &ret_refresh_session));
+  FAILIF (GNUNET_OK !=
+         plugin->create_refresh_session (plugin->cls,
+                                         session,
+                                         &session_hash,
+                                         &refresh_session));
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+         plugin->get_refresh_session (plugin->cls,
+                                      session,
+                                      &session_hash,
+                                      &ret_refresh_session));
 
   auditor_row_cnt = 0;
-  FAILIF (GNUNET_OK != plugin->select_refreshs_above_serial_id (plugin->cls,
-                                                                session,
-                                                               0,
-                                                               
&audit_refresh_session_cb,
-                                                               NULL));
+  FAILIF (GNUNET_OK !=
+         plugin->select_refreshs_above_serial_id (plugin->cls,
+                                                  session,
+                                                  0,
+                                                  &audit_refresh_session_cb,
+                                                  NULL));
   FAILIF (1 != auditor_row_cnt);
   FAILIF (ret_refresh_session.num_newcoins != refresh_session.num_newcoins);
   FAILIF (ret_refresh_session.noreveal_index != 
refresh_session.noreveal_index);
@@ -633,7 +636,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
                                          &fee_refund);
     new_denom_pubs[cnt] = new_dkp[cnt]->pub;
   }
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_refresh_order (plugin->cls,
                                         session,
                                         &session_hash,
@@ -641,7 +644,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
                                         new_denom_pubs));
   ret_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
                                      struct TALER_DenominationPublicKey);
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_refresh_order (plugin->cls,
                                      session,
                                      &session_hash,
@@ -672,19 +675,19 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
       = GNUNET_CRYPTO_rsa_sign_fdh (new_dkp[cnt]->priv.rsa_private_key,
                                     &hc);
     GNUNET_assert (NULL != ev_sigs[cnt].rsa_signature);
-    FAILIF (GNUNET_NO !=
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
             plugin->get_refresh_out (plugin->cls,
                                      session,
                                      &session_hash,
                                      cnt,
                                      &test_sig));
-    FAILIF (GNUNET_OK !=
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
             plugin->insert_refresh_out (plugin->cls,
                                         session,
                                         &session_hash,
                                         cnt,
                                         &ev_sigs[cnt]));
-    FAILIF (GNUNET_OK !=
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
             plugin->get_refresh_out (plugin->cls,
                                      session,
                                      &session_hash,
diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h
index 86d7f89..fd9387f 100644
--- a/src/include/taler_error_codes.h
+++ b/src/include/taler_error_codes.h
@@ -441,14 +441,6 @@ enum TALER_ErrorCode
   TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR = 1304,
 
   /**
-   * The exchange failed to store refresh order data in the
-   * database.
-   * This response is provided with HTTP status code
-   * MHD_HTTP_INTERNAL_ERROR.
-   */
-  TALER_EC_REFRESH_MELT_DB_STORE_ORDER_ERROR = 1305,
-
-  /**
    * The exchange failed to store commit data in the
    * database.
    * This response is provided with HTTP status code
@@ -457,14 +449,6 @@ enum TALER_ErrorCode
   TALER_EC_REFRESH_MELT_DB_STORE_COMMIT_ERROR = 1306,
 
   /**
-   * The exchange failed to store transfer keys in the
-   * database.
-   * This response is provided with HTTP status code
-   * MHD_HTTP_INTERNAL_ERROR.
-   */
-  TALER_EC_REFRESH_MELT_DB_STORE_TRANSFER_ERROR = 1307,
-
-  /**
    * The exchange is unaware of the denomination key that was
    * requested for one of the fresh coins.  This response is provided
    * with HTTP status code MHD_HTTP_BAD_REQUEST.
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 0406c8d..9fe0874 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -1441,11 +1441,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database handle to use
    * @param session_hash hash over the melt to use for the lookup
    * @param[out] refresh_session where to store the result
-   * @return #GNUNET_YES on success,
-   *         #GNUNET_NO if not found,
-   *         #GNUNET_SYSERR on DB failure
+   * @return transaction status
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_refresh_session) (void *cls,
                           struct TALER_EXCHANGEDB_Session *session,
                           const struct GNUNET_HashCode *session_hash,
@@ -1500,10 +1498,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session_hash hash to identify refresh session
    * @param num_newcoins size of the @a denom_pubs array
    * @param[out] denom_pubs where to write @a num_newcoins denomination keys
-   * @return #GNUNET_OK on success
-   *         #GNUNET_SYSERR on internal error
+   * @return transaction status
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_refresh_order) (void *cls,
                         struct TALER_EXCHANGEDB_Session *session,
                         const struct GNUNET_HashCode *session_hash,
@@ -1541,11 +1538,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session_hash hash to identify refresh session
    * @param num_coins size of the @a commit_coins array
    * @param[out] commit_coins array of coin commitments to return
-   * @return #GNUNET_OK on success
-   *         #GNUNET_NO if not found
-   *         #GNUNET_SYSERR on error
+   * @return transaction status
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_refresh_commit_coins) (void *cls,
                                struct TALER_EXCHANGEDB_Session *session,
                                const struct GNUNET_HashCode *session_hash,
@@ -1591,11 +1586,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database connection to use
    * @param session_hash hash to identify refresh session
    * @param[out] tp information to return
-   * @return #GNUNET_SYSERR on internal error,
-   *         #GNUNET_NO if commitment was not found
-   *         #GNUNET_OK on success
+   * @return transaction status
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_refresh_transfer_public_key) (void *cls,
                                       struct TALER_EXCHANGEDB_Session *session,
                                       const struct GNUNET_HashCode 
*session_hash,
@@ -1612,10 +1605,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session_hash hash to identify refresh session
    * @param newcoin_index coin index
    * @param[out] ev_sig coin signature
-   * @return #GNUNET_OK on success, #GNUNET_NO if we have no such entry,
-   *         #GNUNET_SYSERR on error
+   * @return transaction result status
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_refresh_out) (void *cls,
                       struct TALER_EXCHANGEDB_Session *session,
                       const struct GNUNET_HashCode *session_hash,
@@ -1634,10 +1626,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session_hash hash to identify refresh session
    * @param newcoin_index coin index
    * @param ev_sig coin signature
-   * @return #GNUNET_OK on success
-   *         #GNUNET_SYSERR on error
+   * @return transaction result status
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_refresh_out) (void *cls,
                          struct TALER_EXCHANGEDB_Session *session,
                          const struct GNUNET_HashCode *session_hash,

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]