gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] 01/06: first steps towards new /keys response: grouped


From: gnunet
Subject: [taler-exchange] 01/06: first steps towards new /keys response: grouped denominations added
Date: Thu, 23 Jun 2022 18:30:21 +0200

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

oec pushed a commit to branch master
in repository exchange.

commit c165ef31fee97df950081437ebf7484e1b4764ad
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Wed Jun 22 21:01:30 2022 +0200

    first steps towards new /keys response: grouped denominations added
---
 src/exchange/taler-exchange-httpd_keys.c | 321 +++++++++++++++++++++++--------
 1 file changed, 241 insertions(+), 80 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_keys.c 
b/src/exchange/taler-exchange-httpd_keys.c
index b3f0eb48..45bed1a1 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -283,7 +283,6 @@ struct SigningKey
 
 };
 
-
 struct TEH_KeyStateHandle
 {
 
@@ -404,7 +403,6 @@ struct SuspendedKeysRequests
   struct GNUNET_TIME_Absolute timeout;
 };
 
-
 /**
  * Stores the latest generation of our key state.
  */
@@ -1353,7 +1351,7 @@ denomination_info_cb (
   dk->meta = *meta;
   dk->master_sig = *master_sig;
   dk->recoup_possible = recoup_possible;
-  dk->denom_pub.age_mask = meta->age_mask;
+  dk->denom_pub.age_mask = meta->age_mask; /* FIXME-oec: age_mask -> 
reserved_field */
 
   GNUNET_assert (
     GNUNET_OK ==
@@ -1361,6 +1359,7 @@ denomination_info_cb (
                                        &dk->h_denom_pub.hash,
                                        dk,
                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+
 }
 
 
@@ -1727,12 +1726,12 @@ setup_general_response_headers (struct 
TEH_KeyStateHandle *ksh,
  * @a recoup and @a denoms.
  *
  * @param[in,out] ksh key state handle we build @a krd for
- * @param[in] denom_keys_hash hash over all the denominatoin keys in @a denoms 
and age_restricted_denoms
+ * @param[in] denom_keys_hash hash over all the denominatoin keys in @a denoms
  * @param last_cpd timestamp to use
  * @param signkeys list of sign keys to return
  * @param recoup list of revoked keys to return
  * @param denoms list of denominations to return
- * @param age_restricted_denoms list of age restricted denominations to 
return, can be NULL
+ * @param grouped_denominations list of grouped denominations to return
  * @return #GNUNET_OK on success
  */
 static enum GNUNET_GenericReturnValue
@@ -1742,7 +1741,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
             json_t *signkeys,
             json_t *recoup,
             json_t *denoms,
-            json_t *age_restricted_denoms)
+            json_t *grouped_denominations)
 {
   struct KeysResponseData krd;
   struct TALER_ExchangePublicKeyP exchange_pub;
@@ -1753,6 +1752,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
   GNUNET_assert (NULL != signkeys);
   GNUNET_assert (NULL != recoup);
   GNUNET_assert (NULL != denoms);
+  GNUNET_assert (NULL != grouped_denominations);
   GNUNET_assert (NULL != ksh->auditors);
   GNUNET_assert (NULL != TEH_currency);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1778,6 +1778,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
       return GNUNET_SYSERR;
     }
   }
+
   {
     const struct SigningKey *sk;
 
@@ -1803,6 +1804,8 @@ create_krd (struct TEH_KeyStateHandle *ksh,
                                    recoup),
     GNUNET_JSON_pack_array_incref ("denoms",
                                    denoms),
+    GNUNET_JSON_pack_array_incref ("denominations",
+                                   grouped_denominations),
     GNUNET_JSON_pack_array_incref ("auditors",
                                    ksh->auditors),
     GNUNET_JSON_pack_array_incref ("global_fees",
@@ -1833,7 +1836,6 @@ create_krd (struct TEH_KeyStateHandle *ksh,
   {
     json_t *extensions = json_object ();
     bool has_extensions = false;
-    bool age_restriction_enabled = false;
 
     /* Fill in the configurations of the enabled extensions */
     for (const struct TALER_Extension *extension = TALER_extensions_get_head 
();
@@ -1851,8 +1853,6 @@ create_krd (struct TEH_KeyStateHandle *ksh,
 
       /* flag our findings so far */
       has_extensions = true;
-      age_restriction_enabled = (extension->type ==
-                                 TALER_Extension_AgeRestriction);
 
       GNUNET_assert (NULL != extension->config_json);
 
@@ -1901,20 +1901,6 @@ create_krd (struct TEH_KeyStateHandle *ksh,
     {
       json_decref (extensions);
     }
-
-    // Special case for age restrictions: if enabled, provide the list of
-    // age-restricted denominations.
-    if (age_restriction_enabled &&
-        NULL != age_restricted_denoms)
-    {
-      GNUNET_assert (
-        0 ==
-        json_object_set (
-          keys,
-          "age_restricted_denoms",
-          age_restricted_denoms));
-    }
-
   }
 
 
@@ -2010,12 +1996,10 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
   json_t *recoup;
   struct SignKeyCtx sctx;
   json_t *denoms = NULL;
-  json_t *age_restricted_denoms = NULL;
+  json_t *grouped_denominations = NULL;
   struct GNUNET_TIME_Timestamp last_cpd;
   struct GNUNET_CONTAINER_Heap *heap;
   struct GNUNET_HashContext *hash_context = NULL;
-  struct GNUNET_HashContext *hash_context_restricted = NULL;
-  bool have_age_restricted_denoms = false;
 
   sctx.signkeys = json_array ();
   GNUNET_assert (NULL != sctx.signkeys);
@@ -2045,20 +2029,25 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
   GNUNET_assert (NULL != denoms);
   hash_context = GNUNET_CRYPTO_hash_context_start ();
 
-  /* If age restriction is enabled, initialize the array of age restricted
-   denoms  and prepare a hash for them, separate from the others.  We will join
-   those hashes afterwards.*/
-  if (0)
-  {
-    age_restricted_denoms = json_array ();
-    GNUNET_assert (NULL != age_restricted_denoms);
-    hash_context_restricted = GNUNET_CRYPTO_hash_context_start ();
-  }
+  grouped_denominations = json_array ();
+  GNUNET_assert (NULL != grouped_denominations);
 
   last_cpd = GNUNET_TIME_UNIT_ZERO_TS;
 
   {
     struct TEH_DenominationKey *dk;
+    struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
+
+    denominations_by_group =
+      GNUNET_CONTAINER_multihashmap_create (1024,
+                                            GNUNET_NO /* NO, because keys are 
only on the stack */);
+
+    /* groupData is the value we store for each group meta-data */
+    struct groupData
+    {
+      json_t *json;   /* The json blob with the group meta-data and list of 
denominations */
+      struct GNUNET_HashContext *hash_context;   /* hash over all 
denominations in that group */
+    };
 
     /* heap = min heap, sorted by start time */
     while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap)))
@@ -2068,12 +2057,12 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
                                      dk->meta.start) &&
           (! GNUNET_TIME_absolute_is_zero (last_cpd.abs_time)) )
       {
-        struct GNUNET_HashCode hc;
-
-        /* FIXME-oec: Do we need to take hash_context_restricted into account
-         * in this if-branch!?  Current tests suggests: no, (they don't fail).
-         * But something seems to be odd about only finishing hash_context.
+        /*
+         * This is not the first entry in the heap (because last_cpd !=
+         * GNUNET_TIME_UNIT_ZERO_TS) and the previous entry had a different
+         * start time.  Therefore, we create an entry in the ksh.
          */
+        struct GNUNET_HashCode hc;
 
         GNUNET_CRYPTO_hash_context_finish (
           GNUNET_CRYPTO_hash_context_copy (hash_context),
@@ -2085,7 +2074,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
                         sctx.signkeys,
                         recoup,
                         denoms,
-                        age_restricted_denoms))
+                        grouped_denominations))
         {
           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                       "Failed to generate key response data for %s\n",
@@ -2096,8 +2085,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
             /* intentionally empty */;
           GNUNET_CONTAINER_heap_destroy (heap);
           json_decref (denoms);
-          if (NULL != age_restricted_denoms)
-            json_decref (age_restricted_denoms);
+          json_decref (grouped_denominations);
           json_decref (sctx.signkeys);
           json_decref (recoup);
           return GNUNET_SYSERR;
@@ -2108,9 +2096,6 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
 
       {
         json_t *denom;
-        json_t *array;
-        struct GNUNET_HashContext *hc;
-
 
         denom =
           GNUNET_JSON_PACK (
@@ -2131,33 +2116,222 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
             TALER_JSON_PACK_DENOM_FEES ("fee",
                                         &dk->meta.fees));
 
-        /* Put the denom into the correct array depending on the settings and
-         * the properties of the denomination.  Also, we build up the right
-         * hash for the corresponding array. */
-        if (0 &&
-            (0 != dk->denom_pub.age_mask.bits))
+        GNUNET_CRYPTO_hash_context_read (hash_context,
+                                         &dk->h_denom_pub,
+                                         sizeof (struct GNUNET_HashCode));
+
+        GNUNET_assert (
+          0 ==
+          json_array_append_new (
+            denoms,
+            denom));
+
+      }
+
+      /**
+       * Group the denominations by {cipher, value, fees, age_mask}.
+       *
+       * For each group we save the group meta-data and the list of
+       * denominations in this group as a json-blob in the multihashmap
+       * denominations_by_group.
+       **/
+
+      {
+        static const char *denoms_key = "denoms";
+        struct groupData *group;
+        json_t *list;
+        json_t *entry;
+        struct GNUNET_HashCode key;
+
+        /* Find the group/JSON-blob for the key */
+        struct
+        {
+          enum TALER_DenominationCipher cipher;
+          struct TALER_AgeMask age_mask;
+          struct TALER_Amount value;
+          struct TALER_DenomFeeSet fees;
+        } meta = {
+          .cipher = dk->denom_pub.cipher,
+          .value = dk->meta.value,
+          .fees = dk->meta.fees,
+          .age_mask = dk->meta.age_mask,
+        };
+
+        GNUNET_CRYPTO_hash (&meta, sizeof(meta), &key);
+
+        group = (struct groupData *) GNUNET_CONTAINER_multihashmap_get (
+          denominations_by_group,
+          &key);
+
+        if (NULL == group)
         {
-          have_age_restricted_denoms = true;
-          array = age_restricted_denoms;
-          hc = hash_context_restricted;
+          /*
+           * There is no group for this meta-data yet, so let's create a new
+           * group entry.
+           */
+
+          bool age_restricted = meta.age_mask.bits != 0;
+          char *cipher;
+
+          group = GNUNET_new (struct groupData);
+          group->hash_context = GNUNET_CRYPTO_hash_context_start ();
+
+          switch (meta.cipher)
+          {
+          case TALER_DENOMINATION_RSA:
+            cipher = age_restricted ? "RSA+age_restriction": "RSA";
+            break;
+          case TALER_DENOMINATION_CS:
+            cipher = age_restricted ? "CS+age_restriction": "CS";
+            break;
+          default:
+            GNUNET_assert (false);
+          }
+
+          group->json = GNUNET_JSON_PACK (
+            GNUNET_JSON_pack_string ("cipher", cipher),
+            TALER_JSON_PACK_DENOM_FEES ("fee", &meta.fees),
+            TALER_JSON_pack_amount ("value", &meta.value));
+          GNUNET_assert (NULL != group->json);
+
+          if (age_restricted)
+          {
+            GNUNET_assert (0 ==
+                           json_object_set (group->json,
+                                            "age_mask",
+                                            json_integer 
(meta.age_mask.bits)));
+          }
+
+          /* Create a new array for the denominations in this group */
+          list = json_array ();
+          GNUNET_assert (NULL != list);
+          GNUNET_assert (0 ==
+                         json_object_set (group->json, denoms_key, list));
+
+          GNUNET_assert (
+            GNUNET_OK ==
+            GNUNET_CONTAINER_multihashmap_put (denominations_by_group,
+                                               &key,
+                                               group,
+                                               
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
         }
-        else
+
+        /*
+         * Now that we have found/created the right group, add the denomination
+         * to the list
+         */
         {
-          array = denoms;
-          hc = hash_context;
+          struct GNUNET_JSON_PackSpec key_spec;
+
+          switch (meta.cipher)
+          {
+          case TALER_DENOMINATION_RSA:
+            key_spec =
+              GNUNET_JSON_pack_rsa_public_key ("rsa_pub",
+                                               dk->denom_pub.details.
+                                               rsa_public_key);
+            break;
+          case TALER_DENOMINATION_CS:
+            key_spec =
+              GNUNET_JSON_pack_data_varsize ("cs_pub",
+                                             &dk->denom_pub.details.
+                                             cs_public_key,
+                                             sizeof (dk->denom_pub.details.
+                                                     cs_public_key));
+            break;
+          default:
+            GNUNET_assert (false);
+          }
+
+          entry = GNUNET_JSON_PACK (
+            GNUNET_JSON_pack_data_auto ("master_sig",
+                                        &dk->master_sig),
+            GNUNET_JSON_pack_timestamp ("stamp_start",
+                                        dk->meta.start),
+            GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw",
+                                        dk->meta.expire_withdraw),
+            GNUNET_JSON_pack_timestamp ("stamp_expire_deposit",
+                                        dk->meta.expire_deposit),
+            GNUNET_JSON_pack_timestamp ("stamp_expire_legal",
+                                        dk->meta.expire_legal),
+            key_spec
+            );
+          GNUNET_assert (NULL != entry);
         }
 
-        GNUNET_CRYPTO_hash_context_read (hc,
+        /*
+         * Build up the running hash of all denominations in this group
+         * TODO: FIXME-oec: this is cipher and age_restriction dependend?!
+         */
+        GNUNET_CRYPTO_hash_context_read (group->hash_context,
                                          &dk->h_denom_pub,
                                          sizeof (struct GNUNET_HashCode));
 
-        GNUNET_assert (
-          0 ==
-          json_array_append_new (
-            array,
-            denom));
+        /* Finally, add the denomination to the list of denominations in this
+         * group */
+        list = json_object_get (group->json, denoms_key);
+        GNUNET_assert (NULL != list);
+        GNUNET_assert (true == json_is_array (list));
+        GNUNET_assert (0 ==
+                       json_array_append_new (list, entry));
       }
     }
+
+    /* Create the JSON-array of grouped denominations */
+    if (0 <
+        GNUNET_CONTAINER_multihashmap_size (denominations_by_group))
+    {
+      struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
+      struct GNUNET_HashCode all_hashcode;
+      struct GNUNET_HashContext *all_hash_ctx;
+      struct groupData *group = NULL;
+
+      all_hash_ctx =
+        GNUNET_CRYPTO_hash_context_start ();
+
+      iter =
+        GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group);
+
+      while (GNUNET_OK ==
+             GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL, (const
+                                                                       void **)
+                                                          &group))
+      {
+        struct GNUNET_HashCode hc;
+
+        GNUNET_CRYPTO_hash_context_finish (
+          group->hash_context,
+          &hc);
+
+        GNUNET_CRYPTO_hash_context_read (all_hash_ctx,
+                                         &hc,
+                                         sizeof (struct GNUNET_HashCode));
+
+        GNUNET_assert (0 ==
+                       json_object_set (
+                         group->json,
+                         "hash",
+                         GNUNET_JSON_PACK (
+                           GNUNET_JSON_pack_data_auto (NULL, &hc))));
+
+        GNUNET_assert (0 ==
+                       json_array_append_new (
+                         grouped_denominations,
+                         group->json));
+
+        GNUNET_free (group);
+      }
+
+      GNUNET_CONTAINER_multihashmap_iterator_destroy (iter);
+      GNUNET_CONTAINER_multihashmap_destroy (denominations_by_group);
+
+      GNUNET_CRYPTO_hash_context_finish (
+        all_hash_ctx,
+        &all_hashcode);
+
+      /* FIXME-oec: TODO:
+       * sign all_hashcode and add the signature to the /keys response */
+    }
   }
 
   GNUNET_CONTAINER_heap_destroy (heap);
@@ -2165,18 +2339,6 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
   {
     struct GNUNET_HashCode hc;
 
-    /* If age restriction is active and we had at least one denomination of
-     * that sort, we simply add the hash of all age restricted denominations at
-     * the end of the others. */
-    if (0 && have_age_restricted_denoms)
-    {
-      struct GNUNET_HashCode hcr;
-      GNUNET_CRYPTO_hash_context_finish (hash_context_restricted, &hcr);
-      GNUNET_CRYPTO_hash_context_read (hash_context,
-                                       &hcr,
-                                       sizeof (struct GNUNET_HashCode));
-    }
-
     GNUNET_CRYPTO_hash_context_finish (hash_context,
                                        &hc);
 
@@ -2187,14 +2349,12 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
                     sctx.signkeys,
                     recoup,
                     denoms,
-                    age_restricted_denoms))
+                    grouped_denominations))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Failed to generate key response data for %s\n",
                   GNUNET_TIME_timestamp2s (last_cpd));
       json_decref (denoms);
-      if (0 && NULL != age_restricted_denoms)
-        json_decref (age_restricted_denoms);
       json_decref (sctx.signkeys);
       json_decref (recoup);
       return GNUNET_SYSERR;
@@ -2210,8 +2370,6 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
   json_decref (sctx.signkeys);
   json_decref (recoup);
   json_decref (denoms);
-  if (NULL != age_restricted_denoms)
-    json_decref (age_restricted_denoms);
   return GNUNET_OK;
 }
 
@@ -2387,11 +2545,13 @@ build_key_state (struct HelperState *hs,
                        true);
     return NULL;
   }
+
   if (management_only)
   {
     ksh->management_only = true;
     return ksh;
   }
+
   if (GNUNET_OK !=
       finish_keys_response (ksh))
   {
@@ -2401,6 +2561,7 @@ build_key_state (struct HelperState *hs,
                        true);
     return NULL;
   }
+
   return ksh;
 }
 

-- 
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]