added check for empty nonce string
[oweals/gnunet.git] / src / reclaim / gnunet-service-reclaim_tickets.c
index a39a4be5ab599b50999bc54ed94d697ae19701ea..182cb6186ec8adc344c64ef58c957fabe6609c25 100644 (file)
  * @brief reclaim tickets
  *
  */
+#include <inttypes.h>
 #include "gnunet-service-reclaim_tickets.h"
 
+#define DEFAULT_TICKET_REFRESH_INTERVAL GNUNET_TIME_UNIT_HOURS
+
 struct ParallelLookup;
 
+
+/**
+ * A reference to a ticket stored in GNS
+ */
+struct TicketReference
+{
+  /**
+   * DLL
+   */
+  struct TicketReference *next;
+
+  /**
+   * DLL
+   */
+  struct TicketReference *prev;
+
+  /**
+   * Attributes
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+
+  /**
+   * Tickets
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+};
+
+
 struct RECLAIM_TICKETS_ConsumeHandle
 {
   /**
@@ -84,7 +115,6 @@ struct RECLAIM_TICKETS_ConsumeHandle
    * Callbacl closure
    */
   void *cb_cls;
-
 };
 
 /**
@@ -115,125 +145,158 @@ struct ParallelLookup
 
 
 /**
- * A reference to a ticket stored in GNS
+ * Ticket issue request handle
  */
-struct TicketReference
+struct TicketIssueHandle
 {
   /**
-   * DLL
+   * Attributes to issue
    */
-  struct TicketReference *next;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
 
   /**
-   * DLL
+   * Issuer Key
    */
-  struct TicketReference *prev;
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
   /**
-   * Attributes
+   * Ticket to issue
    */
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+  struct GNUNET_RECLAIM_Ticket ticket;
 
   /**
-   * Tickets
+   * QueueEntry
    */
-  struct GNUNET_RECLAIM_Ticket ticket;
-};
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * Callback
+   */
+  RECLAIM_TICKETS_TicketResult cb;
 
+  /**
+   * Callback cls
+   */
+  void *cb_cls;
+};
 
 /**
- * Ticket issue request handle
+ * Ticket iterator
  */
-struct TicketIssueHandle
+struct RECLAIM_TICKETS_Iterator
 {
   /**
-   * Attributes to issue
+   * Namestore queue entry
    */
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
 
   /**
-   * Issuer Key
+   * Iter callback
    */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+  RECLAIM_TICKETS_TicketIter cb;
 
   /**
-   * Ticket to issue
+   * Iter cls
    */
-  struct GNUNET_RECLAIM_Ticket ticket;
+  void *cb_cls;
+};
 
+
+struct RevokedAttributeEntry
+{
   /**
-   * QueueEntry
+   * DLL
    */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+  struct RevokedAttributeEntry *next;
 
   /**
-   * Ticket reference list
+   * DLL
    */
-  struct TicketReference *ticket_refs_head;
+  struct RevokedAttributeEntry *prev;
 
   /**
-   * Ticket reference list
+   * Old ID of the attribute
    */
-  struct TicketReference *ticket_refs_tail;
+  uint64_t old_id;
 
   /**
-   * Number of references
+   * New ID of the attribute
    */
-  uint32_t ticket_ref_num;
+  uint64_t new_id;
+};
+
+
+/**
+ * Ticket revocation request handle
+ */
+struct RECLAIM_TICKETS_RevokeHandle
+{
+  /**
+   * Issuer Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
   /**
    * Callback
    */
-  RECLAIM_TICKETS_TicketResult cb;
+  RECLAIM_TICKETS_RevokeCallback cb;
 
   /**
    * Callback cls
    */
   void *cb_cls;
 
-};
+  /**
+   * Ticket to issue
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
 
-/**
- * Ticket iterator
- */
-struct RECLAIM_TICKETS_Iterator
-{
   /**
-   * Issuer Key
+   * QueueEntry
    */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
 
   /**
-   * Issuer pubkey
+   * Namestore iterator
    */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
 
   /**
-   * Namestore queue entry
+   * Revoked attributes
    */
-  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+  struct RevokedAttributeEntry *attrs_head;
 
   /**
-   * Iter callback
+   * Revoked attributes
    */
-  RECLAIM_TICKETS_TicketIter cb;
+  struct RevokedAttributeEntry *attrs_tail;
 
   /**
-   * Iter cls
+   * Current attribute to move
    */
-  void *cb_cls;
+  struct RevokedAttributeEntry *move_attr;
 
   /**
-   * Ticket reference list
+   * Number of attributes in ticket
    */
-  struct TicketReference *tickets_head;
+  unsigned int ticket_attrs;
 
   /**
-   * Ticket reference list
+   * Tickets to update
    */
-  struct TicketReference *tickets_tail;
+  struct TicketRecordsEntry *tickets_to_update_head;
+
+  /**
+   * Tickets to update
+   */
+  struct TicketRecordsEntry *tickets_to_update_tail;
 };
 
+/**
+ * Ticket expiration interval
+ */
+static struct GNUNET_TIME_Relative ticket_refresh_interval;
+
 /* Namestore handle */
 static struct GNUNET_NAMESTORE_Handle *nsh;
 
@@ -243,29 +306,432 @@ static struct GNUNET_GNS_Handle *gns;
 /* Handle to the statistics service */
 static struct GNUNET_STATISTICS_Handle *stats;
 
-static int
-create_sym_key_from_ecdh (const struct GNUNET_HashCode *new_key_hash,
-                          struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
-                          struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
-{
-  struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
-
-  GNUNET_CRYPTO_hash_to_enc (new_key_hash,
-                             &new_key_hash_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
-  static const char ctx_key[] = "gnuid-aes-ctx-key";
-  GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-                     new_key_hash, sizeof (struct GNUNET_HashCode),
-                     ctx_key, strlen (ctx_key),
-                     NULL, 0);
-  static const char ctx_iv[] = "gnuid-aes-ctx-iv";
-  GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
-                     new_key_hash, sizeof (struct GNUNET_HashCode),
-                     ctx_iv, strlen (ctx_iv),
-                     NULL, 0);
-  return GNUNET_OK;
+static void
+move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rh);
+
+static void
+move_attrs_cont (void *cls)
+{
+  move_attrs ((struct RECLAIM_TICKETS_RevokeHandle *) cls);
 }
 
+/**
+ * Cleanup revoke handle
+ *
+ * @param rh the ticket revocation handle
+ */
+static void
+cleanup_rvk (struct RECLAIM_TICKETS_RevokeHandle *rh)
+{
+  struct RevokedAttributeEntry *ae;
+  struct TicketRecordsEntry *le;
+  if (NULL != rh->ns_qe)
+    GNUNET_NAMESTORE_cancel (rh->ns_qe);
+  if (NULL != rh->ns_it)
+    GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
+  while (NULL != (ae = rh->attrs_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (rh->attrs_head, rh->attrs_tail, ae);
+    GNUNET_free (ae);
+  }
+  while (NULL != (le = rh->tickets_to_update_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (rh->tickets_to_update_head,
+                                 rh->tickets_to_update_head,
+                                 le);
+    if (NULL != le->data)
+      GNUNET_free (le->data);
+    if (NULL != le->label)
+      GNUNET_free (le->label);
+    GNUNET_free (le);
+  }
+  GNUNET_free (rh);
+}
+
+static void
+del_attr_finished (void *cls, int32_t success, const char *emsg)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  rvk->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error removing attribute: %s\n",
+                emsg);
+    rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
+    cleanup_rvk (rvk);
+    return;
+  }
+  rvk->move_attr = rvk->move_attr->next;
+  GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
+}
+
+static void
+move_attr_finished (void *cls, int32_t success, const char *emsg)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  char *label;
+  rvk->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error moving attribute: %s\n", emsg);
+    rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
+    cleanup_rvk (rvk);
+    return;
+  }
+  label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
+                                               sizeof (uint64_t));
+  GNUNET_assert (NULL != label);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing attribute %s\n", label);
+  rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+                                               &rvk->identity,
+                                               label,
+                                               0,
+                                               NULL,
+                                               &del_attr_finished,
+                                               rvk);
+  GNUNET_free (label);
+}
+
+
+static void
+rvk_move_attr_cb (void *cls,
+                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                  const char *label,
+                  unsigned int rd_count,
+                  const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
+  struct GNUNET_GNSRECORD_Data new_rd;
+  struct RevokedAttributeEntry *le;
+  char *new_label;
+  char *attr_data;
+  rvk->ns_qe = NULL;
+  if (0 == rd_count)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "The attribute %s no longer exists!\n",
+                label);
+    le = rvk->move_attr;
+    rvk->move_attr = le->next;
+    GNUNET_CONTAINER_DLL_remove (rvk->attrs_head, rvk->attrs_tail, le);
+    GNUNET_free (le);
+    GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
+    return;
+  }
+  /** find a new place for this attribute **/
+  rvk->move_attr->new_id =
+    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
+  new_rd = *rd;
+  claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Attribute to update: Name=%s, ID=%" PRIu64 "\n",
+              claim->name,
+              claim->id);
+  claim->id = rvk->move_attr->new_id;
+  new_rd.data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (claim);
+  attr_data = GNUNET_malloc (rd->data_size);
+  new_rd.data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize (claim, attr_data);
+  new_rd.data = attr_data;
+  new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
+                                                   sizeof (uint64_t));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
+  rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+                                               &rvk->identity,
+                                               new_label,
+                                               1,
+                                               &new_rd,
+                                               &move_attr_finished,
+                                               rvk);
+  GNUNET_free (new_label);
+  GNUNET_free (claim);
+  GNUNET_free (attr_data);
+}
+
+
+static void
+rvk_ticket_update (void *cls,
+                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                   const char *label,
+                   unsigned int rd_count,
+                   const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  struct TicketRecordsEntry *le;
+  struct RevokedAttributeEntry *ae;
+  int has_changed = GNUNET_NO;
+
+  /** Let everything point to the old record **/
+  for (int i = 0; i < rd_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
+      continue;
+    for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
+    {
+      if (0 != memcmp (rd[i].data, &ae->old_id, sizeof (uint64_t)))
+        continue;
+      has_changed = GNUNET_YES;
+      break;
+    }
+    if (GNUNET_YES == has_changed)
+      break;
+  }
+  if (GNUNET_YES == has_changed)
+  {
+    le = GNUNET_new (struct TicketRecordsEntry);
+    le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
+    le->data = GNUNET_malloc (le->data_size);
+    le->rd_count = rd_count;
+    le->label = GNUNET_strdup (label);
+    GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
+    GNUNET_CONTAINER_DLL_insert (rvk->tickets_to_update_head,
+                                 rvk->tickets_to_update_tail,
+                                 le);
+  }
+  GNUNET_NAMESTORE_zone_iterator_next (rvk->ns_it, 1);
+}
+
+
+static void
+process_tickets (void *cls);
+
+
+static void
+ticket_processed (void *cls, int32_t success, const char *emsg)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  rvk->ns_qe = NULL;
+  GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
+}
+
+static void
+process_tickets (void *cls)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  struct TicketRecordsEntry *le;
+  struct RevokedAttributeEntry *ae;
+  if (NULL == rvk->tickets_to_update_head)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Finished updatding tickets, success\n");
+    rvk->cb (rvk->cb_cls, GNUNET_OK);
+    cleanup_rvk (rvk);
+    return;
+  }
+  le = rvk->tickets_to_update_head;
+  GNUNET_CONTAINER_DLL_remove (rvk->tickets_to_update_head,
+                               rvk->tickets_to_update_tail,
+                               le);
+  struct GNUNET_GNSRECORD_Data rd[le->rd_count];
+  if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
+                                                         le->data,
+                                                         le->rd_count,
+                                                         rd))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to deserialize ticket record(s)\n");
+    rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
+    cleanup_rvk (rvk);
+    return;
+  }
+  for (int i = 0; i < le->rd_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
+      continue;
+    for (ae = rvk->attrs_head; NULL != ae; ae = ae->next)
+    {
+      if (0 != memcmp (rd[i].data, &ae->old_id, sizeof (uint64_t)))
+        continue;
+      rd[i].data = &ae->new_id;
+    }
+  }
+  rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+                                               &rvk->identity,
+                                               le->label,
+                                               le->rd_count,
+                                               rd,
+                                               &ticket_processed,
+                                               rvk);
+  GNUNET_free (le->label);
+  GNUNET_free (le->data);
+  GNUNET_free (le);
+}
+
+static void
+rvk_ticket_update_finished (void *cls)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  rvk->ns_it = NULL;
+  GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
+}
+
+
+static void
+rvk_ns_iter_err (void *cls)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  rvk->ns_it = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Namestore error on revocation (id=%" PRIu64 "\n",
+              rvk->move_attr->old_id);
+  rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
+  cleanup_rvk (rvk);
+}
+
+
+static void
+rvk_ns_err (void *cls)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  rvk->ns_qe = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Namestore error on revocation (id=%" PRIu64 "\n",
+              rvk->move_attr->old_id);
+  rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
+  cleanup_rvk (rvk);
+}
+
+
+static void
+move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk)
+{
+  char *label;
+
+  if (NULL == rvk->move_attr)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished moving attributes\n");
+    rvk->ns_it =
+      GNUNET_NAMESTORE_zone_iteration_start (nsh,
+                                             &rvk->identity,
+                                             &rvk_ns_iter_err,
+                                             rvk,
+                                             &rvk_ticket_update,
+                                             rvk,
+                                             &rvk_ticket_update_finished,
+                                             rvk);
+    return;
+  }
+  label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
+                                               sizeof (uint64_t));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving attribute %s\n", label);
+
+  rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
+                                                &rvk->identity,
+                                                label,
+                                                &rvk_ns_err,
+                                                rvk,
+                                                &rvk_move_attr_cb,
+                                                rvk);
+  GNUNET_free (label);
+}
+
+
+static void
+remove_ticket_cont (void *cls, int32_t success, const char *emsg)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  rvk->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
+    rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
+    cleanup_rvk (rvk);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted ticket\n");
+  if (0 == rvk->ticket_attrs)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "No attributes to move... strange\n");
+    rvk->cb (rvk->cb_cls, GNUNET_OK);
+    cleanup_rvk (rvk);
+    return;
+  }
+  rvk->move_attr = rvk->attrs_head;
+  move_attrs (rvk);
+}
+
+
+static void
+revoke_attrs_cb (void *cls,
+                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                 const char *label,
+                 unsigned int rd_count,
+                 const struct GNUNET_GNSRECORD_Data *rd)
+
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  struct RevokedAttributeEntry *le;
+  rvk->ns_qe = NULL;
+  for (int i = 0; i < rd_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
+      continue;
+    le = GNUNET_new (struct RevokedAttributeEntry);
+    le->old_id = *((uint64_t *) rd[i].data);
+    GNUNET_CONTAINER_DLL_insert (rvk->attrs_head, rvk->attrs_tail, le);
+    rvk->ticket_attrs++;
+  }
+
+  /** Now, remove ticket **/
+  rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+                                               &rvk->identity,
+                                               label,
+                                               0,
+                                               NULL,
+                                               &remove_ticket_cont,
+                                               rvk);
+}
+
+
+static void
+rvk_attrs_err_cb (void *cls)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
+  rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
+  cleanup_rvk (rvk);
+}
+
+
+struct RECLAIM_TICKETS_RevokeHandle *
+RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket,
+                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                        RECLAIM_TICKETS_RevokeCallback cb,
+                        void *cb_cls)
+{
+  struct RECLAIM_TICKETS_RevokeHandle *rvk;
+  char *label;
+
+  rvk = GNUNET_new (struct RECLAIM_TICKETS_RevokeHandle);
+  rvk->cb = cb;
+  rvk->cb_cls = cb_cls;
+  rvk->identity = *identity;
+  rvk->ticket = *ticket;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&rvk->identity, &rvk->ticket.identity);
+  /** Get shared attributes **/
+  label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof (uint64_t));
+  GNUNET_assert (NULL != label);
+  rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
+                                                identity,
+                                                label,
+                                                &rvk_attrs_err_cb,
+                                                rvk,
+                                                &revoke_attrs_cb,
+                                                rvk);
+  GNUNET_free (label);
+  return rvk;
+}
+
+
+void
+RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh)
+{
+  cleanup_rvk (rh);
+}
+/*******************************
+ * Ticket consume
+ *******************************/
 
 /**
  * Cleanup ticket consume handle
@@ -275,19 +741,19 @@ static void
 cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
 {
   struct ParallelLookup *lu;
-  struct ParallelLookup *tmp;
   if (NULL != cth->lookup_request)
     GNUNET_GNS_lookup_cancel (cth->lookup_request);
-  for (lu = cth->parallel_lookups_head;
-       NULL != lu;) {
-    GNUNET_GNS_lookup_cancel (lu->lookup_request);
-    GNUNET_free (lu->label);
-    tmp = lu->next;
+  if (NULL != cth->kill_task)
+    GNUNET_SCHEDULER_cancel (cth->kill_task);
+  while (NULL != (lu = cth->parallel_lookups_head))
+  {
+    if (NULL != lu->lookup_request)
+      GNUNET_GNS_lookup_cancel (lu->lookup_request);
+    GNUNET_free_non_null (lu->label);
     GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
                                  cth->parallel_lookups_tail,
                                  lu);
     GNUNET_free (lu);
-    lu = tmp;
   }
 
   if (NULL != cth->attrs)
@@ -298,14 +764,15 @@ cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
 
 static void
 process_parallel_lookup_result (void *cls,
-                          uint32_t rd_count,
-                          const struct GNUNET_GNSRECORD_Data *rd)
+                                uint32_t rd_count,
+                                const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct ParallelLookup *parallel_lookup = cls;
   struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle;
   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Parallel lookup finished (count=%u)\n", rd_count);
+              "Parallel lookup finished (count=%u)\n",
+              rd_count);
 
   GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
                                cth->parallel_lookups_tail,
@@ -314,36 +781,30 @@ process_parallel_lookup_result (void *cls,
 
   GNUNET_STATISTICS_update (stats,
                             "attribute_lookup_time_total",
-                            GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
-                            GNUNET_YES);
-  GNUNET_STATISTICS_update (stats,
-                            "attribute_lookups_count",
-                            1,
+                            GNUNET_TIME_absolute_get_duration (
+                              parallel_lookup->lookup_start_time)
+                              .rel_value_us,
                             GNUNET_YES);
+  GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES);
 
 
   GNUNET_free (parallel_lookup);
   if (1 != rd_count)
-    GNUNET_break(0);//TODO
+    GNUNET_break (0); // TODO
   if (rd->record_type == GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR)
   {
     attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
-    attr_le->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data,
-                                                           rd->data_size);
+    attr_le->claim =
+      GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size);
     GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
                                  cth->attrs->list_tail,
                                  attr_le);
   }
   if (NULL != cth->parallel_lookups_head)
-    return; //Wait for more
+    return; // Wait for more
   /* Else we are done */
 
-  GNUNET_SCHEDULER_cancel (cth->kill_task);
-  cth->cb (cth->cb_cls,
-           &cth->ticket.identity,
-           cth->attrs,
-           GNUNET_OK,
-           NULL);
+  cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL);
   cleanup_cth (cth);
 }
 
@@ -356,8 +817,8 @@ abort_parallel_lookups (void *cls)
   struct ParallelLookup *tmp;
 
   cth->kill_task = NULL;
-  for (lu = cth->parallel_lookups_head;
-       NULL != lu;) {
+  for (lu = cth->parallel_lookups_head; NULL != lu;)
+  {
     GNUNET_GNS_lookup_cancel (lu->lookup_request);
     GNUNET_free (lu->label);
     tmp = lu->next;
@@ -367,146 +828,97 @@ abort_parallel_lookups (void *cls)
     GNUNET_free (lu);
     lu = tmp;
   }
-  cth->cb (cth->cb_cls,
-           NULL,
-           NULL,
-           GNUNET_SYSERR,
-           "Aborted");
-
+  cth->cb (cth->cb_cls, NULL, NULL, GNUNET_SYSERR, "Aborted");
 }
 
 
-
 static void
 lookup_authz_cb (void *cls,
                  uint32_t rd_count,
                  const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
-  struct GNUNET_HashCode new_key_hash;
-  struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
-  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
   struct ParallelLookup *parallel_lookup;
-  size_t size;
-  char *buf;
-  char *attr_lbl;
-  char *lbls;
+  char *lbl;
 
   cth->lookup_request = NULL;
-  if (1 != rd_count)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Number of keys %d != 1.",
-                rd_count);
-    cth->cb (cth->cb_cls,
-             NULL,
-             NULL,
-             GNUNET_SYSERR,
-             "Number of keys %d != 1.");
-    cleanup_cth (cth);
-    return;
-  }
-
-  //Decrypt
-  ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
-
-  buf = GNUNET_malloc (rd->data_size
-                       - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-
-  //Calculate symmetric key from ecdh parameters
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CRYPTO_ecdsa_ecdh (&cth->identity,
-                                           ecdh_key,
-                                           &new_key_hash));
-  create_sym_key_from_ecdh (&new_key_hash,
-                            &enc_key,
-                            &enc_iv);
-  size = GNUNET_CRYPTO_symmetric_decrypt (rd->data
-                               + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
-                                          rd->data_size
-                               - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
-                                          &enc_key,
-                                          &enc_iv,
-                                          buf);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Decrypted bytes: %zd Expected bytes: %zd\n",
-              size,
-              rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
   GNUNET_STATISTICS_update (stats,
-    "reclaim_authz_lookup_time_total",
-    GNUNET_TIME_absolute_get_duration (cth->lookup_start_time).rel_value_us,
-    GNUNET_YES);
+                            "reclaim_authz_lookup_time_total",
+                            GNUNET_TIME_absolute_get_duration (
+                              cth->lookup_start_time)
+                              .rel_value_us,
+                            GNUNET_YES);
   GNUNET_STATISTICS_update (stats,
                             "reclaim_authz_lookups_count",
                             1,
                             GNUNET_YES);
-  lbls = GNUNET_strdup (buf);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Attributes found %s\n", lbls);
 
-  for (attr_lbl = strtok (lbls, ",");
-       NULL != attr_lbl;
-       attr_lbl = strtok (NULL, ","))
+  for (int i = 0; i < rd_count; i++)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Looking up %s\n", attr_lbl);
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
+      continue;
+    lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Attribute ref found %s\n", lbl);
     parallel_lookup = GNUNET_new (struct ParallelLookup);
     parallel_lookup->handle = cth;
-    parallel_lookup->label = GNUNET_strdup (attr_lbl);
-    parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
-    parallel_lookup->lookup_request
-      GNUNET_GNS_lookup (gns,
-                           attr_lbl,
-                           &cth->ticket.identity,
-                           GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR,
-                           GNUNET_GNS_LO_DEFAULT,
-                           &process_parallel_lookup_result,
-                           parallel_lookup);
+    parallel_lookup->label = lbl;
+    parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
+    parallel_lookup->lookup_request =
+      GNUNET_GNS_lookup (gns,
+                         lbl,
+                         &cth->ticket.identity,
+                         GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR,
+                         GNUNET_GNS_LO_DEFAULT,
+                         &process_parallel_lookup_result,
+                         parallel_lookup);
     GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
                                  cth->parallel_lookups_tail,
                                  parallel_lookup);
   }
-  GNUNET_free (lbls);
-  GNUNET_free (buf);
-  cth->kill_task = GNUNET_SCHEDULER_add_delayed (
-                    GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
-                    &abort_parallel_lookups,
-                    cth);
+  if (NULL != cth->parallel_lookups_head)
+  {
+    cth->kill_task = GNUNET_SCHEDULER_add_delayed (
+      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3),
+      &abort_parallel_lookups,
+      cth);
+    return;
+  }
+  cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL);
+  cleanup_cth (cth);
 }
 
 
-
-struct RECLAIM_TICKETS_ConsumeHandle*
+struct RECLAIM_TICKETS_ConsumeHandle *
 RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_EcdsaPrivateKey *id,
-                               const struct GNUNET_RECLAIM_Ticket *ticket,
-                               RECLAIM_TICKETS_ConsumeCallback cb,
-                               void* cb_cls)
+                         const struct GNUNET_RECLAIM_Ticket *ticket,
+                         RECLAIM_TICKETS_ConsumeCallback cb,
+                         void *cb_cls)
 {
   struct RECLAIM_TICKETS_ConsumeHandle *cth;
   char *label;
   cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle);
 
   cth->identity = *id;
-  GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity,
-                                      &cth->identity_pub);
+  GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub);
   cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
   cth->ticket = *ticket;
   cth->cb = cb;
   cth->cb_cls = cb_cls;
-  label = GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd,
-                                               sizeof (uint64_t));
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Looking for AuthZ info under %s\n", label);
+  label =
+    GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd, sizeof (uint64_t));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Looking for AuthZ info under %s\n",
+              label);
   cth->lookup_start_time = GNUNET_TIME_absolute_get ();
-  cth->lookup_request = GNUNET_GNS_lookup (gns,
-                                           label,
-                                           &cth->ticket.identity,
-                                           GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ,
-                                           GNUNET_GNS_LO_DEFAULT,
-                                           &lookup_authz_cb,
-                                           cth);
+  cth->lookup_request =
+    GNUNET_GNS_lookup (gns,
+                       label,
+                       &cth->ticket.identity,
+                       GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF,
+                       GNUNET_GNS_LO_DEFAULT,
+                       &lookup_authz_cb,
+                       cth);
   GNUNET_free (label);
   return cth;
 }
@@ -530,154 +942,14 @@ RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
 static void
 cleanup_issue_handle (struct TicketIssueHandle *handle)
 {
-  struct TicketReference *tr;
-  struct TicketReference *tr_tmp;
-  if (NULL != handle->attrs)
-    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
   if (NULL != handle->ns_qe)
     GNUNET_NAMESTORE_cancel (handle->ns_qe);
-  for (tr = handle->ticket_refs_head; NULL != tr;)
-  {
-    if (NULL != tr->attrs)
-      GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
-    tr_tmp = tr;
-    tr = tr->next;
-    GNUNET_free (tr_tmp);
-  }
   GNUNET_free (handle);
 }
 
 
-
-static void
-store_ticket_refs_cont (void *cls,
-                        int32_t success,
-                        const char *emsg)
-{
-  struct TicketIssueHandle *handle = cls;
-  handle->ns_qe = NULL;
-  if (GNUNET_OK != success)
-  {
-    handle->cb (handle->cb_cls,
-                NULL,
-                GNUNET_SYSERR,
-                "Error storing updated ticket refs in GNS");
-    cleanup_issue_handle (handle);
-    return;
-  }
-  handle->cb (handle->cb_cls,
-              &handle->ticket,
-              GNUNET_OK,
-              NULL);
-  cleanup_issue_handle (handle);
-}
-
-
-
 static void
-update_ticket_refs (void* cls)
-{
-  struct TicketIssueHandle *handle = cls;
-  struct GNUNET_GNSRECORD_Data refs_rd[handle->ticket_ref_num];
-  struct TicketReference *tr;
-  char* buf;
-  size_t buf_size;
-
-  tr = handle->ticket_refs_head;
-  for (int i = 0; i < handle->ticket_ref_num; i++)
-  {
-    buf_size = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (tr->attrs);
-    buf_size += sizeof (struct GNUNET_RECLAIM_Ticket);
-    buf = GNUNET_malloc (buf_size);
-    memcpy (buf, &tr->ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
-    GNUNET_RECLAIM_ATTRIBUTE_list_serialize (tr->attrs,
-                                             buf + sizeof (struct GNUNET_RECLAIM_Ticket));
-    refs_rd[i].data = buf;
-    refs_rd[i].data_size = buf_size;
-    refs_rd[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
-    refs_rd[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF;
-    refs_rd[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION |
-      GNUNET_GNSRECORD_RF_PRIVATE;
-    tr = tr->next;
-  }
-
-  handle->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
-                                                  &handle->identity,
-                                                  GNUNET_GNS_EMPTY_LABEL_AT,
-                                                  handle->ticket_ref_num,
-                                                  refs_rd,
-                                                  &store_ticket_refs_cont,
-                                                  handle);
-  for (int i = 0; i < handle->ticket_ref_num; i++)
-    GNUNET_free ((char*)refs_rd[i].data);
-}
-
-
-
-static void
-ticket_lookup_cb (void *cls,
-                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                  const char *label,
-                  unsigned int rd_count,
-                  const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct TicketIssueHandle *handle = cls;
-  struct TicketReference *tr;
-  const char* attr_data;
-  size_t attr_data_len;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received tickets from local namestore.\n");
-  handle->ns_qe = NULL;
-  for (int i = 0; i < rd_count; i++)
-  {
-    if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
-      continue;
-    tr = GNUNET_new (struct TicketReference);
-    memcpy (&tr->ticket, rd[i].data,
-            sizeof (struct GNUNET_RECLAIM_Ticket));
-    if (0 != memcmp (&tr->ticket.identity,
-                     &handle->ticket.identity,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-    {
-      //Not our ticket
-      GNUNET_free (tr);
-      continue;
-    }
-    attr_data = rd[i].data + sizeof (struct GNUNET_RECLAIM_Ticket);
-    attr_data_len = rd[i].data_size - sizeof (struct GNUNET_RECLAIM_Ticket);
-    tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attr_data,
-                                                           attr_data_len);
-    GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
-                                 handle->ticket_refs_tail,
-                                 tr);
-    handle->ticket_ref_num++;
-  }
-  tr = GNUNET_new (struct TicketReference);
-  tr->ticket = handle->ticket;
-  tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (handle->attrs);
-  GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
-                               handle->ticket_refs_tail,
-                               tr);
-  handle->ticket_ref_num++;
-  GNUNET_SCHEDULER_add_now (&update_ticket_refs, handle);
-}
-
-static void
-ticket_lookup_error_cb (void *cls)
-{
-  struct TicketIssueHandle *handle = cls;
-  handle->ns_qe = NULL;
-  handle->cb (handle->cb_cls,
-              &handle->ticket,
-              GNUNET_SYSERR,
-              "Error checking for ticketsin GNS\n");
-  cleanup_issue_handle (handle);
-}
-
-static void
-store_ticket_issue_cont (void *cls,
-                         int32_t success,
-                         const char *emsg)
+store_ticket_issue_cont (void *cls, int32_t success, const char *emsg)
 {
   struct TicketIssueHandle *handle = cls;
 
@@ -690,132 +962,64 @@ store_ticket_issue_cont (void *cls,
                 "Error storing AuthZ ticket in GNS");
     return;
   }
-  /* First, local references to tickets */
-  handle->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
-                                                   &handle->identity,
-                                                   GNUNET_GNS_EMPTY_LABEL_AT,
-                                                   &ticket_lookup_error_cb,
-                                                   handle,
-                                                   &ticket_lookup_cb,
-                                                   handle);
-}
-
-
-static int
-serialize_authz_record (const struct GNUNET_RECLAIM_Ticket *ticket,
-                        const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
-                        struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
-                        char **result)
-{
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-  struct GNUNET_HashCode new_key_hash;
-  ssize_t enc_size;
-  char *enc_keyinfo;
-  char *buf;
-  char *write_ptr;
-  char attrs_str_len;
-  char* label;
-
-  GNUNET_assert (NULL != attrs->list_head);
-  attrs_str_len = 0;
-  for (le = attrs->list_head; NULL != le; le = le->next) {
-    attrs_str_len += 15 + 1; //TODO propery calculate
-  }
-  buf = GNUNET_malloc (attrs_str_len);
-  write_ptr = buf;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Writing attributes\n");
-  for (le = attrs->list_head; NULL != le; le = le->next) {
-    label = GNUNET_STRINGS_data_to_string_alloc (&le->claim->id,
-                                                 sizeof (uint64_t));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Adding attribute to record: %s\n", label);
-
-    GNUNET_memcpy (write_ptr,
-                   label,
-                   strlen (label));
-    write_ptr[strlen (label)] = ',';
-    write_ptr += strlen (label) + 1;
-    GNUNET_free (label);
-  }
-  write_ptr--;
-  write_ptr[0] = '\0'; //replace last , with a 0-terminator
-  // ECDH keypair E = eG
-  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
-  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
-                                      &ecdh_pubkey);
-  enc_keyinfo = GNUNET_malloc (attrs_str_len);
-  // Derived key K = H(eB)
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
-                                                        &ticket->audience,
-                                                        &new_key_hash));
-  create_sym_key_from_ecdh (&new_key_hash, &skey, &iv);
-  enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
-                                              attrs_str_len,
-                                              &skey, &iv,
-                                              enc_keyinfo);
-  *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
-                           enc_size);
-  GNUNET_memcpy (*result,
-                 &ecdh_pubkey,
-                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
-                 enc_keyinfo,
-                 enc_size);
-  GNUNET_free (enc_keyinfo);
-  GNUNET_free (buf);
-  return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
+  handle->cb (handle->cb_cls, &handle->ticket, GNUNET_OK, NULL);
+  cleanup_issue_handle (handle);
 }
 
 
-
 static void
 issue_ticket (struct TicketIssueHandle *ih)
 {
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
-  struct GNUNET_GNSRECORD_Data code_record[1];
-  char *authz_record_data;
-  size_t authz_record_len;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_GNSRECORD_Data *attrs_record;
   char *label;
+  size_t list_len = 1;
+  int i;
 
-  //TODO rename function
-  authz_record_len = serialize_authz_record (&ih->ticket,
-                                             ih->attrs,
-                                             &ecdhe_privkey,
-                                             &authz_record_data);
-  code_record[0].data = authz_record_data;
-  code_record[0].data_size = authz_record_len;
-  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
-  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ;
-  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-
-  label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
-                                               sizeof (uint64_t));
-  //Publish record
+  for (le = ih->attrs->list_head; NULL != le; le = le->next)
+    list_len++;
+
+  attrs_record =
+    GNUNET_malloc (list_len * sizeof (struct GNUNET_GNSRECORD_Data));
+  i = 0;
+  for (le = ih->attrs->list_head; NULL != le; le = le->next)
+  {
+    attrs_record[i].data = &le->claim->id;
+    attrs_record[i].data_size = sizeof (le->claim->id);
+    //FIXME: Should this be the attribute expiration time or ticket refresh intv
+    attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
+    attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF;
+    attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+    i++;
+  }
+  attrs_record[i].data = &ih->ticket;
+  attrs_record[i].data_size = sizeof (struct GNUNET_RECLAIM_Ticket);
+  attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
+  attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET;
+  attrs_record[i].flags =
+    GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
+
+  label =
+    GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, sizeof (uint64_t));
+  // Publish record
   ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
                                               &ih->identity,
                                               label,
-                                              1,
-                                              code_record,
+                                              list_len,
+                                              attrs_record,
                                               &store_ticket_issue_cont,
                                               ih);
-  GNUNET_free (ecdhe_privkey);
+  GNUNET_free (attrs_record);
   GNUNET_free (label);
-  GNUNET_free (authz_record_data);
 }
 
 
-
-
 void
 RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
                        const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
                        const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
                        RECLAIM_TICKETS_TicketResult cb,
-                       voidcb_cls)
+                       void *cb_cls)
 {
   struct TicketIssueHandle *tih;
   tih = GNUNET_new (struct TicketIssueHandle);
@@ -823,11 +1027,9 @@ RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
   tih->cb_cls = cb_cls;
   tih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
   tih->identity = *identity;
-  GNUNET_CRYPTO_ecdsa_key_get_public (identity,
-                                      &tih->ticket.identity);
+  GNUNET_CRYPTO_ecdsa_key_get_public (identity, &tih->ticket.identity);
   tih->ticket.rnd =
-    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
-                              UINT64_MAX);
+    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
   tih->ticket.audience = *audience;
   issue_ticket (tih);
 }
@@ -839,55 +1041,11 @@ RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
 static void
 cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter)
 {
-  struct TicketReference *tr;
-  struct TicketReference *tr_tmp;
-  if (NULL != iter->ns_qe)
-    GNUNET_NAMESTORE_cancel (iter->ns_qe);
-  for (tr = iter->tickets_head; NULL != tr;)
-  {
-    if (NULL != tr->attrs)
-      GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
-    tr_tmp = tr;
-    tr = tr->next;
-    GNUNET_free (tr_tmp);
-  }
+  if (NULL != iter->ns_it)
+    GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
   GNUNET_free (iter);
 }
 
-static void
-do_cleanup_iter (void* cls)
-{
-  struct RECLAIM_TICKETS_Iterator *iter = cls;
-  cleanup_iter (iter);
-}
-
-/**
- * Perform ticket iteration step
- *
- * @param ti ticket iterator to process
- */
-static void
-run_ticket_iteration_round (struct RECLAIM_TICKETS_Iterator *iter)
-{
-  struct TicketReference *tr;
-  if (NULL == iter->tickets_head)
-  {
-    //No more tickets
-    iter->cb (iter->cb_cls,
-              NULL);
-    GNUNET_SCHEDULER_add_now (&do_cleanup_iter, iter);
-    return;
-  }
-  tr = iter->tickets_head;
-  GNUNET_CONTAINER_DLL_remove (iter->tickets_head,
-                               iter->tickets_tail,
-                               tr);
-  iter->cb (iter->cb_cls,
-            &tr->ticket);
-  if (NULL != tr->attrs)
-    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
-  GNUNET_free (tr);
-}
 
 static void
 collect_tickets_cb (void *cls,
@@ -897,89 +1055,97 @@ collect_tickets_cb (void *cls,
                     const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct RECLAIM_TICKETS_Iterator *iter = cls;
-  struct TicketReference *tr;
-  size_t attr_data_len;
-  const char* attr_data;
-  iter->ns_qe = NULL;
 
   for (int i = 0; i < rd_count; i++)
   {
-    if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET != rd[i].record_type)
       continue;
-    tr = GNUNET_new (struct TicketReference);
-    memcpy (&tr->ticket, rd[i].data,
-            sizeof (struct GNUNET_RECLAIM_Ticket));
-    if (0 != memcmp (&tr->ticket.identity,
-                     &iter->identity_pub,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-    {
-      //Not our ticket
-      GNUNET_free (tr);
-      continue;
-    }
-    attr_data = rd[i].data + sizeof (struct GNUNET_RECLAIM_Ticket);
-    attr_data_len = rd[i].data_size - sizeof (struct GNUNET_RECLAIM_Ticket);
-    tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attr_data,
-                                                           attr_data_len);
-    GNUNET_CONTAINER_DLL_insert (iter->tickets_head,
-                                 iter->tickets_tail,
-                                 tr);
+    iter->cb (iter->cb_cls, (struct GNUNET_RECLAIM_Ticket *) rd[i].data);
+    return;
   }
-  run_ticket_iteration_round (iter);
+  GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
+}
+
+
+static void
+collect_tickets_finished_cb (void *cls)
+{
+  struct RECLAIM_TICKETS_Iterator *iter = cls;
+  iter->ns_it = NULL;
+  iter->cb (iter->cb_cls, NULL);
+  cleanup_iter (iter);
 }
 
+
 static void
 collect_tickets_error_cb (void *cls)
 {
   struct RECLAIM_TICKETS_Iterator *iter = cls;
-  iter->ns_qe = NULL;
-  iter->cb (iter->cb_cls,
-            NULL);
+  iter->ns_it = NULL;
+  iter->cb (iter->cb_cls, NULL);
   cleanup_iter (iter);
 }
 
+
 void
 RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter)
 {
-  run_ticket_iteration_round (iter);
+  GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1);
 }
 
+
 void
 RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter)
 {
+  GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it);
   cleanup_iter (iter);
 }
 
-struct RECLAIM_TICKETS_Iterator*
-RECLAIM_TICKETS_iteration_start (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-                                 RECLAIM_TICKETS_TicketIter cb,
-                                 void* cb_cls)
+
+struct RECLAIM_TICKETS_Iterator *
+RECLAIM_TICKETS_iteration_start (
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+  RECLAIM_TICKETS_TicketIter cb,
+  void *cb_cls)
 {
   struct RECLAIM_TICKETS_Iterator *iter;
 
   iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator);
-  iter->identity = *identity;
-  GNUNET_CRYPTO_ecdsa_key_get_public (identity,
-                                      &iter->identity_pub);
   iter->cb = cb;
   iter->cb_cls = cb_cls;
-  iter->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
-                                                 identity,
-                                                 GNUNET_GNS_EMPTY_LABEL_AT,
-                                                 &collect_tickets_error_cb,
-                                                 iter,
-                                                 &collect_tickets_cb,
-                                                 iter);
+  iter->ns_it =
+    GNUNET_NAMESTORE_zone_iteration_start (nsh,
+                                           identity,
+                                           &collect_tickets_error_cb,
+                                           iter,
+                                           &collect_tickets_cb,
+                                           iter,
+                                           &collect_tickets_finished_cb,
+                                           iter);
   return iter;
 }
 
 
-
-
 int
 RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  //Connect to identity and namestore services
+  // Get ticket expiration time (relative) from config
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_time (c,
+                                           "reclaim",
+                                           "TICKET_REFRESH_INTERVAL",
+                                           &ticket_refresh_interval))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Configured refresh interval for tickets: %s\n",
+                GNUNET_STRINGS_relative_time_to_string (ticket_refresh_interval,
+                                                        GNUNET_YES));
+  }
+  else
+  {
+    ticket_refresh_interval = DEFAULT_TICKET_REFRESH_INTERVAL;
+  }
+  // Connect to identity and namestore services
   nsh = GNUNET_NAMESTORE_connect (c);
   if (NULL == nsh)
   {
@@ -990,8 +1156,7 @@ RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
   gns = GNUNET_GNS_connect (c);
   if (NULL == gns)
   {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-                         "error connecting to gns");
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
     return GNUNET_SYSERR;
   }
   stats = GNUNET_STATISTICS_create ("reclaim", c);