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: address #5010 for /


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: address #5010 for /refresh/melt
Date: Thu, 22 Jun 2017 11:49:44 +0200

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new fbff951  address #5010 for /refresh/melt
fbff951 is described below

commit fbff951e7d0a8965c44e37716067d5ddc13c975a
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Jun 22 11:49:40 2017 +0200

    address #5010 for /refresh/melt
---
 src/exchange/taler-exchange-httpd_refresh_melt.c   | 344 +++++++++------------
 src/exchangedb/perf_taler_exchangedb_interpreter.c |  34 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |  70 ++---
 src/exchangedb/test_exchangedb.c                   |   6 +-
 src/include/taler_exchangedb_plugin.h              |  24 +-
 5 files changed, 205 insertions(+), 273 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c 
b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 71f5a99..edcd849 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -83,8 +83,8 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection 
*connection,
                                       const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                       struct TALER_Amount coin_value,
                                       struct TALER_EXCHANGEDB_TransactionList 
*tl,
-                                      struct TALER_Amount requested,
-                                      struct TALER_Amount residual)
+                                      const struct TALER_Amount *requested,
+                                      const struct TALER_Amount *residual)
 {
   json_t *history;
 
@@ -104,9 +104,9 @@ reply_refresh_melt_insufficient_funds (struct 
MHD_Connection *connection,
                                        "original_value",
                                        TALER_JSON_from_amount (&coin_value),
                                        "residual_value",
-                                       TALER_JSON_from_amount (&residual),
+                                       TALER_JSON_from_amount (residual),
                                        "requested_value",
-                                       TALER_JSON_from_amount (&requested),
+                                       TALER_JSON_from_amount (requested),
                                        "history",
                                        history);
 }
@@ -156,6 +156,17 @@ struct RefreshMeltContext
 {
 
   /**
+   * Key state that can be used to lookup keys.
+   */
+  struct TEH_KS_StateHandle *key_state;
+
+  /**
+   * Information about the denomination key of the coin being
+   * melted.
+   */ 
+  struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
+
+  /**
    * Array of denominations of the fresh coins.
    */
   struct TALER_DenominationPublicKey *denom_pubs;
@@ -205,51 +216,39 @@ struct RefreshMeltContext
  *
  * @param connection the connection to send errors to
  * @param session the database connection
- * @param key_state the exchange's key state
- * @param session_hash hash identifying the refresh session
- * @param coin_details details about the coin being melted
- * @param[out] meltp on success, set to melt details
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO if an error message was generated,
- *         #GNUNET_SYSERR on internal errors (no response generated)
+ * @param[in,out] rmc melt context
+ * @param[out] mhd_ret status code to return to MHD on hard error
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus 
 refresh_check_melt (struct MHD_Connection *connection,
                     struct TALER_EXCHANGEDB_Session *session,
-                    const struct TEH_KS_StateHandle *key_state,
-                    const struct GNUNET_HashCode *session_hash,
-                    const struct TEH_DB_MeltDetails *coin_details,
-                    struct TALER_EXCHANGEDB_RefreshMelt *meltp)
+                   struct RefreshMeltContext *rmc,
+                   int *mhd_ret)
 {
-  struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk;
-  struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
   struct TALER_EXCHANGEDB_TransactionList *tl;
+  struct TALER_EXCHANGEDB_RefreshMelt *meltp = &rmc->refresh_session.melt;
   struct TALER_Amount coin_value;
   struct TALER_Amount coin_residual;
   struct TALER_Amount spent;
-  int res;
   enum GNUNET_DB_QueryStatus qs;
 
-  dk = TEH_KS_denomination_key_lookup (key_state,
-                                       &coin_details->coin_info.denom_pub,
-                                       TEH_KS_DKU_DEPOSIT);
-  if (NULL == dk)
-    return (MHD_YES ==
-            TEH_RESPONSE_reply_internal_error (connection,
-                                              
TALER_EC_REFRESH_MELT_DB_DENOMINATION_KEY_NOT_FOUND,
-                                              "denomination key no longer 
available while executing transaction"))
-        ? GNUNET_NO : GNUNET_SYSERR;
-  dki = &dk->issue;
   TALER_amount_ntoh (&coin_value,
-                     &dki->properties.value);
+                     &rmc->dki->issue.properties.value);
   /* fee for THIS transaction; the melt amount includes the fee! */
-  spent = coin_details->melt_amount_with_fee;
+  spent = rmc->coin_melt_details.melt_amount_with_fee;
   /* add historic transaction costs of this coin */
   qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
                                           session,
-                                          &coin_details->coin_info.coin_pub,
+                                          
&rmc->coin_melt_details.coin_info.coin_pub,
                                          &tl);
-  (void) qs; /* FIXME #5010 */
+  if (0 > qs)
+  {
+    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;
+  }
   if (GNUNET_OK !=
       TEH_DB_calculate_transaction_list_totals (tl,
                                                &spent,
@@ -258,10 +257,9 @@ refresh_check_melt (struct MHD_Connection *connection,
     GNUNET_break (0);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
-    return (MHD_YES ==
-            TEH_RESPONSE_reply_internal_db_error (connection,
-                                                 
TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED))
-      ? GNUNET_NO : GNUNET_SYSERR;
+    *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                    
TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
   /* Refuse to refresh when the coin's value is insufficient
      for the cost of all transactions. */
@@ -271,43 +269,41 @@ refresh_check_melt (struct MHD_Connection *connection,
     GNUNET_assert (GNUNET_SYSERR !=
                    TALER_amount_subtract (&coin_residual,
                                           &spent,
-                                          
&coin_details->melt_amount_with_fee));
-    res = (MHD_YES ==
-           reply_refresh_melt_insufficient_funds (connection,
-                                                 
&coin_details->coin_info.coin_pub,
-                                                 coin_value,
-                                                 tl,
-                                                 
coin_details->melt_amount_with_fee,
-                                                 coin_residual))
-        ? GNUNET_NO : GNUNET_SYSERR;
+                                          
&rmc->coin_melt_details.melt_amount_with_fee));
+    *mhd_ret = reply_refresh_melt_insufficient_funds (connection,
+                                                     
&rmc->coin_melt_details.coin_info.coin_pub,
+                                                     coin_value,
+                                                     tl,
+                                                     
&rmc->coin_melt_details.melt_amount_with_fee,
+                                                     &coin_residual);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
-    return res;
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
   TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                           tl);
 
-  meltp->coin = coin_details->coin_info;
-  meltp->coin_sig = coin_details->melt_sig;
-  meltp->session_hash = *session_hash;
-  meltp->amount_with_fee = coin_details->melt_amount_with_fee;
-  meltp->melt_fee = coin_details->melt_fee;
-  return GNUNET_OK;
+  meltp->coin = rmc->coin_melt_details.coin_info;
+  meltp->coin_sig = rmc->coin_melt_details.melt_sig;
+  meltp->session_hash = rmc->session_hash;
+  meltp->amount_with_fee = rmc->coin_melt_details.melt_amount_with_fee;
+  meltp->melt_fee = rmc->coin_melt_details.melt_fee;
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
 /**
  * Execute a "/refresh/melt".  We have been given a list of valid
- * coins and a request to melt them into the given
- * @a refresh_session_pub.  Check that the coins all have the
- * required value left and if so, store that they have been
- * melted and confirm the melting operation to the client.
+ * coins and a request to melt them into the given @a
+ * refresh_session_pub.  Check that the coins all have the required
+ * value left and if so, store that they have been melted and confirm
+ * the melting operation to the client.
  *
- * 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.
+ * 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
@@ -323,9 +319,7 @@ refresh_melt_transaction (void *cls,
                          int *mhd_ret)
 {
   struct RefreshMeltContext *rmc = cls;
-  struct TEH_KS_StateHandle *key_state;
   enum GNUNET_DB_QueryStatus qs;
-  int res;
 
   qs = TEH_plugin->get_refresh_session (TEH_plugin->cls,
                                        session,
@@ -352,20 +346,12 @@ refresh_melt_transaction (void *cls,
     = 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,
-                                &rmc->session_hash,
-                                &rmc->coin_melt_details,
-                                &rmc->refresh_session.melt)))
-  {
-    TEH_KS_release (key_state);
-    *mhd_ret = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
-    return GNUNET_DB_STATUS_HARD_ERROR;    
-  }
-  TEH_KS_release (key_state);
+  qs = refresh_check_melt (connection,
+                          session,
+                          rmc,
+                          mhd_ret);
+  if (0 > qs)
+    return qs;
 
   if ( (0 >=
        (qs = TEH_plugin->create_refresh_session (TEH_plugin->cls,
@@ -403,9 +389,10 @@ refresh_melt_transaction (void *cls,
 
 
 /**
- * Handle a "/refresh/melt" request after the main JSON 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.
+ * Handle a "/refresh/melt" request after the main JSON 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.
  *
  * @param connection the MHD connection to handle
  * @param[out] mhd_ret set on failure to return value for MHD
@@ -417,7 +404,6 @@ refresh_melt_prepare (struct MHD_Connection *connection,
                      int *mhd_ret,
                      struct RefreshMeltContext *rmc)
 {
-  struct TEH_KS_StateHandle *key_state;
   struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk;
   struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
   struct TALER_Amount cost;
@@ -434,16 +420,14 @@ refresh_melt_prepare (struct MHD_Connection *connection,
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_get_zero (TEH_exchange_currency_string,
                                         &total_cost));
-  key_state = TEH_KS_acquire ();
   for (unsigned int i=0;i<rmc->num_newcoins;i++)
   {
-    dk = TEH_KS_denomination_key_lookup (key_state,
+    dk = TEH_KS_denomination_key_lookup (rmc->key_state,
                                          &rmc->denom_pubs[i],
                                          TEH_KS_DKU_WITHDRAW);
     if (NULL == dk)
     {
       GNUNET_break_op (0);
-      TEH_KS_release (key_state);
       *mhd_ret = TEH_RESPONSE_reply_arg_invalid (connection,
                                                 
TALER_EC_REFRESH_MELT_FRESH_DENOMINATION_KEY_NOT_FOUND,
                                                 "new_denoms");
@@ -464,7 +448,6 @@ refresh_melt_prepare (struct MHD_Connection *connection,
                             &total_cost)) )
     {
       GNUNET_break_op (0);
-      TEH_KS_release (key_state);
       *mhd_ret = TEH_RESPONSE_reply_internal_error (connection,
                                                    
TALER_EC_REFRESH_MELT_COST_CALCULATION_OVERFLOW,
                                                    "cost calculation failure");
@@ -472,18 +455,7 @@ refresh_melt_prepare (struct MHD_Connection *connection,
     }
   }
 
-  dk = TEH_KS_denomination_key_lookup (key_state,
-                                       
&rmc->coin_melt_details.coin_info.denom_pub,
-                                       TEH_KS_DKU_DEPOSIT);
-  if (NULL == dk)
-  {
-    GNUNET_break (0);
-    *mhd_ret = TEH_RESPONSE_reply_arg_unknown (connection,
-                                              
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
-                                              "denom_pub");
-    return GNUNET_SYSERR;
-  }
-  dki = &dk->issue;
+  dki = &rmc->dki->issue;
   TALER_amount_ntoh (&fee_melt,
                      &dki->properties.fee_refresh);
   if (GNUNET_OK !=
@@ -492,13 +464,11 @@ refresh_melt_prepare (struct MHD_Connection *connection,
                              &fee_melt))
   {
     GNUNET_break_op (0);
-    TEH_KS_release (key_state);
     *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 !=
       TALER_amount_cmp (&total_cost,
                         &total_melt))
@@ -580,87 +550,6 @@ get_coin_public_info (struct MHD_Connection *connection,
 
 
 /**
- * Verify that the signature shows that this coin is to be melted into
- * the given @a session_hash melting session, and that this is a valid
- * coin (we know the denomination key and the signature on it is
- * valid).  Essentially, this does all of the per-coin checks that can
- * be done before the transaction starts.
- *
- * @param connection the connection to send error responses to
- * @param session_hash hash over refresh session the coin is melted into
- * @param[in,out] melt_detail details about the coin's melting permission,
- *                            the `melt_fee` is updated
- * @return #GNUNET_YES if coin public info in JSON was valid
- *         #GNUNET_NO JSON was invalid, response was generated
- *         #GNUNET_SYSERR on internal error
- */
-static int
-verify_coin_public_info (struct MHD_Connection *connection,
-                         const struct GNUNET_HashCode *session_hash,
-                         struct TEH_DB_MeltDetails *melt_detail)
-{
-  struct TALER_RefreshMeltCoinAffirmationPS body;
-  struct TEH_KS_StateHandle *key_state;
-  struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
-  struct TALER_Amount fee_refresh;
-
-  /* FIXME: we lookup the dki twice during /refresh/melt.
-     This should be avoided. */
-  key_state = TEH_KS_acquire ();
-  dki = TEH_KS_denomination_key_lookup (key_state,
-                                        &melt_detail->coin_info.denom_pub,
-                                       TEH_KS_DKU_DEPOSIT);
-  if (NULL == dki)
-  {
-    TEH_KS_release (key_state);
-    TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
-    return TEH_RESPONSE_reply_arg_unknown (connection,
-                                          
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
-                                           "denom_pub");
-  }
-  TALER_amount_ntoh (&fee_refresh,
-                     &dki->issue.properties.fee_refresh);
-  melt_detail->melt_fee = fee_refresh;
-  body.purpose.size = htonl (sizeof (struct 
TALER_RefreshMeltCoinAffirmationPS));
-  body.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
-  body.session_hash = *session_hash;
-  TALER_amount_hton (&body.amount_with_fee,
-                     &melt_detail->melt_amount_with_fee);
-  TALER_amount_hton (&body.melt_fee,
-                     &fee_refresh);
-  body.coin_pub = melt_detail->coin_info.coin_pub;
-  if (TALER_amount_cmp (&fee_refresh,
-                        &melt_detail->melt_amount_with_fee) > 0)
-  {
-    GNUNET_break_op (0);
-    TEH_KS_release (key_state);
-    return (MHD_YES ==
-            TEH_RESPONSE_reply_external_error (connection,
-                                              
TALER_EC_REFRESH_MELT_AMOUNT_INSUFFICIENT,
-                                               "melt amount smaller than 
melting fee"))
-      ? GNUNET_NO : GNUNET_SYSERR;
-  }
-
-  TEH_KS_release (key_state);
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
-                                  &body.purpose,
-                                  &melt_detail->melt_sig.eddsa_signature,
-                                  &melt_detail->coin_info.coin_pub.eddsa_pub))
-  {
-    GNUNET_break_op (0);
-    if (MHD_YES !=
-        TEH_RESPONSE_reply_signature_invalid (connection,
-                                             
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
-                                              "confirm_sig"))
-      return GNUNET_SYSERR;
-    return GNUNET_NO;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
  * Release memory from the @a commit_coin array.
  *
  * @param commit_coin array to release
@@ -679,6 +568,7 @@ free_commit_coins (struct 
TALER_EXCHANGEDB_RefreshCommitCoin **commit_coin,
     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]);
+    commit_coin[i] = NULL;
   }
 }
 
@@ -695,27 +585,42 @@ cleanup_rmc (struct RefreshMeltContext *rmc)
                      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);
+    rmc->coin_melt_details.coin_info.denom_pub.rsa_public_key = NULL;
+  }
   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);
+    rmc->coin_melt_details.coin_info.denom_sig.rsa_signature = NULL;
+  }
   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);
+    rmc->denom_pubs = NULL;
   }
   if (NULL != rmc->hash_context)
+  {
     GNUNET_CRYPTO_hash_context_abort (rmc->hash_context);
+    rmc->hash_context = NULL;
+  }
+  if (NULL != rmc->key_state)
+  {
+    TEH_KS_release (rmc->key_state);
+    rmc->key_state = NULL;
+  }
 }
 
 
 /**
- * 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
- * parses the JSON arrays and then passes processing on to
- * #handle_refresh_melt_binary().
+ * 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 parses the JSON arrays and then passes
+ * processing on to #handle_refresh_melt_binary().
  *
  * @param connection the MHD connection to handle
  * @param new_denoms array of denomination keys
@@ -741,7 +646,6 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
   /* For the signature check, we hash most of the inputs together
      (except for the signatures on the coins). */
   rmc.hash_context = GNUNET_CRYPTO_hash_context_start ();
-
   for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
   {
     struct GNUNET_JSON_Specification trans_spec[] = {
@@ -765,7 +669,6 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
                                      sizeof (struct TALER_TransferPublicKeyP));
   }
 
-
   rmc.num_newcoins = json_array_size (new_denoms);
   rmc.denom_pubs = GNUNET_new_array (rmc.num_newcoins,
                                     struct TALER_DenominationPublicKey);
@@ -797,9 +700,10 @@ handle_refresh_melt_json (struct MHD_Connection 
*connection,
                                      buf_size);
     GNUNET_free (buf);
   }
-
+  
+  /* decode JSON data on coin to melt and check that this is a
+     valid coin */
   {
-    /* decode JSON data on coin to melt */
     struct TALER_AmountNBO melt_amount;
 
     res = get_coin_public_info (connection,
@@ -861,18 +765,60 @@ handle_refresh_melt_json (struct MHD_Connection 
*connection,
   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,
-                                 &rmc.session_hash,
-                                 &rmc.coin_melt_details);
-  if (GNUNET_OK != res)
+
+  rmc.key_state = TEH_KS_acquire ();
+  rmc.dki = TEH_KS_denomination_key_lookup (rmc.key_state,
+                                           
&rmc.coin_melt_details.coin_info.denom_pub,
+                                           TEH_KS_DKU_DEPOSIT);
+  if (NULL == rmc.dki)
   {
-    GNUNET_break_op (0);
-    mhd_ret = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-    cleanup_rmc (&rmc);
-    return mhd_ret;
+    TEH_KS_release (rmc.key_state);
+    TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
+    return TEH_RESPONSE_reply_arg_unknown (connection,
+                                          
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
+                                           "denom_pub");
   }
 
+  /* verify signature of coin for melt operation */
+  {
+    struct TALER_RefreshMeltCoinAffirmationPS body;
+    struct TALER_Amount fee_refresh;
+
+    TALER_amount_ntoh (&fee_refresh,
+                      &rmc.dki->issue.properties.fee_refresh);
+    rmc.coin_melt_details.melt_fee = fee_refresh;
+    body.purpose.size = htonl (sizeof (struct 
TALER_RefreshMeltCoinAffirmationPS));
+    body.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
+    body.session_hash = rmc.session_hash;
+    TALER_amount_hton (&body.amount_with_fee,
+                      &rmc.coin_melt_details.melt_amount_with_fee);
+    TALER_amount_hton (&body.melt_fee,
+                      &fee_refresh);
+    body.coin_pub = rmc.coin_melt_details.coin_info.coin_pub;
+    if (TALER_amount_cmp (&fee_refresh,
+                         &rmc.coin_melt_details.melt_amount_with_fee) > 0)
+    {
+      GNUNET_break_op (0);
+      cleanup_rmc (&rmc);
+      return TEH_RESPONSE_reply_external_error (connection,
+                                               
TALER_EC_REFRESH_MELT_AMOUNT_INSUFFICIENT,
+                                               "melt amount smaller than 
melting fee");
+    }
+    
+    if (GNUNET_OK !=
+       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
+                                   &body.purpose,
+                                   
&rmc.coin_melt_details.melt_sig.eddsa_signature,
+                                   
&rmc.coin_melt_details.coin_info.coin_pub.eddsa_pub))
+    {
+      GNUNET_break_op (0);
+      cleanup_rmc (&rmc);
+      return TEH_RESPONSE_reply_signature_invalid (connection,
+                                                  
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
+                                                  "confirm_sig");
+    }
+  }
+    
   /* prepare commit */
   if (GNUNET_OK !=
       refresh_melt_prepare (connection,
diff --git a/src/exchangedb/perf_taler_exchangedb_interpreter.c 
b/src/exchangedb/perf_taler_exchangedb_interpreter.c
index 3f52e90..7a59158 100644
--- a/src/exchangedb/perf_taler_exchangedb_interpreter.c
+++ b/src/exchangedb/perf_taler_exchangedb_interpreter.c
@@ -1553,10 +1553,11 @@ interpret (struct 
PERF_TALER_EXCHANGEDB_interpreter_state *state)
           refresh_session = PERF_TALER_EXCHANGEDB_refresh_session_init ();
           GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
                                             hash);
-          state->plugin->create_refresh_session (state->session,
-                                                 state->session,
-                                                 hash,
-                                                 refresh_session);
+          GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
+                        state->plugin->create_refresh_session (state->session,
+                                                               state->session,
+                                                               hash,
+                                                               
refresh_session));
           state->cmd[state->i].exposed.data.session_hash = hash;
           PERF_TALER_EXCHANGEDB_refresh_session_free (refresh_session);
           GNUNET_free (refresh_session);
@@ -1589,11 +1590,12 @@ interpret (struct 
PERF_TALER_EXCHANGEDB_interpreter_state *state)
           denom_index = 
state->cmd[state->i].details.insert_refresh_order.index_denom;
           session_hash = state->cmd[hash_index].exposed.data.session_hash;
           denom = state->cmd[denom_index].exposed.data.dki;
-          state->plugin->insert_refresh_order (state->plugin->cls,
-                                               state->session,
-                                               session_hash,
-                                               1,
-                                               &denom->denom_pub);
+          GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
+                        state->plugin->insert_refresh_order 
(state->plugin->cls,
+                                                             state->session,
+                                                             session_hash,
+                                                             1,
+                                                             
&denom->denom_pub));
 
         }
         break;
@@ -1616,18 +1618,18 @@ interpret (struct 
PERF_TALER_EXCHANGEDB_interpreter_state *state)
 
       case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_COIN:
         {
-          int ret;
+          enum GNUNET_DB_QueryStatus qs;
           unsigned int hash_index;
           struct TALER_EXCHANGEDB_RefreshCommitCoin *refresh_commit;
 
           hash_index = 
state->cmd[state->i].details.insert_refresh_commit_coin.index_hash;
           refresh_commit = PERF_TALER_EXCHANGEDB_refresh_commit_coin_init ();
-          ret = state->plugin->insert_refresh_commit_coins (state->plugin->cls,
-                                                            state->session,
-                                                            
state->cmd[hash_index].exposed.data.session_hash,
-                                                            1,
-                                                            refresh_commit);
-          GNUNET_assert (GNUNET_OK == ret);
+          qs = state->plugin->insert_refresh_commit_coins (state->plugin->cls,
+                                                          state->session,
+                                                          
state->cmd[hash_index].exposed.data.session_hash,
+                                                          1,
+                                                          refresh_commit);
+          GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
         }
         break;
 
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 592751f..9df7fc4 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3344,11 +3344,9 @@ postgres_get_refresh_session (void *cls,
  * @param session database handle to use
  * @param session_hash hash over the melt to use to locate the session
  * @param refresh_session session data to store
- * @return #GNUNET_YES on success,
- *         #GNUNET_NO on transient error
- *         #GNUNET_SYSERR on DB failure
+ * @return query status for the transaction
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_create_refresh_session (void *cls,
                                  struct TALER_EXCHANGEDB_Session *session,
                                  const struct GNUNET_HashCode *session_hash,
@@ -3366,7 +3364,7 @@ postgres_create_refresh_session (void *cls,
   int ret;
   enum GNUNET_DB_QueryStatus qs;
 
-  /* check if the coin is already known */
+  /* check if the coin is already known (FIXME: #5010) */
   ret = get_known_coin (cls,
                         session,
                         &refresh_session->melt.coin.coin_pub,
@@ -3384,13 +3382,13 @@ postgres_create_refresh_session (void *cls,
     if (0 > qs)
     {
       GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-      return GNUNET_SYSERR;
+      return qs;
     }
   }
-
-  return execute_prepared_non_select (session,
-                                      "insert_refresh_session",
-                                      params);
+  
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "insert_refresh_session",
+                                            params);
 }
 
 
@@ -3403,11 +3401,9 @@ postgres_create_refresh_session (void *cls,
  * @param session_hash hash to identify refresh session
  * @param num_newcoins number of coins to generate, size of the @a denom_pubs 
array
  * @param denom_pubs array denominations of the coins to create
- * @return #GNUNET_OK on success
- *         #GNUNET_NO on transient error
- *         #GNUNET_SYSERR on internal error
+ * @return query status for the transaction
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_refresh_order (void *cls,
                                struct TALER_EXCHANGEDB_Session *session,
                                const struct GNUNET_HashCode *session_hash,
@@ -3426,18 +3422,18 @@ postgres_insert_refresh_order (void *cls,
         GNUNET_PQ_query_param_auto_from_type (&denom_pub_hash),
         GNUNET_PQ_query_param_end
       };
-      int ret;
+      enum GNUNET_DB_QueryStatus qs;
 
       GNUNET_CRYPTO_rsa_public_key_hash (denom_pubs[i].rsa_public_key,
                                         &denom_pub_hash);
-      ret = execute_prepared_non_select (session,
-                                         "insert_refresh_order",
-                                         params);
-      if (GNUNET_OK != ret)
-        return ret;
+      qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                              "insert_refresh_order",
+                                              params);
+      if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+        return qs;
     }
   }
-  return GNUNET_OK;
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -3524,11 +3520,9 @@ postgres_get_refresh_order (void *cls,
  * @param session_hash hash to identify refresh session
  * @param num_newcoins coin index size of the @a commit_coins array
  * @param commit_coins array of coin commitments to store
- * @return #GNUNET_OK on success
- *         #GNUNET_NO on transient error
- *         #GNUNET_SYSERR on error
+ * @return query transaction status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_refresh_commit_coins (void *cls,
                                       struct TALER_EXCHANGEDB_Session *session,
                                       const struct GNUNET_HashCode 
*session_hash,
@@ -3544,15 +3538,15 @@ postgres_insert_refresh_commit_coins (void *cls,
                                         commit_coins[coin_off].coin_ev_size),
       GNUNET_PQ_query_param_end
     };
-    int ret;
+    enum GNUNET_DB_QueryStatus qs;
 
-    ret = execute_prepared_non_select (session,
-                                       "insert_refresh_commit_coin",
-                                       params);
-    if (GNUNET_OK != ret)
-      return ret;
+    qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "insert_refresh_commit_coin",
+                                            params);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+      return qs;
   }
-  return GNUNET_OK;
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -3640,11 +3634,9 @@ postgres_get_refresh_commit_coins (void *cls,
  * @param session database connection to use
  * @param session_hash hash to identify refresh session
  * @param tp transfer public key to store
- * @return #GNUNET_SYSERR on internal error,
- *         #GNUNET_NO on transient errors
- *         #GNUNET_OK on success
+ * @return transaction status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_refresh_transfer_public_key (void *cls,
                                              struct TALER_EXCHANGEDB_Session 
*session,
                                              const struct GNUNET_HashCode 
*session_hash,
@@ -3656,9 +3648,9 @@ postgres_insert_refresh_transfer_public_key (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  return execute_prepared_non_select (session,
-                                      "insert_transfer_public_key",
-                                      params);
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "insert_transfer_public_key",
+                                            params);
 }
 
 
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 673d514..1b3797d 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -349,7 +349,7 @@ test_refresh_commit_coins (struct TALER_EXCHANGEDB_Session 
*session,
                                 ccoin->coin_ev,
                                 ccoin->coin_ev_size);
   }
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_refresh_commit_coins (plugin->cls,
                                                session,
                                                session_hash,
@@ -417,7 +417,7 @@ test_refresh_commit_links (struct TALER_EXCHANGEDB_Session 
*session,
                                                    &tp));
   for (i=0;i<TALER_CNC_KAPPA;i++)
     RND_BLK (&rctp[i]);
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_refresh_transfer_public_key (plugin->cls,
                                                       session,
                                                       session_hash,
@@ -572,7 +572,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
     meltp->melt_fee = fee_refresh;
   }
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
          plugin->create_refresh_session (plugin->cls,
                                          session,
                                          &session_hash,
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 9fe0874..b586f27 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -1457,11 +1457,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database handle to use
    * @param session_hash hash over the melt to use to locate the session
    * @param refresh_session session data to store
-   * @return #GNUNET_YES on success,
-   *         #GNUNET_NO on transient error
-   *         #GNUNET_SYSERR on DB failure
+   * @return query status for the transaction
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*create_refresh_session) (void *cls,
                              struct TALER_EXCHANGEDB_Session *session,
                              const struct GNUNET_HashCode *session_hash,
@@ -1477,11 +1475,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session_hash hash to identify refresh session
    * @param num_newcoins number of coins to generate, size of the @a 
denom_pubs array
    * @param denom_pubs array denominations of the coins to create
-   * @return #GNUNET_OK on success
-   *         #GNUNET_NO on transient error
-   *         #GNUNET_SYSERR on internal error
+   * @return query status for the transaction
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_refresh_order) (void *cls,
                            struct TALER_EXCHANGEDB_Session *session,
                            const struct GNUNET_HashCode *session_hash,
@@ -1517,11 +1513,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session_hash hash to identify refresh session
    * @param num_newcoins coin index size of the @a commit_coins array
    * @param commit_coin array of coin commitments to store
-   * @return #GNUNET_OK on success
-   *         #GNUNET_NO on transient error
-   *         #GNUNET_SYSERR on error
+   * @return query status for the transaction
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_refresh_commit_coins) (void *cls,
                                   struct TALER_EXCHANGEDB_Session *session,
                                   const struct GNUNET_HashCode *session_hash,
@@ -1568,11 +1562,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database connection to use
    * @param session_hash hash to identify refresh session
    * @param tp public key to store
-   * @return #GNUNET_SYSERR on internal error
-   *         #GNUNET_NO on transient errors
-   *         #GNUNET_OK on success
+   * @return query status for the transaction
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_refresh_transfer_public_key) (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]