gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] 02/02: [age-withdraw] first tests pass


From: gnunet
Subject: [taler-exchange] 02/02: [age-withdraw] first tests pass
Date: Mon, 24 Jul 2023 20:30:35 +0200

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

oec pushed a commit to branch master
in repository exchange.

commit 3e29bdfb8bfda133b7c25a36160a3533e836e0b8
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Mon Jul 24 20:23:42 2023 +0200

    [age-withdraw] first tests pass
    
    age-withdraw successfully tested (no reveal yet):
    
    1. reserve filled with amount large enough to trigger kyc
    2. kyc oauth2 test daemon sets birthday to 2015-00-00
    3. usual withdraw fails with CONFLICT and AGE_RESTRICTION_REQUIRED
    4. age-withdraw with loo large of an maximum age fails
    5. age-withdraw with appropriate maximum age succeeds
---
 src/exchange/taler-exchange-httpd_age-withdraw.c | 178 ++++++++++++-----------
 src/exchangedb/exchange_do_age_withdraw.sql      |  34 ++---
 src/exchangedb/pg_do_age_withdraw.c              |  12 +-
 src/exchangedb/pg_do_age_withdraw.h              |   2 +
 src/include/taler_exchange_service.h             |   2 +
 src/include/taler_exchangedb_plugin.h            |   2 +
 src/include/taler_testing_lib.h                  |  36 +++++
 src/lib/exchange_api_age_withdraw.c              |  49 ++++++-
 src/testing/test_exchange_api_age_restriction.c  |  12 ++
 src/testing/testing_api_cmd_age_withdraw.c       |  23 ++-
 src/util/age_restriction.c                       |   8 +-
 11 files changed, 222 insertions(+), 136 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_age-withdraw.c 
b/src/exchange/taler-exchange-httpd_age-withdraw.c
index 106feb01..60bc5fec 100644
--- a/src/exchange/taler-exchange-httpd_age-withdraw.c
+++ b/src/exchange/taler-exchange-httpd_age-withdraw.c
@@ -113,7 +113,7 @@ free_age_withdraw_context_resources (struct 
AgeWithdrawContext *awc)
 static enum GNUNET_GenericReturnValue
 parse_age_withdraw_json (
   struct MHD_Connection *connection,
-  const json_t *j_denoms_h,
+  const json_t *j_denom_hs,
   const json_t *j_blinded_coin_evs,
   struct AgeWithdrawContext *awc,
   MHD_RESULT *mhd_ret)
@@ -135,9 +135,9 @@ parse_age_withdraw_json (
 
   /* Verify JSON-structure consistency */
   {
-    uint32_t num_coins = json_array_size (j_denoms_h);
+    uint32_t num_coins = json_array_size (j_denom_hs);
 
-    if (! json_is_array (j_denoms_h))
+    if (! json_is_array (j_denom_hs))
       error = "denoms_h must be an array";
     else if (! json_is_array (j_blinded_coin_evs))
       error = "coin_evs must be an array";
@@ -168,7 +168,7 @@ parse_age_withdraw_json (
   awc->denom_hs = GNUNET_new_array (awc->num_coins,
                                     struct TALER_DenominationHashP);
 
-  json_array_foreach (j_denoms_h, idx, value) {
+  json_array_foreach (j_denom_hs, idx, value) {
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_fixed_auto (NULL, &awc->denom_hs[idx]),
       GNUNET_JSON_spec_end ()
@@ -196,24 +196,17 @@ parse_age_withdraw_json (
 
   /* Parse blinded envelopes. */
   json_array_foreach (j_blinded_coin_evs, idx, value) {
-    const json_t *j_kappa_coin_evs;
-    struct GNUNET_JSON_Specification aspec[] = {
-      GNUNET_JSON_spec_array_const (NULL, &j_kappa_coin_evs),
-      GNUNET_JSON_spec_end ()
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (value, aspec, NULL, NULL))
+    const json_t *j_kappa_coin_evs = value;
+    if (! json_is_array (j_kappa_coin_evs))
     {
       GNUNET_snprintf (buf,
                        sizeof(buf),
-                       "couldn't parse entry no. %d in array coin_evs",
+                       "enxtry %d in array blinded_coin_evs is not an array",
                        idx + 1);
       error = buf;
       goto EXIT;
     }
-
-    if (TALER_CNC_KAPPA != json_array_size (j_kappa_coin_evs))
+    else if (TALER_CNC_KAPPA != json_array_size (j_kappa_coin_evs))
     {
       GNUNET_snprintf (buf,
                        sizeof(buf),
@@ -223,28 +216,47 @@ parse_age_withdraw_json (
       goto EXIT;
     }
 
-    /* Now parse the individual kappa envelopes */
+    /* Now parse the individual kappa envelopes and calculate the hash of
+     * the commitment along the way. */
     {
       size_t off = idx * TALER_CNC_KAPPA;
-      size_t kappa = 0;
+      unsigned int kappa = 0;
+      enum GNUNET_GenericReturnValue ret;
+      struct GNUNET_HashContext *hash_context;
+
+      hash_context = GNUNET_CRYPTO_hash_context_start ();
 
       json_array_foreach (j_kappa_coin_evs, kappa, value) {
         struct GNUNET_JSON_Specification spec[] = {
-          GNUNET_JSON_spec_fixed_auto (NULL, &awc->coin_evs[off + kappa]),
+          TALER_JSON_spec_blinded_planchet (NULL, &awc->coin_evs[off + kappa]),
           GNUNET_JSON_spec_end ()
         };
-
         if (GNUNET_OK !=
             GNUNET_JSON_parse (value, spec, NULL, NULL))
         {
           GNUNET_snprintf (buf,
                            sizeof(buf),
-                           "couldn't parse array no. %d in coin_evs",
+                           "couldn't parse array no. %d in 
blinded_coin_evs[%d]",
+                           kappa + 1,
                            idx + 1);
           error = buf;
           goto EXIT;
         }
 
+        /* Continue to hash of the coin candidates */
+        {
+          struct TALER_BlindedCoinHashP bch;
+          ret = TALER_coin_ev_hash (&awc->coin_evs[off + kappa],
+                                    &awc->denom_hs[idx],
+                                    &bch);
+
+          GNUNET_assert (GNUNET_OK == ret);
+
+          GNUNET_CRYPTO_hash_context_read (hash_context,
+                                           &bch,
+                                           sizeof(bch));
+        }
+
         /* Check for duplicate planchets
          * FIXME: is this needed?
          */
@@ -258,39 +270,15 @@ parse_age_withdraw_json (
           }
         }
       }
+
+      /* Finally, calculate the h_commitment from all blinded envelopes */
+      GNUNET_CRYPTO_hash_context_finish (hash_context,
+                                         &awc->commitment.h_commitment.hash);
     }
   }; /* json_array_foreach over j_blinded_coin_evs */
 
-  /* We successfully parsed denoms_h and blinded_coins_evs */
   GNUNET_assert (NULL == error);
 
-  /* Finally, calculate the h_commitment from all blinded envelopes */
-  {
-    enum GNUNET_GenericReturnValue ret;
-    struct GNUNET_HashContext *hash_context;
-
-    hash_context = GNUNET_CRYPTO_hash_context_start ();
-
-    for (size_t c = 0;
-         c < TALER_CNC_KAPPA * awc->num_coins;
-         c++)
-    {
-      struct TALER_BlindedCoinHashP bch;
-
-      ret = TALER_coin_ev_hash (&awc->coin_evs[c],
-                                &awc->denom_hs[c],
-                                &bch);
-
-      GNUNET_assert (GNUNET_OK == ret);
-      GNUNET_CRYPTO_hash_context_read (hash_context,
-                                       &bch,
-                                       sizeof(bch));
-    }
-
-    GNUNET_CRYPTO_hash_context_finish (hash_context,
-                                       &awc->commitment.h_commitment.hash);
-  }
-
 
 EXIT:
   if (NULL != error)
@@ -513,7 +501,6 @@ verify_reserve_signature (
   const struct TALER_EXCHANGEDB_AgeWithdraw *commitment,
   enum MHD_Result *mhd_ret)
 {
-
   TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
   if (GNUNET_OK !=
       TALER_wallet_age_withdraw_verify (&commitment->h_commitment,
@@ -741,6 +728,7 @@ age_withdraw_transaction (void *cls,
     bool age_ok = false;
     bool conflict = false;
     uint16_t allowed_maximum_age = 0;
+    uint32_t reserve_birthday = 0;
 
     qs = TEH_plugin->do_age_withdraw (TEH_plugin->cls,
                                       &awc->commitment,
@@ -749,7 +737,29 @@ age_withdraw_transaction (void *cls,
                                       &balance_ok,
                                       &age_ok,
                                       &allowed_maximum_age,
+                                      &reserve_birthday,
                                       &conflict);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "XXXXXXX got from do_age_withdraw:"
+                "\n\tqs: %d"
+                "\n\tcommitment: %s"
+                "\n\tmax_age: %d"
+                "\n\tfound: %d"
+                "\n\tbalance_ok: %d"
+                "\n\tage_ok: %d"
+                "\n\tallowed_maximum_age: %d"
+                "\n\treserve_birthday: %d"
+                "\n\tconflict: %d\n",
+                qs,
+                GNUNET_h2s (&awc->commitment.h_commitment.hash),
+                awc->commitment.max_age,
+                found,
+                balance_ok,
+                age_ok,
+                allowed_maximum_age,
+                reserve_birthday,
+                conflict);
+
     if (0 > qs)
     {
       if (GNUNET_DB_STATUS_HARD_ERROR == qs)
@@ -765,18 +775,6 @@ age_withdraw_transaction (void *cls,
                                           NULL);
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
-    else if (! balance_ok)
-    {
-      TEH_plugin->rollback (TEH_plugin->cls);
-
-      *mhd_ret = TEH_RESPONSE_reply_reserve_insufficient_balance (
-        connection,
-        TALER_EC_EXCHANGE_AGE_WITHDRAW_INSUFFICIENT_FUNDS,
-        &awc->commitment.amount_with_fee,
-        &awc->commitment.reserve_pub);
-
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
     else if (! age_ok)
     {
       enum TALER_ErrorCode ec =
@@ -785,10 +783,24 @@ age_withdraw_transaction (void *cls,
       *mhd_ret =
         TALER_MHD_REPLY_JSON_PACK (
           connection,
-          TALER_ErrorCode_get_http_status_safe (ec),
+          MHD_HTTP_CONFLICT,
           TALER_MHD_PACK_EC (ec),
           GNUNET_JSON_pack_uint64 ("allowed_maximum_age",
-                                   allowed_maximum_age));
+                                   allowed_maximum_age),
+          GNUNET_JSON_pack_uint64 ("reserve_birthday",
+                                   reserve_birthday));
+
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    else if (! balance_ok)
+    {
+      TEH_plugin->rollback (TEH_plugin->cls);
+
+      *mhd_ret = TEH_RESPONSE_reply_reserve_insufficient_balance (
+        connection,
+        TALER_EC_EXCHANGE_AGE_WITHDRAW_INSUFFICIENT_FUNDS,
+        &awc->commitment.amount_with_fee,
+        &awc->commitment.reserve_pub);
 
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
@@ -802,6 +814,7 @@ age_withdraw_transaction (void *cls,
       GNUNET_assert (ok);
       return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     }
+    *mhd_ret = -1;
   }
 
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
@@ -842,10 +855,11 @@ sign_and_do_age_withdraw (
   awc->now = GNUNET_TIME_timestamp_get ();
 
   /* Pick the challenge */
-  awc->commitment.noreveal_index =
-    noreveal_index =
-      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
-                                TALER_CNC_KAPPA);
+  noreveal_index =
+    GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
+                              TALER_CNC_KAPPA);
+
+  awc->commitment.noreveal_index = noreveal_index;
 
   /* Choose and sign the coins */
   {
@@ -893,21 +907,11 @@ sign_and_do_age_withdraw (
                                 result,
                                 &age_withdraw_transaction,
                                 awc);
-
-  if (GNUNET_OK != ret)
-  {
-    GNUNET_break (0);
-    *result = TALER_MHD_reply_with_error (connection,
-                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                          
TALER_EC_GENERIC_UNEXPECTED_REQUEST_ERROR,
-                                          NULL);
-  }
-
   /* Free resources */
-  awc->commitment.h_coin_evs = NULL;
-  awc->commitment.denom_sigs = NULL;
   for (unsigned int i = 0; i<awc->num_coins; i++)
     TALER_blinded_denom_sig_free (&denom_sigs[i]);
+  awc->commitment.h_coin_evs = NULL;
+  awc->commitment.denom_sigs = NULL;
   return ret;
 }
 
@@ -918,14 +922,14 @@ TEH_handler_age_withdraw (struct TEH_RequestContext *rc,
                           const json_t *root)
 {
   MHD_RESULT mhd_ret;
-  const json_t *j_denoms_h;
-  const json_t *j_blinded_coins_evs;
+  const json_t *j_denom_hs;
+  const json_t *j_blinded_coin_evs;
   struct AgeWithdrawContext awc = {0};
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_array_const ("denoms_h",
-                                  &j_denoms_h),
-    GNUNET_JSON_spec_array_const ("blinded_coins_evs",
-                                  &j_blinded_coins_evs),
+    GNUNET_JSON_spec_array_const ("denom_hs",
+                                  &j_denom_hs),
+    GNUNET_JSON_spec_array_const ("blinded_coin_evs",
+                                  &j_blinded_coin_evs),
     GNUNET_JSON_spec_uint16 ("max_age",
                              &awc.commitment.max_age),
     GNUNET_JSON_spec_fixed_auto ("reserve_sig",
@@ -957,8 +961,8 @@ TEH_handler_age_withdraw (struct TEH_RequestContext *rc,
     /* Parse denoms_h and blinded_coins_evs, partially fill awc */
     if (GNUNET_OK !=
         parse_age_withdraw_json (rc->connection,
-                                 j_denoms_h,
-                                 j_blinded_coins_evs,
+                                 j_denom_hs,
+                                 j_blinded_coin_evs,
                                  &awc,
                                  &mhd_ret))
       break;
diff --git a/src/exchangedb/exchange_do_age_withdraw.sql 
b/src/exchangedb/exchange_do_age_withdraw.sql
index d6ae118a..2230d4bf 100644
--- a/src/exchangedb/exchange_do_age_withdraw.sql
+++ b/src/exchangedb/exchange_do_age_withdraw.sql
@@ -32,6 +32,7 @@ CREATE OR REPLACE FUNCTION exchange_do_age_withdraw(
   OUT balance_ok BOOLEAN,
   OUT age_ok BOOLEAN,
   OUT required_age INT2, -- in years ϵ [0,1..)
+  OUT reserve_birthday INT4,
   OUT conflict BOOLEAN)
 LANGUAGE plpgsql
 AS $$
@@ -39,7 +40,6 @@ DECLARE
   reserve_gc INT8;
   reserve_val INT8;
   reserve_frac INT4;
-  reserve_birthday INT4;
   not_before date;
   earliest_date date;
 BEGIN
@@ -64,23 +64,20 @@ SELECT
 
 IF NOT FOUND
 THEN
-  -- reserve unknown
   reserve_found=FALSE;
-  balance_ok=FALSE;
-  age_ok=FALSE;
-  required_age=0;
+  age_ok = FALSE;
+  required_age=-1;
   conflict=FALSE;
+  balance_ok=FALSE;
   RETURN;
 END IF;
 
+reserve_found = TRUE;
+conflict=FALSE;  -- not really yet determined
 
 -- Check age requirements
-IF ((maximum_age_committed = 0) OR (reserve_birthday = 0))
+IF (reserve_birthday <> 0)
 THEN
-  -- No commitment to a non-zero age was provided or the reserve is marked as
-  -- having no age restriction. We can simply pass.
-  age_ok = OK;
-ELSE 
   not_before=date '1970-01-01' + reserve_birthday;
   earliest_date = current_date - make_interval(maximum_age_committed);
   --
@@ -95,14 +92,18 @@ ELSE
   --
   IF (earliest_date < not_before)
   THEN
-    reserve_found = TRUE;
-    balance_ok = FALSE;
+    required_age = extract(year from age(current_date, not_before));
     age_ok = FALSE;
-    required_age = extract(year from age(not_before, current_date)) + 1;
+    balance_ok=TRUE; -- NOT REALLY
     RETURN;
   END IF;
 END IF;
 
+age_ok = TRUE;
+required_age=0;
+
+
+
 -- Check reserve balance is sufficient.
 IF (reserve_val > amount_val)
 THEN
@@ -125,6 +126,8 @@ ELSE
   END IF;
 END IF;
 
+balance_ok=TRUE;
+
 -- Calculate new expiration dates.
 min_reserve_gc=GREATEST(min_reserve_gc,reserve_gc);
 
@@ -136,9 +139,6 @@ UPDATE reserves SET
 WHERE
   reserves.reserve_pub=rpub;
 
-reserve_found=TRUE;
-balance_ok=TRUE;
-
 -- Write the commitment into the age-withdraw table
 INSERT INTO exchange.age_withdraw
   (h_commitment
@@ -146,7 +146,7 @@ INSERT INTO exchange.age_withdraw
   ,reserve_pub
   ,reserve_sig
   ,noreveal_index
-  ,denomination_serials
+  ,denom_serials
   ,h_blind_evs
   ,denom_sigs)
 VALUES
diff --git a/src/exchangedb/pg_do_age_withdraw.c 
b/src/exchangedb/pg_do_age_withdraw.c
index 8a93ef8d..c79b2b3d 100644
--- a/src/exchangedb/pg_do_age_withdraw.c
+++ b/src/exchangedb/pg_do_age_withdraw.c
@@ -38,8 +38,8 @@ TEH_PG_do_age_withdraw (
   bool *balance_ok,
   bool *age_ok,
   uint16_t *required_age,
-  bool *conflict,
-  uint64_t *ruuid)
+  uint32_t *reserve_birthday,
+  bool *conflict)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_TIME_Timestamp gc;
@@ -72,10 +72,10 @@ TEH_PG_do_age_withdraw (
                                 age_ok),
     GNUNET_PQ_result_spec_uint16 ("required_age",
                                   required_age),
+    GNUNET_PQ_result_spec_uint32 ("reserve_birthday",
+                                  reserve_birthday),
     GNUNET_PQ_result_spec_bool ("conflict",
                                 conflict),
-    GNUNET_PQ_result_spec_uint64 ("ruuid",
-                                  ruuid),
     GNUNET_PQ_result_spec_end
   };
 
@@ -93,9 +93,9 @@ TEH_PG_do_age_withdraw (
            ",balance_ok"
            ",age_ok"
            ",required_age"
+           ",reserve_birthday"
            ",conflict"
-           ",ruuid"
-           " FROM exchange_do_batch_withdraw"
+           " FROM exchange_do_age_withdraw"
            " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                    "call_age_withdraw",
diff --git a/src/exchangedb/pg_do_age_withdraw.h 
b/src/exchangedb/pg_do_age_withdraw.h
index 8f42bfb5..71376022 100644
--- a/src/exchangedb/pg_do_age_withdraw.h
+++ b/src/exchangedb/pg_do_age_withdraw.h
@@ -36,6 +36,7 @@
  * @param[out] balance_ok set to true if the balance was sufficient
  * @param[out] age_ok set to true if no age requirements are present on the 
reserve
  * @param[out] required_age if @e age_ok is false, set to the maximum allowed 
age when withdrawing from this reserve
+ * @param[out] reserve_birthday if @e age_ok is false, set to the birthday of 
the reserve
  * @param[out] conflict set to true if there already is an entry in the 
database for the given pair (h_commitment, reserve_pub)
  * @return query execution status
  */
@@ -48,6 +49,7 @@ TEH_PG_do_age_withdraw (
   bool *balance_ok,
   bool *age_ok,
   uint16_t *required_age,
+  uint32_t *reserve_birthday,
   bool *conflict);
 
 #endif
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index 7bd1b324..e8d78916 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -2966,6 +2966,7 @@ struct TALER_EXCHANGE_AgeWithdrawBlindedHandle;
  * @param curl_ctx The curl context to use
  * @param exchange_url The base-URL of the exchange
  * @param keys The /keys material from the exchange
+ * @param max_age The maximum age that the coins are committed to.
  * @param num_input number of entries in the @a blinded_input array
  * @param blinded_input array of planchet details of the planchet to withdraw
  * @param reserve_priv private key of the reserve to withdraw from
@@ -2981,6 +2982,7 @@ TALER_EXCHANGE_age_withdraw_blinded (
   struct TALER_EXCHANGE_Keys *keys,
   const char *exchange_url,
   const struct TALER_ReservePrivateKeyP *reserve_priv,
+  uint8_t max_age,
   unsigned int num_input,
   const struct TALER_EXCHANGE_AgeWithdrawBlindedInput blinded_input[static
                                                                     num_input],
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index c4b894e2..f5fdd7f1 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -3863,6 +3863,7 @@ struct TALER_EXCHANGEDB_Plugin
    * @param[out] balance_ok set to true if the balance was sufficient
    * @param[out] age_ok set to true if age requirements were met
    * @param[out] allowed_maximum_age if @e age_ok is FALSE, this is set to the 
allowed maximum age
+   * @param[out] reserve_birthday if @e age_ok is FALSE, this is set to the 
reserve's birthday
    * @return query execution status
    */
   enum GNUNET_DB_QueryStatus
@@ -3874,6 +3875,7 @@ struct TALER_EXCHANGEDB_Plugin
     bool *balance_ok,
     bool *age_ok,
     uint16_t *allowed_maximum_age,
+    uint32_t *reserve_birthday,
     bool *conflict);
 
   /**
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index c2893769..a514ad2d 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -1130,6 +1130,42 @@ TALER_TESTING_cmd_batch_withdraw (const char *label,
                                   const char *amount,
                                   ...);
 
+/**
+ * Create an age-withdraw command, letting the caller specify
+ * the maximum agend and desired amounts as string.  Takes a variable,
+ * non-empty list of the denomination amounts via VARARGS, similar to
+ * #TALER_TESTING_cmd_withdraw_amount(), just using a batch withdraw.
+ *
+ * @param label command label.
+ * @param reserve_reference command providing us with a reserve to withdraw 
from
+ * @param max_age maximum allowed age, same for each coin
+ * @param expected_response_code which HTTP response code
+ *        we expect from the exchange.
+ * @param amount how much we withdraw for the first coin
+ * @param ... NULL-terminated list of additional amounts to withdraw (one per 
coin)
+ * @return the withdraw command to be executed by the interpreter.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_age_withdraw (const char *label,
+                                const char *reserve_reference,
+                                uint8_t max_age,
+                                unsigned int expected_response_code,
+                                const char *amount,
+                                ...);
+
+/**
+ * Create a "age-withdraw reveal" command.
+ *
+ * @param label command label.
+ * @param age_withdraw_reference reference to a "age-withdraw" command.
+ * @param expected_response_code expected HTTP response code.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_age_withdraw_reveal (
+  const char *label,
+  const char *age_withdraw_reference,
+  unsigned int expected_response_code);
 
 /**
  * Create a withdraw command, letting the caller specify
diff --git a/src/lib/exchange_api_age_withdraw.c 
b/src/lib/exchange_api_age_withdraw.c
index c68fe67d..bd84dcb3 100644
--- a/src/lib/exchange_api_age_withdraw.c
+++ b/src/lib/exchange_api_age_withdraw.c
@@ -29,12 +29,14 @@
 #include <gnunet/gnunet_curl_lib.h>
 #include <sys/wait.h>
 #include "taler_curl_lib.h"
+#include "taler_error_codes.h"
 #include "taler_json_lib.h"
 #include "taler_exchange_service.h"
 #include "exchange_api_common.h"
 #include "exchange_api_handle.h"
 #include "taler_signatures.h"
 #include "exchange_api_curl_defaults.h"
+#include "taler_util.h"
 
 /**
  * A CoinCandidate is populated from a master secret
@@ -315,12 +317,13 @@ reserve_age_withdraw_ok (
   };
   struct TALER_ExchangeSignatureP exchange_sig;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_uint8 ("noreaveal_index",
+    GNUNET_JSON_spec_uint8 ("noreveal_index",
                             &response.details.ok.noreveal_index),
     GNUNET_JSON_spec_fixed_auto ("exchange_sig",
                                  &exchange_sig),
     GNUNET_JSON_spec_fixed_auto ("exchange_pub",
-                                 &response.details.ok.exchange_pub)
+                                 &response.details.ok.exchange_pub),
+    GNUNET_JSON_spec_end ()
   };
 
   if (GNUNET_OK!=
@@ -538,6 +541,14 @@ handle_reserve_age_withdraw_blinded_finished (
     awbr.hr.hint = TALER_JSON_get_error_hint (j_response);
     break;
   case MHD_HTTP_CONFLICT:
+    /* The age requirements might not have been met */
+    awbr.hr.ec = TALER_JSON_get_error_code (j_response);
+    if (TALER_EC_EXCHANGE_AGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE == awbr.hr.ec)
+    {
+      awbr.hr.hint = TALER_JSON_get_error_hint (j_response);
+      break;
+    }
+
     /* The exchange says that the reserve has insufficient funds;
        check the signatures in the history... */
     if (GNUNET_OK !=
@@ -611,6 +622,9 @@ perform_protocol (
   json_t *j_request_body = NULL;
   CURL *curlh = NULL;
 
+  GNUNET_assert (0 < awbh->num_input);
+  awbh->age_mask = awbh->blinded_input[0].denom_pub->key.age_mask;
+
   FAIL_IF (GNUNET_OK !=
            TALER_amount_set_zero (awbh->keys->currency,
                                   &awbh->amount_with_fee));
@@ -649,12 +663,17 @@ perform_protocol (
   {
     /* Build the denomination array */
     {
-      const struct TALER_EXCHANGE_DenomPublicKey *denom =
+      const struct TALER_EXCHANGE_DenomPublicKey *denom_pub =
         awbh->blinded_input[i].denom_pub;
-      json_t *jdenom = GNUNET_JSON_PACK (
-        TALER_JSON_pack_denom_pub (NULL,
-                                   &denom->key));
+      const struct TALER_DenominationHashP *denom_h = &denom_pub->h_key;
+      json_t *jdenom;
+
+      /* The mask must be the same for all coins */
+      FAIL_IF (awbh->age_mask.bits != denom_pub->key.age_mask.bits);
 
+      jdenom = GNUNET_JSON_PACK (
+        GNUNET_JSON_pack_data_auto (NULL,
+                                    denom_h));
       FAIL_IF (NULL == jdenom);
       FAIL_IF (0 < json_array_append_new (j_denoms,
                                           jdenom));
@@ -686,6 +705,9 @@ perform_protocol (
                                            &bch,
                                            sizeof(bch));
         }
+
+        FAIL_IF (0 < json_array_append_new (j_array_candidates,
+                                            j_can));
       }
     }
   }
@@ -702,9 +724,17 @@ perform_protocol (
                                   awbh->reserve_priv,
                                   &awbh->reserve_sig);
 
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_wallet_age_withdraw_verify (&awbh->h_commitment,
+                                                   &awbh->amount_with_fee,
+                                                   &awbh->age_mask,
+                                                   awbh->max_age,
+                                                   &awbh->reserve_pub,
+                                                   &awbh->reserve_sig));
+
   /* Initiate the POST-request */
   j_request_body = GNUNET_JSON_PACK (
-    GNUNET_JSON_pack_array_steal ("denoms_h", j_denoms),
+    GNUNET_JSON_pack_array_steal ("denom_hs", j_denoms),
     GNUNET_JSON_pack_array_steal ("blinded_coin_evs", j_array_candidates),
     GNUNET_JSON_pack_uint64 ("max_age", awbh->max_age),
     GNUNET_JSON_pack_data_auto ("reserve_sig", &awbh->reserve_sig));
@@ -813,6 +843,7 @@ call_age_withdraw_blinded (
       awh->keys,
       awh->exchange_url,
       awh->reserve_priv,
+      awh->max_age,
       awh->num_coins,
       blinded_input,
       copy_results,
@@ -1064,7 +1095,7 @@ prepare_coins (
               &cd->denom_pub,
               &planchet->blinded_planchet.details.cs_blinded_planchet.nonce,
               &csr_withdraw_done,
-              &cls);
+              cls);
           FAIL_IF (NULL == cls->csr_withdraw_handle);
 
           awh->csr.pending++;
@@ -1163,6 +1194,7 @@ TALER_EXCHANGE_age_withdraw_blinded (
   struct TALER_EXCHANGE_Keys *keys,
   const char *exchange_url,
   const struct TALER_ReservePrivateKeyP *reserve_priv,
+  uint8_t max_age,
   unsigned int num_input,
   const struct TALER_EXCHANGE_AgeWithdrawBlindedInput blinded_input[static
                                                                     num_input],
@@ -1179,6 +1211,7 @@ TALER_EXCHANGE_age_withdraw_blinded (
   awbh->reserve_priv = reserve_priv;
   awbh->callback = res_cb;
   awbh->callback_cls = res_cb_cls;
+  awbh->max_age = max_age;
 
   GNUNET_CRYPTO_eddsa_key_get_public (&awbh->reserve_priv->eddsa_priv,
                                       &awbh->reserve_pub.eddsa_pub);
diff --git a/src/testing/test_exchange_api_age_restriction.c 
b/src/testing/test_exchange_api_age_restriction.c
index 93bd28bf..b3f7357f 100644
--- a/src/testing/test_exchange_api_age_restriction.c
+++ b/src/testing/test_exchange_api_age_restriction.c
@@ -284,6 +284,18 @@ run (void *cls,
                                        "EUR:10",
                                        0, /* age restriction off */
                                        MHD_HTTP_CONFLICT),
+    TALER_TESTING_cmd_age_withdraw ("age-withdraw-coin-1-too-low",
+                                    "create-reserve-kyc-1",
+                                    18, /* Too high */
+                                    MHD_HTTP_CONFLICT,
+                                    "EUR:10",
+                                    NULL),
+    TALER_TESTING_cmd_age_withdraw ("age-withdraw-coin-1",
+                                    "create-reserve-kyc-1",
+                                    8,
+                                    MHD_HTTP_OK,
+                                    "EUR:10",
+                                    NULL),
     TALER_TESTING_cmd_end (),
   };
 
diff --git a/src/testing/testing_api_cmd_age_withdraw.c 
b/src/testing/testing_api_cmd_age_withdraw.c
index ea3249c0..9b7bfd20 100644
--- a/src/testing/testing_api_cmd_age_withdraw.c
+++ b/src/testing/testing_api_cmd_age_withdraw.c
@@ -209,21 +209,15 @@ age_withdraw_cb (
     break;
   case MHD_HTTP_CONFLICT:
     /* TODO[oec]: Add this to the response-type and handle it here */
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Age withdraw test command does not YET support status code 
%u\n",
-                response->hr.http_status);
     break;
   case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
-    /* TODO[oec]: Add this to response-type and handle it here  */
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Age withdraw test command does not YET support status code 
%u\n",
-                response->hr.http_status);
-    break;
   default:
     /* Unsupported status code (by test harness) */
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Age withdraw test command does not support status code %u\n",
-                response->hr.http_status);
+                "test command for age-withdraw not support status code %u, 
body:\n"
+                ">>%s<<\n",
+                response->hr.http_status,
+                json_dumps (response->hr.reply, JSON_INDENT (2)));
     GNUNET_break (0);
     break;
   }
@@ -366,12 +360,13 @@ age_withdraw_cleanup (
     struct TALER_EXCHANGE_AgeWithdrawCoinInput *in = &aws->coin_inputs[n];
     struct CoinOutputState *out = &aws->coin_outputs[n];
 
-    if (NULL != in->denom_pub)
+    if (NULL != in && NULL != in->denom_pub)
     {
       TALER_EXCHANGE_destroy_denomination_key (in->denom_pub);
       in->denom_pub = NULL;
     }
-    TALER_age_commitment_proof_free (&out->details.age_commitment_proof);
+    if (NULL != out)
+      TALER_age_commitment_proof_free (&out->details.age_commitment_proof);
   }
   GNUNET_free (aws->coin_inputs);
   GNUNET_free (aws->coin_outputs);
@@ -490,10 +485,10 @@ TALER_TESTING_cmd_age_withdraw (const char *label,
                   label);
       GNUNET_assert (0);
     }
+    /* move on to next vararg! */
+    amount = va_arg (ap, const char *);
   }
 
-  /* move on to next vararg! */
-  amount = va_arg (ap, const char *);
   GNUNET_assert (NULL == amount);
   va_end (ap);
 
diff --git a/src/util/age_restriction.c b/src/util/age_restriction.c
index eec0c834..d8c6e4da 100644
--- a/src/util/age_restriction.c
+++ b/src/util/age_restriction.c
@@ -32,10 +32,10 @@ GNUNET_CRYPTO_Edx25519PublicKey
 GNUNET_CRYPTO_EcdsaPublicKey
 #endif
 TALER_age_commitment_base_public_key = {
-  .q_y = { 0x6f, 0xe5, 0x87, 0x9a, 0x3d, 0xa9, 0x44, 0x20,
-           0x80, 0xbd, 0x6a, 0xb9, 0x44, 0x56, 0x91, 0x19,
-           0xaf, 0xb4, 0xc8, 0x7b, 0x89, 0xce, 0x23, 0x17,
-           0x97, 0x20, 0x5c, 0xbb, 0x9c, 0xd7, 0xcc, 0xd9},
+  .q_y = { 0x64, 0x41, 0xb9, 0xbd, 0xbf, 0x14, 0x39, 0x8e,
+           0x46, 0xeb, 0x5c, 0x1d, 0x34, 0xd3, 0x9b, 0x2f,
+           0x9b, 0x7d, 0xc8, 0x18, 0xeb, 0x9c, 0x09, 0xfb,
+           0x43, 0xad, 0x16, 0x64, 0xbc, 0x18, 0x49, 0xb5},
 };
 
 void

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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