gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] 01/02: clean up KS keystate logic


From: gnunet
Subject: [taler-exchange] 01/02: clean up KS keystate logic
Date: Fri, 17 Jan 2020 19:03:39 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

commit 33d71e72802213fabbdade5239ecf75833a57335
Author: Christian Grothoff <address@hidden>
AuthorDate: Fri Jan 17 18:55:26 2020 +0100

    clean up KS keystate logic
---
 src/exchange/taler-exchange-httpd_deposit.c      | 136 +++++-----
 src/exchange/taler-exchange-httpd_keystate.c     |   3 +-
 src/exchange/taler-exchange-httpd_payback.c      | 149 +++++-----
 src/exchange/taler-exchange-httpd_refresh_melt.c | 331 +++++++++++------------
 4 files changed, 312 insertions(+), 307 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 38cc4307..0e4e0b26 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -256,7 +256,6 @@ verify_and_execute_deposit (struct MHD_Connection 
*connection,
   int mhd_ret;
   struct TALER_Amount amount_without_fee;
   struct DepositContext dc;
-  struct TEH_KS_StateHandle *mks;
   const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
   enum TALER_ErrorCode ec;
   unsigned int hc;
@@ -288,32 +287,35 @@ verify_and_execute_deposit (struct MHD_Connection 
*connection,
   }
 
   /* check denomination */
-  mks = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
-  if (NULL == mks)
-  {
-    TALER_LOG_ERROR ("Lacking keys to operate\n");
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       TALER_EC_EXCHANGE_BAD_CONFIGURATION,
-                                       "no keys");
-  }
-  dki = TEH_KS_denomination_key_lookup_by_hash (mks,
-                                                &deposit->coin.denom_pub_hash,
-                                                TEH_KS_DKU_DEPOSIT,
-                                                &ec,
-                                                &hc);
-  if (NULL == dki)
   {
+    struct TEH_KS_StateHandle *mks;
+
+    mks = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
+    if (NULL == mks)
+    {
+      TALER_LOG_ERROR ("Lacking keys to operate\n");
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_EXCHANGE_BAD_CONFIGURATION,
+                                         "no keys");
+    }
+    dki = TEH_KS_denomination_key_lookup_by_hash (mks,
+                                                  
&deposit->coin.denom_pub_hash,
+                                                  TEH_KS_DKU_DEPOSIT,
+                                                  &ec,
+                                                  &hc);
+    if (NULL == dki)
+    {
+      TEH_KS_release (mks);
+      return TALER_MHD_reply_with_error (connection,
+                                         hc,
+                                         ec,
+                                         "Could not find denomination key used 
in deposit");
+    }
+    TALER_amount_ntoh (&dc.value,
+                       &dki->issue.properties.value);
     TEH_KS_release (mks);
-    return TALER_MHD_reply_with_error (connection,
-                                       hc,
-                                       ec,
-                                       "Could not find denomination key used 
in deposit");
   }
-  TALER_amount_ntoh (&dc.value,
-                     &dki->issue.properties.value);
-  TEH_KS_release (mks);
-
   /* execute transaction */
   dc.deposit = deposit;
   if (GNUNET_OK !=
@@ -406,7 +408,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
   unsigned int hc;
   struct TALER_EXCHANGEDB_Deposit deposit;
   struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
-  struct TEH_KS_StateHandle *key_state;
   struct GNUNET_HashCode my_h_wire;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_json ("wire", &wire),
@@ -503,50 +504,53 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler 
*rh,
   }
 
   /* check denomination exists and is valid */
-  key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
-  if (NULL == key_state)
-  {
-    TALER_LOG_ERROR ("Lacking keys to operate\n");
-    GNUNET_JSON_parse_free (spec);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       TALER_EC_EXCHANGE_BAD_CONFIGURATION,
-                                       "no keys");
-  }
-  dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
-                                                &deposit.coin.denom_pub_hash,
-                                                TEH_KS_DKU_DEPOSIT,
-                                                &ec,
-                                                &hc);
-  if (NULL == dki)
   {
+    struct TEH_KS_StateHandle *key_state;
+
+    key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
+    if (NULL == key_state)
+    {
+      TALER_LOG_ERROR ("Lacking keys to operate\n");
+      GNUNET_JSON_parse_free (spec);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_EXCHANGE_BAD_CONFIGURATION,
+                                         "no keys");
+    }
+    dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                  &deposit.coin.denom_pub_hash,
+                                                  TEH_KS_DKU_DEPOSIT,
+                                                  &ec,
+                                                  &hc);
+    if (NULL == dki)
+    {
+      TEH_KS_release (key_state);
+      TALER_LOG_WARNING ("Unknown denomination key in /deposit request\n");
+      GNUNET_JSON_parse_free (spec);
+      return TALER_MHD_reply_with_error (connection,
+                                         hc,
+                                         ec,
+                                         "Could not find denomination key used 
in deposit");
+    }
+    TALER_amount_ntoh (&deposit.deposit_fee,
+                       &dki->issue.properties.fee_deposit);
+    /* check coin signature */
+    if (GNUNET_YES !=
+        TALER_test_coin_valid (&deposit.coin,
+                               &dki->denom_pub))
+    {
+      TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
+      TEH_KS_release (key_state);
+      GNUNET_JSON_parse_free (spec);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_UNAUTHORIZED,
+                                         
TALER_EC_DEPOSIT_DENOMINATION_SIGNATURE_INVALID,
+                                         "ub_sig");
+    }
+    TALER_amount_ntoh (&deposit.deposit_fee,
+                       &dki->issue.properties.fee_deposit);
     TEH_KS_release (key_state);
-    TALER_LOG_WARNING ("Unknown denomination key in /deposit request\n");
-    GNUNET_JSON_parse_free (spec);
-    return TALER_MHD_reply_with_error (connection,
-                                       hc,
-                                       ec,
-                                       "Could not find denomination key used 
in deposit");
-  }
-  TALER_amount_ntoh (&deposit.deposit_fee,
-                     &dki->issue.properties.fee_deposit);
-  /* check coin signature */
-  if (GNUNET_YES !=
-      TALER_test_coin_valid (&deposit.coin,
-                             &dki->denom_pub))
-  {
-    TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
-    TEH_KS_release (key_state);
-    GNUNET_JSON_parse_free (spec);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_UNAUTHORIZED,
-                                       
TALER_EC_DEPOSIT_DENOMINATION_SIGNATURE_INVALID,
-                                       "ub_sig");
   }
-  TALER_amount_ntoh (&deposit.deposit_fee,
-                     &dki->issue.properties.fee_deposit);
-  TEH_KS_release (key_state);
-
   if (0 < TALER_amount_cmp (&deposit.deposit_fee,
                             &deposit.amount_with_fee))
   {
diff --git a/src/exchange/taler-exchange-httpd_keystate.c 
b/src/exchange/taler-exchange-httpd_keystate.c
index 8b40144d..60b7cb2c 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -448,6 +448,7 @@ ks_release (struct TEH_KS_StateHandle *key_state)
   key_state->refcnt--;
   if (0 == key_state->refcnt)
   {
+    GNUNET_assert (key_state != internal_key_state);
     if (NULL != key_state->denomkey_map)
     {
       GNUNET_CONTAINER_multihashmap_iterate (key_state->denomkey_map,
@@ -476,7 +477,6 @@ ks_release (struct TEH_KS_StateHandle *key_state)
     GNUNET_array_grow (key_state->krd_array,
                        key_state->krd_array_length,
                        0);
-    GNUNET_assert (key_state != internal_key_state);
     GNUNET_free (key_state);
   }
 }
@@ -1261,6 +1261,7 @@ setup_general_response_headers (const struct 
TEH_KS_StateHandle *key_state,
     m = GNUNET_TIME_relative_to_absolute (TEH_max_keys_caching);
     m = GNUNET_TIME_absolute_min (m,
                                   key_state->next_reload);
+    m = GNUNET_TIME_UNIT_FOREVER_ABS;
     get_date_string (m,
                      dat);
     // FIXME: setting 'm' to FOREVER here exposes
diff --git a/src/exchange/taler-exchange-httpd_payback.c 
b/src/exchange/taler-exchange-httpd_payback.c
index bfd0f413..1a6a67d5 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -420,7 +420,6 @@ verify_and_execute_payback (struct MHD_Connection 
*connection,
                             int refreshed)
 {
   struct PaybackContext pc;
-  struct TEH_KS_StateHandle *key_state;
   const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
   struct TALER_PaybackRequestPS pr;
   struct GNUNET_HashCode c_hash;
@@ -430,86 +429,88 @@ verify_and_execute_payback (struct MHD_Connection 
*connection,
   unsigned int hc;
 
   /* check denomination exists and is in payback mode */
-  key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
-  if (NULL == key_state)
   {
-    TALER_LOG_ERROR ("Lacking keys to operate\n");
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       TALER_EC_EXCHANGE_BAD_CONFIGURATION,
-                                       "no keys");
-  }
-  dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
-                                                &coin->denom_pub_hash,
-                                                TEH_KS_DKU_PAYBACK,
-                                                &ec,
-                                                &hc);
-  if (NULL == dki)
-  {
-    TEH_KS_release (key_state);
-    TALER_LOG_WARNING (
-      "Denomination key in /payback request not in payback mode\n");
-    return TALER_MHD_reply_with_error (connection,
-                                       hc,
-                                       ec,
-                                       "denomination not allowing payback");
-  }
-  TALER_amount_ntoh (&pc.value,
-                     &dki->issue.properties.value);
+    struct TEH_KS_StateHandle *key_state;
 
-  /* check denomination signature */
-  if (GNUNET_YES !=
-      TALER_test_coin_valid (coin,
-                             &dki->denom_pub))
-  {
-    TALER_LOG_WARNING ("Invalid coin passed for /payback\n");
-    TEH_KS_release (key_state);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_FORBIDDEN,
-                                       
TALER_EC_PAYBACK_DENOMINATION_SIGNATURE_INVALID,
-                                       "denom_sig");
-  }
+    key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
+    if (NULL == key_state)
+    {
+      TALER_LOG_ERROR ("Lacking keys to operate\n");
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_EXCHANGE_BAD_CONFIGURATION,
+                                         "no keys");
+    }
+    dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                  &coin->denom_pub_hash,
+                                                  TEH_KS_DKU_PAYBACK,
+                                                  &ec,
+                                                  &hc);
+    if (NULL == dki)
+    {
+      TEH_KS_release (key_state);
+      TALER_LOG_WARNING (
+        "Denomination key in /payback request not in payback mode\n");
+      return TALER_MHD_reply_with_error (connection,
+                                         hc,
+                                         ec,
+                                         "denomination not allowing payback");
+    }
+    TALER_amount_ntoh (&pc.value,
+                       &dki->issue.properties.value);
 
-  /* check payback request signature */
-  pr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_PAYBACK);
-  pr.purpose.size = htonl (sizeof (struct TALER_PaybackRequestPS));
-  pr.coin_pub = coin->coin_pub;
-  pr.h_denom_pub = dki->issue.properties.denom_hash;
-  pr.coin_blind = *coin_bks;
+    /* check denomination signature */
+    if (GNUNET_YES !=
+        TALER_test_coin_valid (coin,
+                               &dki->denom_pub))
+    {
+      TALER_LOG_WARNING ("Invalid coin passed for /payback\n");
+      TEH_KS_release (key_state);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_FORBIDDEN,
+                                         
TALER_EC_PAYBACK_DENOMINATION_SIGNATURE_INVALID,
+                                         "denom_sig");
+    }
 
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_PAYBACK,
-                                  &pr.purpose,
-                                  &coin_sig->eddsa_signature,
-                                  &coin->coin_pub.eddsa_pub))
-  {
-    TALER_LOG_WARNING ("Invalid signature on /payback request\n");
-    TEH_KS_release (key_state);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_FORBIDDEN,
-                                       TALER_EC_PAYBACK_SIGNATURE_INVALID,
-                                       "coin_sig");
-  }
+    /* check payback request signature */
+    pr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_PAYBACK);
+    pr.purpose.size = htonl (sizeof (struct TALER_PaybackRequestPS));
+    pr.coin_pub = coin->coin_pub;
+    pr.h_denom_pub = dki->issue.properties.denom_hash;
+    pr.coin_blind = *coin_bks;
 
-  GNUNET_CRYPTO_hash (&coin->coin_pub.eddsa_pub,
-                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
-                      &c_hash);
-  if (GNUNET_YES !=
-      GNUNET_CRYPTO_rsa_blind (&c_hash,
-                               &coin_bks->bks,
-                               dki->denom_pub.rsa_public_key,
-                               &coin_ev,
-                               &coin_ev_size))
-  {
-    GNUNET_break (0);
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_PAYBACK,
+                                    &pr.purpose,
+                                    &coin_sig->eddsa_signature,
+                                    &coin->coin_pub.eddsa_pub))
+    {
+      TALER_LOG_WARNING ("Invalid signature on /payback request\n");
+      TEH_KS_release (key_state);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_FORBIDDEN,
+                                         TALER_EC_PAYBACK_SIGNATURE_INVALID,
+                                         "coin_sig");
+    }
+    GNUNET_CRYPTO_hash (&coin->coin_pub.eddsa_pub,
+                        sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
+                        &c_hash);
+    if (GNUNET_YES !=
+        GNUNET_CRYPTO_rsa_blind (&c_hash,
+                                 &coin_bks->bks,
+                                 dki->denom_pub.rsa_public_key,
+                                 &coin_ev,
+                                 &coin_ev_size))
+    {
+      GNUNET_break (0);
+      TEH_KS_release (key_state);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_PAYBACK_BLINDING_FAILED,
+                                         "coin_bks");
+    }
     TEH_KS_release (key_state);
-
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       TALER_EC_PAYBACK_BLINDING_FAILED,
-                                       "coin_bks");
   }
-  TEH_KS_release (key_state);
   GNUNET_CRYPTO_hash (coin_ev,
                       coin_ev_size,
                       &pc.h_blind);
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c 
b/src/exchange/taler-exchange-httpd_refresh_melt.c
index e0a4d836..e2d92c50 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -51,7 +51,7 @@ static int
 reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection,
                                        const struct
                                        TALER_CoinSpendPublicKeyP *coin_pub,
-                                       struct TALER_Amount coin_value,
+                                       const struct TALER_Amount *coin_value,
                                        struct TALER_EXCHANGEDB_TransactionList 
*
                                        tl,
                                        const struct TALER_Amount *requested,
@@ -77,7 +77,7 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection 
*connection,
                                     "coin_pub",
                                     GNUNET_JSON_from_data_auto (coin_pub),
                                     "original_value",
-                                    TALER_JSON_from_amount (&coin_value),
+                                    TALER_JSON_from_amount (coin_value),
                                     "residual_value",
                                     TALER_JSON_from_amount (residual),
                                     "requested_value",
@@ -144,12 +144,17 @@ struct RefreshMeltContext
   struct TALER_EXCHANGEDB_RefreshSession refresh_session;
 
   /**
-   * Information about the @e coin's denomination.
+   * Information about the @e coin's value.
    */
-  struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
+  struct TALER_Amount coin_value;
 
   /**
-   * Set to #GNUNET_YES if this @a dki was revoked and the operation
+   * Information about the @e coin's refresh fee.
+   */
+  struct TALER_Amount coin_refresh_fee;
+
+  /**
+   * Set to #GNUNET_YES if this coin's denomination was revoked and the 
operation
    * is thus only allowed for zombie coins where the transaction
    * history includes a #TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK.
    */
@@ -175,12 +180,9 @@ refresh_check_melt (struct MHD_Connection *connection,
                     int *mhd_ret)
 {
   struct TALER_EXCHANGEDB_TransactionList *tl;
-  struct TALER_Amount coin_value;
   struct TALER_Amount spent;
   enum GNUNET_DB_QueryStatus qs;
 
-  TALER_amount_ntoh (&coin_value,
-                     &rmc->dki->issue.properties.value);
   /* Start with cost of this melt transaction */
   spent = rmc->refresh_session.amount_with_fee;
 
@@ -242,7 +244,7 @@ refresh_check_melt (struct MHD_Connection *connection,
 
   /* Refuse to refresh when the coin's value is insufficient
      for the cost of all transactions. */
-  if (TALER_amount_cmp (&coin_value,
+  if (TALER_amount_cmp (&rmc->coin_value,
                         &spent) < 0)
   {
     struct TALER_Amount coin_residual;
@@ -254,7 +256,7 @@ refresh_check_melt (struct MHD_Connection *connection,
     *mhd_ret = reply_refresh_melt_insufficient_funds (connection,
                                                       
&rmc->refresh_session.coin
                                                       .coin_pub,
-                                                      coin_value,
+                                                      &rmc->coin_value,
                                                       tl,
                                                       &rmc->refresh_session.
                                                       amount_with_fee,
@@ -374,22 +376,6 @@ static int
 handle_refresh_melt (struct MHD_Connection *connection,
                      struct RefreshMeltContext *rmc)
 {
-  /* sanity-check that "total melt amount > melt fee" */
-  {
-    struct TALER_Amount fee_refresh;
-
-    TALER_amount_ntoh (&fee_refresh,
-                       &rmc->dki->issue.properties.fee_refresh);
-    if (TALER_amount_cmp (&fee_refresh,
-                          &rmc->refresh_session.amount_with_fee) > 0)
-    {
-      GNUNET_break_op (0);
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_BAD_REQUEST,
-                                         
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION,
-                                         "melt amount smaller than melting 
fee");
-    }
-  }
 
   /* verify signature of coin for melt operation */
   {
@@ -401,7 +387,8 @@ handle_refresh_melt (struct MHD_Connection *connection,
     body.rc = rmc->refresh_session.rc;
     TALER_amount_hton (&body.amount_with_fee,
                        &rmc->refresh_session.amount_with_fee);
-    body.melt_fee = rmc->dki->issue.properties.fee_refresh;
+    TALER_amount_hton (&body.melt_fee,
+                       &rmc->coin_refresh_fee);
     body.coin_pub = rmc->refresh_session.coin.coin_pub;
 
     if (GNUNET_OK !=
@@ -440,6 +427,155 @@ handle_refresh_melt (struct MHD_Connection *connection,
 }
 
 
+/**
+ * Check for information about the melted coin's denomination,
+ * extracting its validity status and fee structure.
+ *
+ * @param connection HTTP connection we are handling
+ * @param rmc parsed request information
+ * @return MHD status code
+ */
+static int
+check_for_denomination_key (struct MHD_Connection *connection,
+                            struct RefreshMeltContext *rmc)
+{
+  struct TEH_KS_StateHandle *key_state;
+
+  key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
+  if (NULL == key_state)
+  {
+    TALER_LOG_ERROR ("Lacking keys to operate\n");
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       TALER_EC_EXCHANGE_BAD_CONFIGURATION,
+                                       "no keys");
+  }
+
+  {
+    /* Baseline: check if deposits/refreshs are generally
+       simply still allowed for this denomination */
+    struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
+    unsigned int hc;
+    enum TALER_ErrorCode ec;
+
+    dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                  &rmc->refresh_session.coin.
+                                                  denom_pub_hash,
+                                                  TEH_KS_DKU_DEPOSIT,
+                                                  &ec,
+                                                  &hc);
+    /* Consider case that denomination was revoked but
+       this coin was already seen and thus refresh is OK. */
+    if (NULL == dki)
+    {
+      dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                    &rmc->refresh_session.coin.
+                                                    denom_pub_hash,
+                                                    TEH_KS_DKU_PAYBACK,
+                                                    &ec,
+                                                    &hc);
+      if (NULL != dki)
+      {
+        struct GNUNET_HashCode denom_hash;
+        enum GNUNET_DB_QueryStatus qs;
+
+        qs = TEH_plugin->get_coin_denomination (TEH_plugin->cls,
+                                                NULL,
+                                                &rmc->refresh_session.coin.
+                                                coin_pub,
+                                                &denom_hash);
+        if (0 > qs)
+        {
+          TEH_KS_release (key_state);
+          return TALER_MHD_reply_with_error (connection,
+                                             MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                             
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR,
+                                             "failed to find information about 
old coin");
+        }
+        GNUNET_break (0 ==
+                      GNUNET_memcmp (&denom_hash,
+                                     
&rmc->refresh_session.coin.denom_pub_hash));
+        if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+        {
+          /* We never saw this coin before, so _this_ justification is not OK 
*/
+          dki = NULL;
+        }
+      }
+    }
+
+    /* Consider the case that the denomination expired for deposits,
+       but /refresh/payback refilled the balance of the 'zombie' coin
+       and we should thus allow the refresh during the legal period. */
+    if (NULL == dki)
+    {
+      dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                    &rmc->refresh_session.coin.
+                                                    denom_pub_hash,
+                                                    TEH_KS_DKU_ZOMBIE,
+                                                    &ec,
+                                                    &hc);
+      if (NULL != dki)
+        rmc->zombie_required = GNUNET_YES;
+    }
+    if (NULL == dki)
+    {
+      TEH_KS_release (key_state);
+      TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt 
request\n");
+      return TALER_MHD_reply_with_error (connection,
+                                         hc,
+                                         ec,
+                                         "unknown denomination");
+    }
+    TALER_amount_ntoh (&rmc->coin_refresh_fee,
+                       &dki->issue.properties.fee_refresh);
+    TALER_amount_ntoh (&rmc->coin_value,
+                       &dki->issue.properties.value);
+    if (GNUNET_OK !=
+        TALER_test_coin_valid (&rmc->refresh_session.coin,
+                               &dki->denom_pub))
+    {
+      GNUNET_break_op (0);
+      TEH_KS_release (key_state);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_FORBIDDEN,
+                                         
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID,
+                                         "denom_sig");
+    }
+  }
+  TEH_KS_release (key_state);
+
+  /* run actual logic, now that the request was parsed */
+  /* make sure coin is 'known' in database */
+  {
+    struct TEH_DB_KnowCoinContext kcc;
+    int mhd_ret;
+
+    kcc.coin = &rmc->refresh_session.coin;
+    kcc.connection = connection;
+    if (GNUNET_OK !=
+        TEH_DB_run_transaction (connection,
+                                "know coin for refresh-melt",
+                                &mhd_ret,
+                                &TEH_DB_know_coin_transaction,
+                                &kcc))
+      return mhd_ret;
+  }
+
+  /* sanity-check that "total melt amount > melt fee" */
+  if (TALER_amount_cmp (&rmc->coin_refresh_fee,
+                        &rmc->refresh_session.amount_with_fee) > 0)
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION,
+                                       "melt amount smaller than melting fee");
+  }
+  return handle_refresh_melt (connection,
+                              rmc);
+}
+
+
 /**
  * Handle a "/refresh/melt" request.  Parses the request into the JSON
  * components and then hands things of to #handle_refresh_melt_json()
@@ -463,9 +599,6 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler 
*rh,
   json_t *root;
   struct RefreshMeltContext rmc;
   int res;
-  unsigned int hc;
-  enum TALER_ErrorCode ec;
-  struct TEH_KS_StateHandle *key_state;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("coin_pub",
                                  &rmc.refresh_session.coin.coin_pub),
@@ -504,143 +637,9 @@ TEH_REFRESH_handler_refresh_melt (struct 
TEH_RequestHandler *rh,
   if (GNUNET_OK != res)
     return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
 
-  key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
-  if (NULL == key_state)
-  {
-    TALER_LOG_ERROR ("Lacking keys to operate\n");
-    res = TALER_MHD_reply_with_error (connection,
-                                      MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                      TALER_EC_EXCHANGE_BAD_CONFIGURATION,
-                                      "no keys");
-    goto cleanup;
-  }
-
-  /* Baseline: check if deposits/refreshs are generally
-     simply still allowed for this denomination */
-  rmc.dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
-                                                    &rmc.refresh_session.coin.
-                                                    denom_pub_hash,
-                                                    TEH_KS_DKU_DEPOSIT,
-                                                    &ec,
-                                                    &hc);
-  /* Consider case that denomination was revoked but
-     this coin was already seen and thus refresh is OK. */
-  if (NULL == rmc.dki)
-  {
-    struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
-
-    dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
-                                                  &rmc.refresh_session.coin.
-                                                  denom_pub_hash,
-                                                  TEH_KS_DKU_PAYBACK,
-                                                  &ec,
-                                                  &hc);
-    if (NULL != dki)
-    {
-      struct TALER_CoinPublicInfo coin_info;
-      enum GNUNET_DB_QueryStatus qs;
-
-      qs = TEH_plugin->get_known_coin (TEH_plugin->cls,
-                                       NULL,
-                                       &rmc.refresh_session.coin.coin_pub,
-                                       &coin_info);
-      if (0 > qs)
-      {
-        GNUNET_break (0);
-        res = TALER_MHD_reply_with_error (connection,
-                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                          TALER_EC_REFRESH_MELT_DB_FETCH_ERROR,
-                                          "failed to find information about 
old coin");
-        goto cleanup;
-      }
-      if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-      {
-        /* Coin was known beforehand, so we should allow the refresh */
-        rmc.dki = dki;
-        GNUNET_CRYPTO_rsa_signature_free (coin_info.denom_sig.rsa_signature);
-      }
-    }
-  }
-
-  /* Consider the case that the denomination expired for deposits,
-     but /refresh/payback refilled the balance of the 'zombie' coin
-     and we should thus allow the refresh during the legal period. */
-  if (NULL == rmc.dki)
-  {
-    struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
-
-    dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
-                                                  &rmc.refresh_session.coin.
-                                                  denom_pub_hash,
-                                                  TEH_KS_DKU_ZOMBIE,
-                                                  &ec,
-                                                  &hc);
-    if (NULL != dki)
-    {
-      rmc.dki = dki;
-      rmc.zombie_required = GNUNET_YES;
-    }
-  }
-
-  if (NULL == rmc.dki)
-  {
-    TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
-    res = TALER_MHD_reply_with_error (connection,
-                                      hc,
-                                      ec,
-                                      "unknown denomination");
-    goto cleanup;
-  }
-
-  if (GNUNET_OK !=
-      TALER_test_coin_valid (&rmc.refresh_session.coin,
-                             &rmc.dki->denom_pub))
-  {
-    GNUNET_break_op (0);
-    GNUNET_JSON_parse_free (spec);
-    TEH_KS_release (key_state);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_FORBIDDEN,
-                                       
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID,
-                                       "denom_sig");
-  }
-
-  /* run actual logic, now that the request was parsed */
-
-  /* make sure coin is 'known' in database */
-  {
-    struct TEH_DB_KnowCoinContext kcc;
-    int mhd_ret;
-
-    kcc.coin = &rmc.refresh_session.coin;
-    kcc.connection = connection;
-    if (GNUNET_OK !=
-        TEH_DB_run_transaction (connection,
-                                "know coin for refresh-melt",
-                                &mhd_ret,
-                                &TEH_DB_know_coin_transaction,
-                                &kcc))
-      return mhd_ret;
-  }
-
-  res = handle_refresh_melt (connection,
-                             &rmc);
-
-
-cleanup:
-  if (NULL != key_state)
-  {
-    TEH_KS_release (key_state);
-    key_state = NULL;
-  }
-  if (NULL != rmc.refresh_session.coin.denom_sig.rsa_signature)
-  {
-    GNUNET_CRYPTO_rsa_signature_free (
-      rmc.refresh_session.coin.denom_sig.rsa_signature);
-    rmc.refresh_session.coin.denom_sig.rsa_signature = NULL;
-  }
+  res = check_for_denomination_key (connection,
+                                    &rmc);
   GNUNET_JSON_parse_free (spec);
-
   return res;
 }
 

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



reply via email to

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