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 (05d5b735 -> 5844a20


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated (05d5b735 -> 5844a20f)
Date: Wed, 24 Jul 2019 00:30:13 +0200

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

grothoff pushed a change to branch master
in repository exchange.

    from 05d5b735 typo
     new e75d5522 need the hash of coin_ev with an index for select
     new 5844a20f implement zombie check

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_deposit.c      |   4 +-
 src/exchange/taler-exchange-httpd_payback.c      |   6 +-
 src/exchange/taler-exchange-httpd_refresh_melt.c | 107 +++++++++++++++--------
 src/exchange/taler-exchange-httpd_refund.c       |   2 +-
 src/exchange/taler-exchange-httpd_responses.c    |   2 +-
 src/exchangedb/plugin_exchangedb_postgres.c      |  51 ++++++-----
 src/include/taler_error_codes.h                  |   8 +-
 src/lib/test_exchange_api_revocation.c           |  31 ++++---
 src/lib/testing_api_cmd_payback.c                | 101 ++++++++++++++-------
 9 files changed, 203 insertions(+), 109 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 5320c9c7..51adacb7 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -179,7 +179,9 @@ deposit_transaction (void *cls,
 
   /* Start with fee for THIS transaction */
   spent = deposit->amount_with_fee;
-  /* add cost of all previous transactions */
+  /* add cost of all previous transactions; skip PAYBACK as revoked
+     denominations are not eligible for deposit, and if we are the old coin
+     pub of a revoked coin (aka a zombie), then ONLY refresh is allowed. */
   qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
                                           session,
                                           &deposit->coin.coin_pub,
diff --git a/src/exchange/taler-exchange-httpd_payback.c 
b/src/exchange/taler-exchange-httpd_payback.c
index 45f8c2fc..8cfc1aec 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -281,13 +281,15 @@ payback_transaction (void *cls,
   }
   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   {
-    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Payback requested for unknown envelope %s\n",
+                GNUNET_h2s (&pc->h_blind));
     *mhd_ret = reply_payback_unknown (connection,
                                       TALER_EC_PAYBACK_WITHDRAW_NOT_FOUND);
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
-  /* Calculate remaining balance. */
+  /* Calculate remaining balance, including paybacks already applied. */
   qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
                                           session,
                                           &pc->coin->coin_pub,
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c 
b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 5674a12f..8677d627 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -48,11 +48,11 @@
  */
 static int
 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,
-                                      const struct TALER_Amount *requested,
-                                      const struct TALER_Amount *residual)
+                                       const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
+                                       struct TALER_Amount coin_value,
+                                       struct TALER_EXCHANGEDB_TransactionList 
*tl,
+                                       const struct TALER_Amount *requested,
+                                       const struct TALER_Amount *residual)
 {
   json_t *history;
 
@@ -64,9 +64,9 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection 
*connection,
                                        MHD_HTTP_FORBIDDEN,
                                        "{s:s, s:I, s:o, s:o, s:o, s:o, s:o}",
                                        "error",
-                                      "insufficient funds",
-                                      "code",
-                                      (json_int_t) 
TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS,
+                                       "insufficient funds",
+                                       "code",
+                                       (json_int_t) 
TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS,
                                        "coin_pub",
                                        GNUNET_JSON_from_data_auto (coin_pub),
                                        "original_value",
@@ -90,8 +90,8 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection 
*connection,
  */
 static int
 reply_refresh_melt_success (struct MHD_Connection *connection,
-                           const struct TALER_RefreshCommitmentP *rc,
-                           uint32_t noreveal_index)
+                            const struct TALER_RefreshCommitmentP *rc,
+                            uint32_t noreveal_index)
 {
   struct TALER_RefreshMeltConfirmationPS body;
   struct TALER_ExchangePublicKeyP pub;
@@ -139,6 +139,13 @@ struct RefreshMeltContext
    */
   struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
 
+  /**
+   * Set to #GNUNET_YES if this @a dki was revoked and the operation
+   * is thus only allowed for zombie coins where the transaction
+   * history includes a #TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK.
+   */
+  int zombie_required;
+
 };
 
 
@@ -168,11 +175,12 @@ refresh_check_melt (struct MHD_Connection *connection,
   /* Start with cost of this melt transaction */
   spent = rmc->refresh_session.amount_with_fee;
 
-  /* add historic transaction costs of this coin */
+  /* add historic transaction costs of this coin, including paybacks as
+     we might be a zombie coin */
   qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
                                           session,
                                           &rmc->refresh_session.coin.coin_pub,
-                                          GNUNET_NO,
+                                          GNUNET_YES,
                                           &tl);
   if (0 > qs)
   {
@@ -181,16 +189,40 @@ refresh_check_melt (struct MHD_Connection *connection,
                                                        
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
     return qs;
   }
+  if (rmc->zombie_required)
+  {
+    for (struct TALER_EXCHANGEDB_TransactionList *tp = tl;
+         NULL != tp;
+         tp = tp->next)
+    {
+      if (TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK == tp->type)
+      {
+        rmc->zombie_required = GNUNET_NO; /* was satisfied! */
+        break;
+      }
+    }
+    if (rmc->zombie_required)
+    {
+      /* zombie status not satisfied */
+      GNUNET_break (0);
+      TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
+                                              tl);
+      *mhd_ret = TEH_RESPONSE_reply_external_error (connection,
+                                                    
TALER_EC_REFRESH_MELT_COIN_EXPIRED_NO_ZOMBIE,
+                                                    "denomination expired");
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
   if (GNUNET_OK !=
       TEH_DB_calculate_transaction_list_totals (tl,
-                                               &spent,
-                                               &spent))
+                                                &spent,
+                                                &spent))
   {
     GNUNET_break (0);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
     *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
-                                                    
TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED);
+                                                     
TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED);
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
@@ -206,11 +238,11 @@ refresh_check_melt (struct MHD_Connection *connection,
                                           &spent,
                                           
&rmc->refresh_session.amount_with_fee));
     *mhd_ret = reply_refresh_melt_insufficient_funds (connection,
-                                                     
&rmc->refresh_session.coin.coin_pub,
-                                                     coin_value,
-                                                     tl,
-                                                     
&rmc->refresh_session.amount_with_fee,
-                                                     &coin_residual);
+                                                      
&rmc->refresh_session.coin.coin_pub,
+                                                      coin_value,
+                                                      tl,
+                                                      
&rmc->refresh_session.amount_with_fee,
+                                                      &coin_residual);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
     return GNUNET_DB_STATUS_HARD_ERROR;
@@ -245,9 +277,9 @@ refresh_check_melt (struct MHD_Connection *connection,
  */
 static enum GNUNET_DB_QueryStatus
 refresh_melt_transaction (void *cls,
-                         struct MHD_Connection *connection,
-                         struct TALER_EXCHANGEDB_Session *session,
-                         int *mhd_ret)
+                          struct MHD_Connection *connection,
+                          struct TALER_EXCHANGEDB_Session *session,
+                          int *mhd_ret)
 {
   struct RefreshMeltContext *rmc = cls;
   enum GNUNET_DB_QueryStatus qs;
@@ -262,8 +294,8 @@ refresh_melt_transaction (void *cls,
   {
     TALER_LOG_DEBUG ("Found already-melted coin\n");
     *mhd_ret = reply_refresh_melt_success (connection,
-                                          &rmc->refresh_session.rc,
-                                          noreveal_index);
+                                           &rmc->refresh_session.rc,
+                                           noreveal_index);
     /* Note: we return "hard error" to ensure the wrapper
        does not retry the transaction, and to also not generate
        a "fresh" response (as we would on "success") */
@@ -273,22 +305,22 @@ refresh_melt_transaction (void *cls,
   {
     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
       *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
-                                                      
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
+                                                       
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
     return qs;
   }
 
   /* check coin has enough funds remaining on it to cover melt cost */
   qs = refresh_check_melt (connection,
-                          session,
-                          rmc,
-                          mhd_ret);
+                           session,
+                           rmc,
+                           mhd_ret);
   if (0 > qs)
     return qs;
 
   /* pick challenge and persist it */
   rmc->refresh_session.noreveal_index
     = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
-                               TALER_CNC_KAPPA);
+                                TALER_CNC_KAPPA);
 
   if (0 >=
       (qs = TEH_plugin->insert_melt (TEH_plugin->cls,
@@ -298,7 +330,7 @@ refresh_melt_transaction (void *cls,
     if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
     {
       *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
-                                                      
TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR);
+                                                       
TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR);
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
     return qs;
@@ -327,9 +359,9 @@ handle_refresh_melt (struct MHD_Connection *connection,
     struct TALER_Amount fee_refresh;
 
     TALER_amount_ntoh (&fee_refresh,
-                      &rmc->dki->issue.properties.fee_refresh);
+                       &rmc->dki->issue.properties.fee_refresh);
     if (TALER_amount_cmp (&fee_refresh,
-                         &rmc->refresh_session.amount_with_fee) > 0)
+                          &rmc->refresh_session.amount_with_fee) > 0)
     {
       GNUNET_break_op (0);
       return TEH_RESPONSE_reply_external_error (connection,
@@ -358,8 +390,8 @@ handle_refresh_melt (struct MHD_Connection *connection,
     {
       GNUNET_break_op (0);
       return TEH_RESPONSE_reply_signature_invalid (connection,
-                                                  
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
-                                                  "confirm_sig");
+                                                   
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
+                                                   "confirm_sig");
     }
   }
 
@@ -505,9 +537,8 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler 
*rh,
                                                   TEH_KS_DKU_ZOMBIE);
     if (NULL != dki)
     {
-      /* Test if zombie-condition is actually satisfied for the coin */
-      if (0 /* FIXME: test if zombie-satisfied */)
-        rmc.dki = dki;
+      rmc.dki = dki;
+      rmc.zombie_required = GNUNET_YES;
     }
   }
 
diff --git a/src/exchange/taler-exchange-httpd_refund.c 
b/src/exchange/taler-exchange-httpd_refund.c
index 69b5cae9..5fea37da 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -165,7 +165,7 @@ refund_transaction (void *cls,
                                           session,
                                           &refund->coin.coin_pub,
                                           GNUNET_NO,
-                                         &tl);
+                                          &tl);
   if (0 > qs)
   {
     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 3cf3e781..f05e4260 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -393,7 +393,7 @@ TEH_RESPONSE_reply_external_error (struct MHD_Connection 
*connection,
  */
 int
 TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection,
-                                enum TALER_ErrorCode ec)
+                                 enum TALER_ErrorCode ec)
 {
   return TEH_RESPONSE_reply_json_pack (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index b308f774..c95ed261 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -266,7 +266,7 @@ postgres_create_tables (void *cls)
        (as they really must be unique). */
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS reserves_out"
                             "(reserve_out_serial_id BIGSERIAL UNIQUE"
-                            ",h_blind_ev BYTEA PRIMARY KEY"
+                            ",h_blind_ev BYTEA PRIMARY KEY CHECK 
(LENGTH(h_blind_ev)=64)"
                             ",denom_pub_hash BYTEA NOT NULL REFERENCES 
denominations (denom_pub_hash)" /* do NOT CASCADE on DELETE, we may keep the 
denomination key alive! */
                             ",denom_sig BYTEA NOT NULL"
                             ",reserve_pub BYTEA NOT NULL REFERENCES reserves 
(reserve_pub) ON DELETE CASCADE"
@@ -319,8 +319,10 @@ postgres_create_tables (void *cls)
                            ",link_sig BYTEA NOT NULL 
CHECK(LENGTH(link_sig)=64)"
                            ",denom_pub_hash BYTEA NOT NULL REFERENCES 
denominations (denom_pub_hash) ON DELETE CASCADE"
                            ",coin_ev BYTEA UNIQUE NOT NULL"
+                           ",h_coin_ev BYTEA NOT NULL 
CHECK(LENGTH(h_coin_ev)=64)"
                            ",ev_sig BYTEA NOT NULL"
                            ",PRIMARY KEY (rc, newcoin_index)"
+                           ",UNIQUE (h_coin_ev)"
                            ");"),
     GNUNET_PQ_make_try_execute ("CREATE INDEX 
refresh_revealed_coins_coin_pub_index ON "
                                 "refresh_revealed_coins (denom_pub_hash);"),
@@ -460,7 +462,7 @@ postgres_create_tables (void *cls)
                            ",amount_frac INT4 NOT NULL"
                            ",amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
                            ",timestamp INT8 NOT NULL"
-                           ",h_blind_ev BYTEA NOT NULL REFERENCES 
refresh_revealed_coins (coin_ev) ON DELETE CASCADE"
+                           ",h_blind_ev BYTEA NOT NULL REFERENCES 
refresh_revealed_coins (h_coin_ev) ON DELETE CASCADE"
                            ");"),
     GNUNET_PQ_make_try_execute("CREATE INDEX payback_refresh_by_coin_index "
                                "ON payback_refresh(coin_pub);"),
@@ -977,10 +979,11 @@ postgres_prepare (PGconn *db_conn)
                             ",link_sig "
                             ",denom_pub_hash "
                             ",coin_ev"
+                            ",h_coin_ev"
                             ",ev_sig"
                             ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
+                            "($1, $2, $3, $4, $5, $6, $7);",
+                            7),
     /* Obtain information about the coins created in a refresh
        operation, used in #postgres_get_refresh_reveal() */
     GNUNET_PQ_make_prepare ("get_refresh_revealed_coins",
@@ -1657,23 +1660,24 @@ postgres_prepare (PGconn *db_conn)
        affecting old coins of refreshed coins */
     GNUNET_PQ_make_prepare ("payback_by_old_coin",
                             "SELECT"
-                            " pr.coin_pub"
-                            ",pr.coin_sig"
-                            ",pr.coin_blind"
-                            ",pr.amount_val"
-                            ",pr.amount_frac"
-                            ",pr.amount_curr"
-                            ",pr.timestamp"
+                            " coin_pub"
+                            ",coin_sig"
+                            ",coin_blind"
+                            ",amount_val"
+                            ",amount_frac"
+                            ",amount_curr"
+                            ",timestamp"
                             ",coins.denom_pub_hash"
                             ",coins.denom_sig"
-                            " FROM refresh_commitments"
-                            "    JOIN refresh_revealed_coins rrc"
-                            "      USING (rc)"
-                            "    JOIN payback_refresh pr"
-                            "      ON (rrc.coin_ev = pr.h_blind_ev)"
+                            " FROM payback_refresh"
                             "    JOIN known_coins coins"
-                            "      ON (coins.coin_pub = pr.coin_pub)"
-                            " WHERE old_coin_pub=$1"
+                            "      USING (coin_pub)"
+                            " WHERE h_blind_ev IN"
+                            "   (SELECT rrc.h_coin_ev"
+                            "    FROM refresh_commitments"
+                            "       JOIN refresh_revealed_coins rrc"
+                            "           USING (rc)"
+                            "    WHERE old_coin_pub=$1)"
                             " FOR UPDATE;",
                             1),
     /* Used in #postgres_get_reserve_history() */
@@ -1768,7 +1772,7 @@ postgres_prepare (PGconn *db_conn)
                             " FROM refresh_revealed_coins"
                             "   JOIN refresh_commitments rcom"
                             "      USING (rc)"
-                            " WHERE coin_ev=$1"
+                            " WHERE h_coin_ev=$1"
                             " LIMIT 1"
                             " FOR UPDATE;",
                             1),
@@ -3921,6 +3925,7 @@ postgres_insert_refresh_reveal (void *cls,
   {
     const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
     struct GNUNET_HashCode denom_pub_hash;
+    struct GNUNET_HashCode h_coin_ev;
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (rc),
       GNUNET_PQ_query_param_uint32 (&i),
@@ -3928,6 +3933,7 @@ postgres_insert_refresh_reveal (void *cls,
       GNUNET_PQ_query_param_auto_from_type (&denom_pub_hash),
       GNUNET_PQ_query_param_fixed_size (rrc->coin_ev,
                                         rrc->coin_ev_size),
+      GNUNET_PQ_query_param_auto_from_type (&h_coin_ev),
       GNUNET_PQ_query_param_rsa_signature (rrc->coin_sig.rsa_signature),
       GNUNET_PQ_query_param_end
     };
@@ -3935,7 +3941,9 @@ postgres_insert_refresh_reveal (void *cls,
 
     GNUNET_CRYPTO_rsa_public_key_hash (rrc->denom_pub.rsa_public_key,
                                        &denom_pub_hash);
-
+    GNUNET_CRYPTO_hash (rrc->coin_ev,
+                        rrc->coin_ev_size,
+                        &h_coin_ev);
     qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
                                              "insert_refresh_revealed_coin",
                                              params);
@@ -4813,9 +4821,6 @@ postgres_get_coin_transactions (void *cls,
     /** #TALER_EXCHANGEDB_TT_REFUND */
     { "get_refunds_by_coin",
       &add_coin_refund },
-    /** #TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK */
-    { "payback_by_old_coin",
-      &add_old_coin_payback },
     { NULL, NULL }
   };
   static const struct Work work_wp[] = {
diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h
index 5767a73b..cd99a40f 100644
--- a/src/include/taler_error_codes.h
+++ b/src/include/taler_error_codes.h
@@ -523,6 +523,12 @@ enum TALER_ErrorCode
    */
   TALER_EC_REFRESH_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS = 1308,
 
+  /**
+   * The denomination of the given coin has past its expiration date and it is
+   * also not a valid zombie (that is, was not refreshed with the fresh coin
+   * being subjected to payback).
+   */
+  TALER_EC_REFRESH_MELT_COIN_EXPIRED_NO_ZOMBIE = 1309,
 
   /**
    * The provided transfer keys do not match up with the
@@ -624,7 +630,7 @@ enum TALER_ErrorCode
    */
   TALER_EC_REFRESH_REVEAL_LINK_SIGNATURE_INVALID = 1362,
 
-  
+
   /**
    * The coin specified in the link request is unknown to the exchange.
    * This response is provided with HTTP status code
diff --git a/src/lib/test_exchange_api_revocation.c 
b/src/lib/test_exchange_api_revocation.c
index 090b38b2..bd1d91c6 100644
--- a/src/lib/test_exchange_api_revocation.c
+++ b/src/lib/test_exchange_api_revocation.c
@@ -159,16 +159,27 @@ run (void *cls,
                               "refresh-melt-1",
                               CONFIG_FILE),
     /* Refund coin to original coin */
-    TALER_TESTING_cmd_payback ("payback-1",
+    TALER_TESTING_cmd_payback ("payback-1a",
                                MHD_HTTP_OK,
-                               "refresh-reveal-1",
-                               "EUR:5",
+                               "refresh-reveal-1#0",
+                               "EUR:1",
                                "refresh-melt-1"),
-    /**
-     * Melt original coin AGAIN
-     * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
+    TALER_TESTING_cmd_payback ("payback-1b",
+                               MHD_HTTP_OK,
+                               "refresh-reveal-1#1",
+                               "EUR:1",
+                               "refresh-melt-1"),
+    TALER_TESTING_cmd_payback ("payback-1c",
+                               MHD_HTTP_OK,
+                               "refresh-reveal-1#2",
+                               "EUR:1",
+                               "refresh-melt-1"),
+    /* Melt original coin AGAIN (FIXME: this command
+       is simply WRONG as it neither matches
+       the EUR:3 that were paid back NOR is melt_double
+       precisely right here!) -- it always tries to MELT EUR:4, which is too 
much! */
     TALER_TESTING_cmd_refresh_melt_double
-      ("refresh-melt-2", "EUR:4",
+      ("refresh-melt-2", "EUR:3",
        "withdraw-coin-1", MHD_HTTP_OK),
     /**
      * Complete (successful) melt operation, and withdraw the coins
@@ -190,18 +201,18 @@ run (void *cls,
     TALER_TESTING_cmd_payback ("payback-2",
                                MHD_HTTP_OK,
                                "refresh-melt-2",
-                               "EUR:5",
+                               "EUR:1",
                                "refresh-melt-2"),
     /* Refund original coin to reserve */
     TALER_TESTING_cmd_payback ("payback-3",
                                MHD_HTTP_OK,
                                "withdraw-coin-1",
-                               "EUR:5",
+                               "EUR:1",
                                NULL),
     /* Check the money is back with the reserve */
     TALER_TESTING_cmd_status ("payback-reserve-status-1",
                               "create-reserve-1",
-                              "EUR:4.0",
+                              "EUR:1.0",
                               MHD_HTTP_OK),
     TALER_TESTING_cmd_end ()
   };
diff --git a/src/lib/testing_api_cmd_payback.c 
b/src/lib/testing_api_cmd_payback.c
index c7ea5091..de394fe2 100644
--- a/src/lib/testing_api_cmd_payback.c
+++ b/src/lib/testing_api_cmd_payback.c
@@ -107,6 +107,51 @@ struct PaybackState
 
 };
 
+
+/**
+ * Parser reference to a coin.
+ *
+ * @param coin_reference of format $LABEL['#' $INDEX]?
+ * @param cref[out] where we return a copy of $LABEL
+ * @param idx[out] where we set $INDEX
+ * @return #GNUNET_SYSERR if $INDEX is present but not numeric
+ */
+static int
+parse_coin_reference (const char *coin_reference,
+                      char **cref,
+                      unsigned int *idx)
+{
+  const char *index;
+
+  /* We allow command references of the form "$LABEL#$INDEX" or
+     just "$LABEL", which implies the index is 0. Figure out
+     which one it is. */
+  index = strchr (coin_reference, '#');
+  if (NULL == index)
+  {
+    *idx = 0;
+    *cref = GNUNET_strdup (coin_reference);
+    return GNUNET_OK;
+  }
+  *cref = GNUNET_strndup (coin_reference,
+                          index - coin_reference);
+  if (1 != sscanf (index + 1,
+                   "%u",
+                   idx))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Numeric index (not `%s') required after `#' in command 
reference of command in %s:%u\n",
+                index,
+                __FILE__,
+                __LINE__);
+    GNUNET_free (*cref);
+    *cref = NULL;
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
 /**
  * Check the result of the payback request: checks whether
  * the HTTP response code is good, and that the coin that
@@ -137,7 +182,6 @@ payback_cb (void *cls,
   struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
   const struct TALER_TESTING_Command *reserve_cmd;
   char *cref;
-  const char *index;
   unsigned int idx;
 
   ps->ph = NULL;
@@ -155,34 +199,15 @@ payback_cb (void *cls,
     return;
   }
 
-  /* We allow command references of the form "$LABEL#$INDEX" or
-     just "$LABEL", which implies the index is 0. Figure out
-     which one it is. */
-  index = strchr (ps->coin_reference, '#');
-  if (NULL == index)
+  if (GNUNET_OK !=
+      parse_coin_reference (ps->coin_reference,
+                            &cref,
+                            &idx))
   {
-    idx = 0;
-    cref = GNUNET_strdup (ps->coin_reference);
-  }
-  else
-  {
-    cref = GNUNET_strndup (ps->coin_reference,
-                           index - ps->coin_reference);
-    if (1 != sscanf (index,
-                     "%u",
-                     &idx))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Numeric index (not `%s') required after `#' in command 
reference of command %s in %s:%u\n",
-                  index,
-                  cmd->label,
-                  __FILE__,
-                  __LINE__);
-      TALER_TESTING_interpreter_fail (is);
-      GNUNET_free (cref);
-      return;
-    }
+    TALER_TESTING_interpreter_fail (is);
+    return;
   }
+
   reserve_cmd = TALER_TESTING_interpreter_lookup_command
     (is, cref);
   GNUNET_free (cref);
@@ -309,10 +334,22 @@ payback_run (void *cls,
   const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
   const struct TALER_DenominationSignature *coin_sig;
   struct TALER_PlanchetSecretsP planchet;
+  char *cref;
+  unsigned int idx;
 
   ps->is = is;
+  if (GNUNET_OK !=
+      parse_coin_reference (ps->coin_reference,
+                            &cref,
+                            &idx))
+  {
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+
   coin_cmd = TALER_TESTING_interpreter_lookup_command
-    (is, ps->coin_reference);
+    (is, cref);
+  GNUNET_free (cref);
 
   if (NULL == coin_cmd)
   {
@@ -322,7 +359,7 @@ payback_run (void *cls,
   }
 
   if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
-    (coin_cmd, 0, &coin_priv))
+    (coin_cmd, idx, &coin_priv))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
@@ -330,7 +367,7 @@ payback_run (void *cls,
   }
 
   if (GNUNET_OK != TALER_TESTING_get_trait_blinding_key
-    (coin_cmd, 0, &blinding_key))
+    (coin_cmd, idx, &blinding_key))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
@@ -340,7 +377,7 @@ payback_run (void *cls,
   planchet.blinding_key = *blinding_key;
 
   if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
-    (coin_cmd, 0, &denom_pub))
+    (coin_cmd, idx, &denom_pub))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
@@ -348,7 +385,7 @@ payback_run (void *cls,
   }
 
   if (GNUNET_OK != TALER_TESTING_get_trait_denom_sig
-     (coin_cmd, 0, &coin_sig))
+     (coin_cmd, idx, &coin_sig))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);

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



reply via email to

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