gnunet-svn
[Top][All Lists]
Advanced

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

[taler-donau] branch master updated: [lib] some changes [testing] try to


From: gnunet
Subject: [taler-donau] branch master updated: [lib] some changes [testing] try to set up client test
Date: Fri, 05 Jan 2024 21:51:12 +0100

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

lukas-matyja pushed a commit to branch master
in repository donau.

The following commit(s) were added to refs/heads/master by this push:
     new 52e2d2c  [lib] some changes [testing] try to set up client test
     new a75ce44  Merge remote-tracking branch 'refs/remotes/origin/master'
52e2d2c is described below

commit 52e2d2c22b1d86b65cf2ed823a4057a9ab7f7f84
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
AuthorDate: Fri Jan 5 21:51:41 2024 +0100

    [lib] some changes [testing] try to set up client test
---
 src/include/donau_service.h          |    4 +-
 src/lib/Makefile.am                  |   34 +-
 src/lib/donau_api_handle.c           |  194 +-----
 src/testing/Makefile.am              |   41 ++
 src/testing/test_api_cmd_get_donau.c |  355 ++++++++++
 src/testing/test_donau_api.c         | 1203 +++++++++++++++++++++++++++++++++-
 6 files changed, 1639 insertions(+), 192 deletions(-)

diff --git a/src/include/donau_service.h b/src/include/donau_service.h
index a501aa6..e6a3c17 100644
--- a/src/include/donau_service.h
+++ b/src/include/donau_service.h
@@ -311,7 +311,7 @@ struct DONAU_GetKeysHandle *
 DONAU_get_keys (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  struct DONAU_Keys *last_keys,
+  //struct DONAU_Keys *last_keys, -> temporarily removed
   DONAU_GetKeysCallback cert_cb,
   void *cert_cb_cls);
 
@@ -367,7 +367,7 @@ void
 DONAU_keys_decref (struct DONAU_Keys *keys);
 
 /**
- * Test if the given @a pub is a the current signing key from the donau
+ * Test if the given @a pub is a current signing key from the donau
  * according to @a keys.
  *
  * @param keys the donau's key set
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 10ae4aa..a2ad6c3 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -13,20 +13,22 @@ endif
 
 # Libraries
 
-#lib_LTLIBRARIES = \
-#      libdonau.la
-#
-#libdonau_la_LDFLAGS = \
-#      -version-info 5:0:0 \
-#      -no-undefined
-#
+lib_LTLIBRARIES = \
+       libtalerdonau.la
+
+libdonau_la_LDFLAGS = \
+       -version-info 5:0:0 \
+       -no-undefined
+libtalerexchange_la_SOURCES = \
+  exchange_api_handle.c exchange_api_handle.h 
+ 
 ## maybe need libtalercurl
-#libdonau_la_LIBADD = \
-#      $(top_builddir)/src/json/libtalerjson.la \
-#      $(top_builddir)/src/util/libdonauutil.la \
-#      -lgnunetcurl \
-#      -lgnunetjson \
-#      -lgnunetutil \
-#      -ljansson \
-#      $(LIBGNURLCURL_LIBS) \
-#      $(XLIB)
+libdonau_la_LIBADD = \
+       $(top_builddir)/src/json/libtalerjson.la \
+       $(top_builddir)/src/util/libdonauutil.la \
+       -lgnunetcurl \
+       -lgnunetjson \
+       -lgnunetutil \
+       -ljansson \
+       $(LIBGNURLCURL_LIBS) \
+       $(XLIB)
diff --git a/src/lib/donau_api_handle.c b/src/lib/donau_api_handle.c
index 8c720bb..ae563bd 100644
--- a/src/lib/donau_api_handle.c
+++ b/src/lib/donau_api_handle.c
@@ -133,24 +133,18 @@ struct DONAU_GetKeysHandle
  *
  * @param[out] sign_key where to return the result
  * @param sign_key_obj json to parse
- * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
- *        invalid or the @a sign_key_obj is malformed.
+ * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if @a sign_key_obj 
+ * is malformed.
  */
 static enum GNUNET_GenericReturnValue
 parse_json_signkey (struct DONAU_SigningPublicKeyAndValidity *sign_key,
                     const json_t *sign_key_obj)
 {
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_fixed_auto ("master_sig",
-                                 &sign_key->master_sig),
     GNUNET_JSON_spec_fixed_auto ("key",
                                  &sign_key->key),
-    GNUNET_JSON_spec_timestamp ("stamp_start",
-                                &sign_key->valid_from),
-    GNUNET_JSON_spec_timestamp ("stamp_expire",
-                                &sign_key->valid_until),
-    GNUNET_JSON_spec_timestamp ("stamp_end",
-                                &sign_key->valid_legal),
+    GNUNET_JSON_spec_varsize ("year_of_validity",
+                                &sign_key->year)
     GNUNET_JSON_spec_end ()
   };
 
@@ -162,106 +156,7 @@ parse_json_signkey (struct 
DONAU_SigningPublicKeyAndValidity *sign_key,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  if (! check_sigs)
-    return GNUNET_OK;
-  if (GNUNET_OK !=
-      TALER_donau_offline_signkey_validity_verify (
-        &sign_key->key,
-        sign_key->valid_from,
-        sign_key->valid_until,
-        sign_key->valid_legal,
-        master_key,
-        &sign_key->master_sig))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Parse a donau's denomination key encoded in JSON partially.
- *
- * Only the values for master_sig, timestamps and the cipher-specific public
- * key are parsed.  All other fields (fees, age_mask, value) MUST have been set
- * prior to calling this function, otherwise the signature verification
- * performed within this function will fail.
- *
- * @param[out] denom_key where to return the result
- * @param cipher cipher type to parse
- * @param check_sigs should we check signatures?
- * @param denom_key_obj json to parse
- * @param master_key master key to use to verify signature
- * @param[in,out] hash_xor where to accumulate data for signature verification 
via XOR
- * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
- *        invalid or the json malformed.
- */
-static enum GNUNET_GenericReturnValue
-parse_json_denomkey_partially (
-  struct DONAU_DenomPublicKey *denom_key,
-  enum TALER_DenominationCipher cipher,
-  bool check_sigs,
-  const json_t *denom_key_obj,
-  struct TALER_MasterPublicKeyP *master_key,
-  struct GNUNET_HashCode *hash_xor)
-{
-  struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_fixed_auto ("master_sig",
-                                 &denom_key->master_sig),
-    GNUNET_JSON_spec_timestamp ("stamp_expire_deposit",
-                                &denom_key->expire_deposit),
-    GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
-                                &denom_key->withdraw_valid_until),
-    GNUNET_JSON_spec_timestamp ("stamp_start",
-                                &denom_key->valid_from),
-    GNUNET_JSON_spec_timestamp ("stamp_expire_legal",
-                                &denom_key->expire_legal),
-    GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_bool ("lost",
-                             &denom_key->lost),
-      NULL),
-    TALER_JSON_spec_denom_pub_cipher (NULL,
-                                      cipher,
-                                      &denom_key->key),
-    GNUNET_JSON_spec_end ()
-  };
-
-  if (GNUNET_OK !=
-      GNUNET_JSON_parse (denom_key_obj,
-                         spec,
-                         NULL, NULL))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  TALER_denom_pub_hash (&denom_key->key,
-                        &denom_key->h_key);
-  if (NULL != hash_xor)
-    GNUNET_CRYPTO_hash_xor (&denom_key->h_key.hash,
-                            hash_xor,
-                            hash_xor);
-  if (! check_sigs)
-    return GNUNET_OK;
-  EXITIF (GNUNET_SYSERR ==
-          TALER_donau_offline_denom_validity_verify (
-            &denom_key->h_key,
-            denom_key->valid_from,
-            denom_key->withdraw_valid_until,
-            denom_key->expire_deposit,
-            denom_key->expire_legal,
-            &denom_key->value,
-            &denom_key->fees,
-            master_key,
-            &denom_key->master_sig));
   return GNUNET_OK;
-EXITIF_exit:
-  /* invalidate denom_key, just to be sure */
-  memset (denom_key,
-          0,
-          sizeof (*denom_key));
-  GNUNET_JSON_parse_free (spec);
-  return GNUNET_SYSERR;
 }
 
 
@@ -270,7 +165,6 @@ EXITIF_exit:
  * and store the data in the @a key_data.
  *
  * @param[in] resp_obj JSON object to parse
- * @param check_sig true if we should check the signature
  * @param[out] key_data where to store the results we decoded
  * @param[out] vc where to store version compatibility data
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
@@ -278,15 +172,12 @@ EXITIF_exit:
  */
 static enum GNUNET_GenericReturnValue
 decode_keys_json (const json_t *resp_obj,
-                  bool check_sig,
                   struct DONAU_Keys *key_data,
                   enum DONAU_VersionCompatibility *vc)
 {
-  struct TALER_DonauSignatureP denominations_sig;
   struct DONAU_DonauPublicKeyP pub;
-  const json_t *sign_keys_array;
+  //const json_t *sign_keys_array;
   const json_t *donation_units_by_group;
-  bool no_signature = false;
 
   if (JSON_OBJECT != json_typeof (resp_obj))
   {
@@ -350,8 +241,8 @@ decode_keys_json (const json_t *resp_obj,
     const char *asset_type;
     struct GNUNET_JSON_Specification mspec[] = {
       GNUNET_JSON_spec_fixed_auto (
-        "denominations_sig",
-        &denominations_sig),
+        "donation_units_sig",
+        &donation_units_sig),
       GNUNET_JSON_spec_fixed_auto (
         "eddsa_pub",
         &pub),
@@ -386,8 +277,8 @@ decode_keys_json (const json_t *resp_obj,
         "signkeys",
         &sign_keys_array),
       GNUNET_JSON_spec_array_const (
-        "denominations",
-        &denominations_by_group),
+        "donation_units",
+        &donation_units_by_group),
       GNUNET_JSON_spec_mark_optional (
         GNUNET_JSON_spec_array_const (
           "recoup",
@@ -461,27 +352,6 @@ decode_keys_json (const json_t *resp_obj,
       key_data->extensions = json_incref ((json_t *) manifests);
   }
 
-  /* parse the global fees */
-  key_data->num_global_fees
-    = json_array_size (global_fees);
-  if (0 != key_data->num_global_fees)
-  {
-    json_t *global_fee;
-    unsigned int index;
-
-    key_data->global_fees
-      = GNUNET_new_array (key_data->num_global_fees,
-                          struct DONAU_GlobalFee);
-    json_array_foreach (global_fees, index, global_fee)
-    {
-      EXITIF (GNUNET_SYSERR ==
-              parse_global_fee (&key_data->global_fees[index],
-                                check_sig,
-                                global_fee,
-                                key_data));
-    }
-  }
-
   /* parse the signing keys */
   key_data->num_sign_keys
     = json_array_size (sign_keys_array);
@@ -577,19 +447,19 @@ decode_keys_json (const json_t *resp_obj,
   }
 
   /*
-   * Parse the denomination keys, merging with the
+   * Parse the donation unit keys, merging with the
    * possibly EXISTING array as required (/keys cherry picking).
    *
-   * The denominations are grouped by common values of
+   * The donation units are grouped by common values of
    *    {cipher, value, fee, age_mask}.
    */
   {
     json_t *group_obj;
     unsigned int group_idx;
 
-    json_array_foreach (denominations_by_group, group_idx, group_obj)
+    json_array_foreach (donation_units_by_group, group_idx, group_obj)
     {
-      /* Running XOR of each SHA512 hash of the denominations' public key in
+      /* Running XOR of each SHA512 hash of the donation units' public key in
          this group.  Used to compare against group.hash after all keys have
          been parsed. */
       struct GNUNET_HashCode group_hash_xor = {0};
@@ -599,7 +469,7 @@ decode_keys_json (const json_t *resp_obj,
       struct TALER_DenominationGroup group = {0};
       const json_t *denom_keys_array;
       struct GNUNET_JSON_Specification group_spec[] = {
-        TALER_JSON_spec_denomination_group (NULL,
+        TALER_JSON_spec_donation_unit_group (NULL,
                                             key_data->currency,
                                             &group),
         GNUNET_JSON_spec_array_const ("denoms",
@@ -615,11 +485,11 @@ decode_keys_json (const json_t *resp_obj,
                                  NULL,
                                  NULL));
 
-      /* Now, parse the individual denominations */
+      /* Now, parse the individual donation units */
       json_array_foreach (denom_keys_array, index, denom_key_obj)
       {
         /* Set the common fields from the group for this particular
-           denomination.  Required to make the validity check inside
+           donation unit.  Required to make the validity check inside
            parse_json_denomkey_partially pass */
         struct DONAU_DenomPublicKey dk = {
           .key.cipher = group.cipher,
@@ -629,8 +499,8 @@ decode_keys_json (const json_t *resp_obj,
         };
         bool found = false;
 
-        EXITIF (GNUNET_SYSERR ==
-                parse_json_denomkey_partially (&dk,
+        EXITIF (GNUNET_SYSERR == //was partially
+                parse_json_donation_unit_key (&dk,
                                                group.cipher,
                                                check_sig,
                                                denom_key_obj,
@@ -656,7 +526,7 @@ decode_keys_json (const json_t *resp_obj,
         if (found)
         {
           /* 0:0:0 did not support /keys cherry picking */
-          TALER_LOG_DEBUG ("Skipping denomination key: already know it\n");
+          TALER_LOG_DEBUG ("Skipping donation unit key: already know it\n");
           TALER_denom_pub_free (&dk.key);
           continue;
         }
@@ -668,12 +538,12 @@ decode_keys_json (const json_t *resp_obj,
         key_data->denom_keys[key_data->num_denom_keys++] = dk;
 
         /* Update "last_denom_issue_date" */
-        TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n",
+        TALER_LOG_DEBUG ("Adding donation unit key that is valid_until %s\n",
                          GNUNET_TIME_timestamp2s (dk.valid_from));
         key_data->last_denom_issue_date
           = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date,
                                        dk.valid_from);
-      };   /* end of json_array_foreach over denominations */
+      };   /* end of json_array_foreach over donation units */
 
       /* The calculated group_hash_xor must be the same as group.hash from
          the JSON. */
@@ -681,7 +551,7 @@ decode_keys_json (const json_t *resp_obj,
               GNUNET_CRYPTO_hash_cmp (&group_hash_xor,
                                       &group.hash));
 
-    } /* end of json_array_foreach over groups of denominations */
+    } /* end of json_array_foreach over groups of donation units */
   } /* end of scope for group_ojb/group_idx */
 
   /* parse the auditor information */
@@ -711,7 +581,7 @@ decode_keys_json (const json_t *resp_obj,
                                 &aix->auditor_pub))
         {
           found = true;
-          /* Merge denomination key signatures of downloaded /keys into 
existing
+          /* Merge donation unit key signatures of downloaded /keys into 
existing
              auditor information 'aix'. */
           TALER_LOG_DEBUG (
             "Merging %u new audited keys with %u known audited keys\n",
@@ -798,7 +668,7 @@ decode_keys_json (const json_t *resp_obj,
               key_data->list_issue_date,
               &hash_xor,
               &pub,
-              &denominations_sig));
+              &donation_units_sig));
   }
   return GNUNET_OK;
 
@@ -866,7 +736,7 @@ keys_completed_cb (void *cls,
     {
       const struct DONAU_Keys *kd_old = gkh->prev_keys;
 
-      /* We keep the denomination keys and auditor signatures from the
+      /* We keep the donation unit keys and auditor signatures from the
          previous iteration (/keys cherry picking) */
       kd->num_denom_keys
         = kd_old->num_denom_keys;
@@ -1130,7 +1000,7 @@ struct DONAU_GetKeysHandle *
 DONAU_get_keys (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  struct DONAU_Keys *last_keys,
+  //struct DONAU_Keys *last_keys, -> temporarily removed
   DONAU_GetKeysCallback cert_cb,
   void *cert_cb_cls)
 {
@@ -1228,7 +1098,7 @@ DONAU_test_signing_key (
 
 
 const struct DONAU_DenomPublicKey *
-DONAU_get_denomination_key (
+DONAU_get_donation_unit_key (
   const struct DONAU_Keys *keys,
   const struct TALER_DenominationPublicKey *pk)
 {
@@ -1242,7 +1112,7 @@ DONAU_get_denomination_key (
 
 
 struct DONAU_DenomPublicKey *
-DONAU_copy_denomination_key (
+DONAU_copy_donation_unit_key (
   const struct DONAU_DenomPublicKey *key)
 {
   struct DONAU_DenomPublicKey *copy;
@@ -1256,7 +1126,7 @@ DONAU_copy_denomination_key (
 
 
 void
-DONAU_destroy_denomination_key (
+DONAU_destroy_donation_unit_key (
   struct DONAU_DenomPublicKey *key)
 {
   TALER_denom_pub_free (&key->key);
@@ -1265,7 +1135,7 @@ DONAU_destroy_denomination_key (
 
 
 const struct DONAU_DenomPublicKey *
-DONAU_get_denomination_key_by_hash (
+DONAU_get_donation_unit_key_by_hash (
   const struct DONAU_Keys *keys,
   const struct TALER_DenominationHashP *hc)
 {
@@ -1645,7 +1515,7 @@ DONAU_keys_to_json (const struct DONAU_Keys *kd)
       if (GNUNET_TIME_timestamp_cmp (now,
                                      >,
                                      dk->expire_deposit))
-        continue; /* skip auditor signatures for denomination keys that have 
expired */
+        continue; /* skip auditor signatures for donation unit keys that have 
expired */
       GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys);
       k = GNUNET_JSON_PACK (
         GNUNET_JSON_pack_data_auto ("denom_pub_h",
@@ -1662,7 +1532,7 @@ DONAU_keys_to_json (const struct DONAU_Keys *kd)
                                   &ai->auditor_pub),
       GNUNET_JSON_pack_string ("auditor_url",
                                ai->auditor_url),
-      GNUNET_JSON_pack_array_steal ("denomination_keys",
+      GNUNET_JSON_pack_array_steal ("donation_unit_keys",
                                     adenoms));
     GNUNET_assert (0 ==
                    json_array_append_new (auditors,
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 35adc65..42c25e1 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -12,3 +12,44 @@ endif
 
 clean-local:
        rm -rf report*
+
+bin_SCRIPTS = \
+  donau-unified-setup.sh
+
+libtalertesting_la_LDFLAGS = \
+  -version-info 0:0:0 \
+  -no-undefined
+libtalertesting_la_SOURCES = \
+  testing_api_cmd_get_exchange.c 
+
+test_exchange_api_cs_SOURCES = \
+  test_exchange_api.c
+test_exchange_api_cs_LDADD = \
+  libtalertesting.la \
+  $(top_builddir)/src/lib/libtalerdonau.la \
+  $(LIBGCRYPT_LIBS) \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  -lgnunetcurl \
+  -lgnunetutil \
+  -ljansson \
+  $(XLIB)
+
+test_exchange_api_rsa_SOURCES = \
+  test_exchange_api.c
+test_exchange_api_rsa_LDADD = \
+  libtalertesting.la \
+  $(top_builddir)/src/lib/libtalerdonau.la \
+  $(LIBGCRYPT_LIBS) \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  -lgnunetcurl \
+  -lgnunetutil \
+  -ljansson \
+  $(XLIB)
+
+  EXTRA_DIST = \
+  $(bin_SCRIPTS) \
+  coins-cs.conf \
+  coins-rsa.conf \
+  test_exchange_api.conf
\ No newline at end of file
diff --git a/src/testing/test_api_cmd_get_donau.c 
b/src/testing/test_api_cmd_get_donau.c
new file mode 100644
index 0000000..d0fc638
--- /dev/null
+++ b/src/testing/test_api_cmd_get_donau.c
@@ -0,0 +1,355 @@
+/*
+  This file is part of TALER
+  (C) 2023 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 3, or
+  (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file testing/testing_api_cmd_get_donau.c
+ * @brief Command to get an donau handle
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+
+
+/**
+ * State for a "get donau" CMD.
+ */
+struct GetExchangeState
+{
+
+  /**
+   * Our interpreter state.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * Exchange handle we produced.
+   */
+  struct TALER_EXCHANGE_GetKeysHandle *donau;
+
+  /**
+   * Keys of the donau.
+   */
+  struct TALER_EXCHANGE_Keys *keys;
+
+  /**
+   * URL of the donau.
+   */
+  char *donau_url;
+
+  /**
+   * Label of a command to use to obtain existing
+   * keys.
+   */
+  const char *last_keys_ref;
+
+  /**
+   * Last denomination date we received when doing this request.
+   */
+  struct GNUNET_TIME_Timestamp my_denom_date;
+
+  /**
+   * Are we waiting for /keys before continuing?
+   */
+  bool wait_for_keys;
+};
+
+
+/**
+ * Function called with information about what keys the donau is using.
+ *
+ * @param cls closure
+ * @param kr response from /keys
+ * @param[in] keys the keys of the donau
+ */
+static void
+cert_cb (void *cls,
+         const struct TALER_EXCHANGE_KeysResponse *kr,
+         struct TALER_EXCHANGE_Keys *keys)
+{
+  struct GetExchangeState *ges = cls;
+  const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr;
+  struct TALER_TESTING_Interpreter *is = ges->is;
+
+  ges->donau = NULL;
+  ges->keys = keys;
+  switch (hr->http_status)
+  {
+  case MHD_HTTP_OK:
+    if (ges->wait_for_keys)
+    {
+      ges->wait_for_keys = false;
+      TALER_TESTING_interpreter_next (is);
+      return;
+    }
+    ges->my_denom_date = kr->details.ok.keys->last_denom_issue_date;
+    return;
+  default:
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "/keys responded with HTTP status %u\n",
+                hr->http_status);
+    if (ges->wait_for_keys)
+    {
+      ges->wait_for_keys = false;
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    return;
+  }
+}
+
+
+/**
+ * Run the "get_donau" command.
+ *
+ * @param cls closure.
+ * @param cmd the command currently being executed.
+ * @param is the interpreter state.
+ */
+static void
+get_donau_run (void *cls,
+                  const struct TALER_TESTING_Command *cmd,
+                  struct TALER_TESTING_Interpreter *is)
+{
+  struct GetExchangeState *ges = cls;
+  struct TALER_EXCHANGE_Keys *xkeys = NULL;
+
+  (void) cmd;
+  if (NULL == ges->donau_url)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+  if (NULL != ges->last_keys_ref)
+  {
+    const struct TALER_TESTING_Command *state_cmd;
+    struct TALER_EXCHANGE_Keys *old_keys;
+    const char *donau_url;
+    json_t *s_keys;
+
+    state_cmd
+      = TALER_TESTING_interpreter_lookup_command (is,
+                                                  ges->last_keys_ref);
+    if (NULL == state_cmd)
+    {
+      /* Command providing serialized keys not found.  */
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_keys (state_cmd,
+                                      &old_keys))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    if (NULL == old_keys)
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_exchange_url (state_cmd,
+                                              &donau_url))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    if (0 != strcmp (donau_url,
+                     ges->donau_url))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    s_keys = TALER_EXCHANGE_keys_to_json (old_keys);
+    if (NULL == s_keys)
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    xkeys = TALER_EXCHANGE_keys_from_json (s_keys);
+    if (NULL == xkeys)
+    {
+      GNUNET_break (0);
+      json_dumpf (s_keys,
+                  stderr,
+                  JSON_INDENT (2));
+      json_decref (s_keys);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    json_decref (s_keys);
+  }
+
+  ges->is = is;
+  ges->donau
+    = TALER_EXCHANGE_get_keys (TALER_TESTING_interpreter_get_context (is),
+                               ges->donau_url,
+                               xkeys,
+                               &cert_cb,
+                               ges);
+  TALER_EXCHANGE_keys_decref (xkeys);
+  if (NULL == ges->donau)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+  if (! ges->wait_for_keys)
+    TALER_TESTING_interpreter_next (is);
+}
+
+
+/**
+ * Cleanup the state.
+ *
+ * @param cls closure.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+get_donau_cleanup (void *cls,
+                      const struct TALER_TESTING_Command *cmd)
+{
+  struct GetExchangeState *ges = cls;
+
+  if (NULL != ges->donau)
+  {
+    TALER_EXCHANGE_get_keys_cancel (ges->donau);
+    ges->donau = NULL;
+  }
+  TALER_EXCHANGE_keys_decref (ges->keys);
+  ges->keys = NULL;
+  GNUNET_free (ges->donau_url);
+  GNUNET_free (ges);
+}
+
+
+/**
+ * Offer internal data to a "get_donau" CMD state to other commands.
+ *
+ * @param cls closure
+ * @param[out] ret result (could be anything)
+ * @param trait name of the trait
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+get_donau_traits (void *cls,
+                     const void **ret,
+                     const char *trait,
+                     unsigned int index)
+{
+  struct GetExchangeState *ges = cls;
+  //unsigned int off = (NULL == ges->master_priv_file) ? 1 : 0;
+  unsigned int off = 1;
+
+  if (NULL != ges->keys)
+  {
+    struct TALER_TESTING_Trait traits[] = {
+      TALER_TESTING_make_trait_keys (ges->keys),
+      TALER_TESTING_make_trait_exchange_url (ges->donau_url),
+      TALER_TESTING_make_trait_timestamp (0,
+                                          &ges->my_denom_date),
+      TALER_TESTING_trait_end ()
+    };
+
+    return TALER_TESTING_get_trait (&traits[off],
+                                    ret,
+                                    trait,
+                                    index);
+  }
+  else
+  {
+    struct TALER_TESTING_Trait traits[] = {
+      TALER_TESTING_make_trait_exchange_url (ges->donau_url),
+      TALER_TESTING_make_trait_timestamp (0,
+                                          &ges->my_denom_date),
+      TALER_TESTING_trait_end ()
+    };
+
+    return TALER_TESTING_get_trait (&traits[off],
+                                    ret,
+                                    trait,
+                                    index);
+  }
+}
+
+
+/**
+ * Get the base URL of the donau from @a cfg.
+ *
+ * @param cfg configuration to evaluate
+ * @return base URL of the donau according to @a cfg
+ */
+static char *
+get_donau_base_url (
+  const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *donau_url;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "donau",
+                                             "BASE_URL",
+                                             &donau_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "donau",
+                               "BASE_URL");
+    return NULL;
+  }
+  return donau_url;
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_get_donau (
+  const char *label,
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *last_keys_ref,
+  bool wait_for_keys,
+  bool load_private_key)
+{
+  struct GetExchangeState *ges;
+
+  ges = GNUNET_new (struct GetExchangeState);
+  ges->donau_url = get_donau_base_url (cfg);
+  ges->last_keys_ref = last_keys_ref;
+  ges->wait_for_keys = wait_for_keys;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = ges,
+      .label = label,
+      .run = &get_donau_run,
+      .cleanup = &get_donau_cleanup,
+      .traits = &get_donau_traits,
+      .name = "donau"
+    };
+
+    return cmd;
+  }
+}
diff --git a/src/testing/test_donau_api.c b/src/testing/test_donau_api.c
index f926e53..7104dd3 100644
--- a/src/testing/test_donau_api.c
+++ b/src/testing/test_donau_api.c
@@ -9,7 +9,7 @@
 
   TALER is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
-  CHARITYABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public
@@ -17,22 +17,24 @@
   <http://www.gnu.org/licenses/>
 */
 /**
- * @file testing/test_donau_api.c
- * @brief testcase to test donau's HTTP API interface
+ * @file testing/test_exchange_api.c
+ * @brief testcase to test exchange's HTTP API interface
  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
  * @author Christian Grothoff
  * @author Marcello Stanisci
  */
 #include "taler/platform.h"
-#include <taler/taler_util.h>
+#include "taler/taler_util.h"
 #include "taler/taler_signatures.h"
-#include "donau_service.h"
+#include "taler/taler_exchange_service.h"
 #include "taler/taler_json_lib.h"
 #include <gnunet/gnunet_util_lib.h>
 #include <gnunet/gnunet_testing_lib.h>
 #include <microhttpd.h>
 #include "taler/taler_bank_service.h"
 #include "taler/taler_fakebank_lib.h"
+#include "taler/taler_testing_lib.h"
+#include "taler/taler_extensions.h"
 
 /**
  * Configuration file we use.  One (big) configuration is used
@@ -40,20 +42,59 @@
  */
 static char *config_file;
 
+/**
+ * Special configuration file to use when we want reserves
+ * to expire 'immediately'.
+ */
+static char *config_file_expire_reserve_now;
+
 /**
  * Our credentials.
  */
-static struct DONAU_TESTING_Credentials cred;
+static struct TALER_TESTING_Credentials cred;
 
 /**
  * Some tests behave differently when using CS as we cannot
- * re-use the coin private key for different denominations
+ * reuse the coin private key for different denominations
  * due to the derivation of it with the /csr values. Hence
  * some tests behave differently in CS mode, hence this
  * flag.
  */
 static bool uses_cs;
 
+/**
+ * Execute the taler-exchange-wirewatch command with
+ * our configuration file.
+ *
+ * @param label label to use for the command.
+ */
+#define CMD_EXEC_WIREWATCH(label) \
+  TALER_TESTING_cmd_exec_wirewatch2 (label, config_file, "exchange-account-2")
+
+/**
+ * Execute the taler-exchange-aggregator, closer and transfer commands with
+ * our configuration file.
+ *
+ * @param label label to use for the command.
+ */
+#define CMD_EXEC_AGGREGATOR(label) \
+  TALER_TESTING_cmd_sleep ("sleep-before-aggregator", 2), \
+  TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \
+  TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file)
+
+
+/**
+ * Run wire transfer of funds from some user's account to the
+ * exchange.
+ *
+ * @param label label to use for the command.
+ * @param amount amount to transfer, i.e. "EUR:1"
+ */
+#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
+  TALER_TESTING_cmd_admin_add_incoming (label, amount, \
+                                        &cred.ba,                \
+                                        cred.user42_payto)
+
 /**
  * Main function that will tell the interpreter what commands to
  * run.
@@ -63,9 +104,1144 @@ static bool uses_cs;
  */
 static void
 run (void *cls,
-     struct DONAU_TESTING_Interpreter *is)
+     struct TALER_TESTING_Interpreter *is)
 {
-  // tests
+  /**
+   * Test withdrawal plus spending.
+   */
+  //struct TALER_TESTING_Command withdraw[] = {
+    /**
+     * Move money to the exchange's bank account.
+     */
+  //   CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
+  //                             "EUR:6.02"),
+  //   TALER_TESTING_cmd_reserve_poll ("poll-reserve-1",
+  //                                   "create-reserve-1",
+  //                                   "EUR:6.02",
+  //                                   GNUNET_TIME_UNIT_MINUTES,
+  //                                   MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-1",
+  //                                                "EUR:6.02",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                "create-reserve-1"),
+  //   /**
+  //    * Make a reserve exist, according to the previous
+  //    * transfer.
+  //    */
+  //   D_EXEC_WIREWATCH ("wirewatch-1"),
+  //   TALER_TESTING_cmd_reserve_poll_finish ("finish-poll-reserve-1",
+  //                                          GNUNET_TIME_UNIT_SECONDS,
+  //                                          "poll-reserve-1"),
+  //   /**
+  //    * Withdraw EUR:5.
+  //    */
+  //   TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1",
+  //                                      "create-reserve-1",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   /**
+  //    * Withdraw EUR:1 using the SAME private coin key as for the previous 
coin
+  //    * (in violation of the specification, to be detected on spending!).
+  //    * However, note that this does NOT work with 'CS', as for a different
+  //    * denomination we get different R0/R1 values from the exchange, and
+  //    * thus will generate a different coin private key as R0/R1 are hashed
+  //    * into the coin priv. So here, we fail to 'reuse' the key due to the
+  //    * cryptographic construction!
+  //    */
+  //   TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x",
+  //                                                "create-reserve-1",
+  //                                                "EUR:1",
+  //                                                0, /* age restriction off 
*/
+  //                                                "withdraw-coin-1",
+  //                                                MHD_HTTP_OK),
+  //   /**
+  //    * Check the reserve is depleted.
+  //    */
+  //   TALER_TESTING_cmd_status ("status-1",
+  //                             "create-reserve-1",
+  //                             "EUR:0",
+  //                             MHD_HTTP_OK),
+  //   /*
+  //    * Try to overdraw.
+  //    */
+  //   TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2",
+  //                                      "create-reserve-1",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_CONFLICT),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // //struct TALER_TESTING_Command spend[] = {
+  //   /**
+  //    * Spend the coin.
+  //    */
+  //   //TALER_TESTING_cmd_deposit ("deposit-simple",
+  //                              "withdraw-coin-1",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:5",
+  //                              MHD_HTTP_OK),
+  //   //TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-1",
+  //                                     "deposit-simple",
+  //                                     MHD_HTTP_OK),
+  //   //TALER_TESTING_cmd_sleep ("sleep-before-deposit-replay",
+  //                            1),
+  //   //TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-2",
+  //                                     "deposit-simple",
+  //                                     MHD_HTTP_OK),
+  //   /* This creates a conflict, as we have the same coin public key 
(reuse!),
+  //      but different denomination public keys (which is not allowed).
+  //      However, note that this does NOT work with 'CS', as for a different
+  //      denomination we get different R0/R1 values from the exchange, and
+  //      thus will generate a different coin private key as R0/R1 are hashed
+  //      into the coin priv. So here, we fail to 'reuse' the key due to the
+  //      cryptographic construction! */
+  //   //TALER_TESTING_cmd_deposit ("deposit-reused-coin-key-failure",
+  //                              "withdraw-coin-1x",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:1",
+  //                              uses_cs
+  //                              ? MHD_HTTP_OK
+  //                              : MHD_HTTP_CONFLICT),
+  //   /**
+  //    * Try to double spend using different wire details.
+  //    */
+  //   //TALER_TESTING_cmd_deposit ("deposit-double-1",
+  //                              "withdraw-coin-1",
+  //                              0,
+  //                              cred.user43_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:5",
+  //                              MHD_HTTP_CONFLICT),
+  //   /* Try to double spend using a different transaction id.
+  //    * The test needs the contract terms to differ. This
+  //    * is currently the case because of the "timestamp" field,
+  //    * which is set automatically by #TALER_TESTING_cmd_deposit().
+  //    * This could theoretically fail if at some point a deposit
+  //    * command executes in less than 1 ms. *///
+  //   //TALER_TESTING_cmd_deposit ("deposit-double-1",
+  //                              "withdraw-coin-1",
+  //                              0,
+  //                              cred.user43_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:5",
+  //                              MHD_HTTP_CONFLICT),
+  //   /**
+  //    * Try to double spend with different proposal.
+  //    */
+  //   //TALER_TESTING_cmd_deposit ("deposit-double-2",
+  //                              "withdraw-coin-1",
+  //                              0,
+  //                              cred.user43_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":2}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:5",
+  //                              MHD_HTTP_CONFLICT),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // struct TALER_TESTING_Command refresh[] = {
+  //   /**
+  //    * Try to melt the coin that shared the private key with another
+  //    * coin (should fail). Note that in the CS-case, we fail also
+  //    * with MHD_HTTP_CONFLICT, but for a different reason: here it
+  //    * is not a denomination conflict, but a double-spending conflict.
+  //    */
+  //   //TALER_TESTING_cmd_melt ("refresh-melt-reused-coin-key-failure",
+  //                           "withdraw-coin-1x",
+  //                           MHD_HTTP_CONFLICT,
+  //                           NULL),
+
+  //   /* Fill reserve with EUR:5, 1ct is for fees. */
+  //   //CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-1",
+  //                             "EUR:5.01"),
+  //   //TALER_TESTING_cmd_check_bank_admin_transfer 
("ck-refresh-create-reserve-1",
+  //                                                "EUR:5.01",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                
"refresh-create-reserve-1"),
+  //   /**
+  //    * Make previous command effective.
+  //    */
+  //   //CMD_EXEC_WIREWATCH ("wirewatch-2"),
+  //   /**
+  //    * Withdraw EUR:5.
+  //    */
+  //   //TALER_TESTING_cmd_withdraw_amount ("refresh-withdraw-coin-1",
+  //                                      "refresh-create-reserve-1",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin
+  //    * (in full) (merchant would receive EUR:0.99 due to 1 ct
+  //    * deposit fee)
+  //    */
+  //   //TALER_TESTING_cmd_deposit ("refresh-deposit-partial",
+  //                              "refresh-withdraw-coin-1",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":\"EUR:1\"}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:1",
+  //                              MHD_HTTP_OK),
+  //   /**
+  //    * Melt the rest of the coin's value
+  //    * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
+  //   //TALER_TESTING_cmd_melt_double ("refresh-melt-1",
+  //                                  "refresh-withdraw-coin-1",
+  //                                  MHD_HTTP_OK,
+  //                                  NULL),
+  //   /**
+  //    * Complete (successful) melt operation, and
+  //    * withdraw the coins
+  //    */
+  //   //TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-1",
+  //                                     "refresh-melt-1",
+  //                                     MHD_HTTP_OK),
+  //   /**
+  //    * Do it again to check idempotency
+  //    */
+  //   //TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-1-idempotency",
+  //                                     "refresh-melt-1",
+  //                                     MHD_HTTP_OK),
+  //   /**
+  //    * Test that /refresh/link works
+  //    */
+  //   //TALER_TESTING_cmd_refresh_link ("refresh-link-1",
+  //                                   "refresh-reveal-1",
+  //                                   MHD_HTTP_OK),
+  //   /**
+  //    * Try to spend a refreshed EUR:1 coin
+  //    */
+  //   //TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1a",
+  //                              "refresh-reveal-1-idempotency",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":3}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:1",
+  //                              MHD_HTTP_OK),
+  //   /**
+  //    * Try to spend a refreshed EUR:0.1 coin
+  //    */
+  //   TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1b",
+  //                              "refresh-reveal-1",
+  //                              3,
+  //                              cred.user43_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":3}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:0.1",
+  //                              MHD_HTTP_OK),
+  //   /* Test running a failing melt operation (same operation
+  //    * again must fail) */
+  //   TALER_TESTING_cmd_melt ("refresh-melt-failing",
+  //                           "refresh-withdraw-coin-1",
+  //                           MHD_HTTP_CONFLICT,
+  //                           NULL),
+  //   /* Test running a failing melt operation (on a coin that
+  //      was itself revealed and subsequently deposited) */
+  //   TALER_TESTING_cmd_melt ("refresh-melt-failing-2",
+  //                           "refresh-reveal-1",
+  //                           MHD_HTTP_CONFLICT,
+  //                           NULL),
+
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // /**
+  //  * Test withdrawal with age restriction.  Success is expected, so it MUST 
be
+  //  * called _after_ TALER_TESTING_cmd_exec_offline_sign_extensions is 
called,
+  //  * i. e. age restriction is activated in the exchange!
+  //  *
+  //  * TODO: create a test that tries to withdraw coins with age restriction 
but
+  //  * (expectedly) fails because the exchange doesn't support age restriction
+  //  * yet.
+  //  */
+  // struct TALER_TESTING_Command withdraw_age[] = {
+  //   /**
+  //    * Move money to the exchange's bank account.
+  //    */
+  //   CMD_TRANSFER_TO_EXCHANGE ("create-reserve-age",
+  //                             "EUR:6.01"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-age",
+  //                                                "EUR:6.01",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                "create-reserve-age"),
+  //   /**
+  //    * Make a reserve exist, according to the previous
+  //    * transfer.
+  //    */
+  //   CMD_EXEC_WIREWATCH ("wirewatch-age"),
+  //   /**
+  //    * Withdraw EUR:5.
+  //    */
+  //   TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-age-1",
+  //                                      "create-reserve-age",
+  //                                      "EUR:5",
+  //                                      13,
+  //                                      MHD_HTTP_OK),
+
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // struct TALER_TESTING_Command spend_age[] = {
+  //   /**
+  //    * Spend the coin.
+  //    */
+  //   TALER_TESTING_cmd_deposit ("deposit-simple-age",
+  //                              "withdraw-coin-age-1",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:4.99",
+  //                              MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age",
+  //                                     "deposit-simple-age",
+  //                                     MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age-1",
+  //                                     "deposit-simple-age",
+  //                                     MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_sleep ("sleep-before-age-deposit-replay",
+  //                            1),
+  //   TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age-2",
+  //                                     "deposit-simple-age",
+  //                                     MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // struct TALER_TESTING_Command track[] = {
+  //   /* Try resolving a deposit's WTID, as we never triggered
+  //    * execution of transactions, the answer should be that
+  //    * the exchange knows about the deposit, but has no WTID yet.
+  //    */
+  //   TALER_TESTING_cmd_track_transaction ("deposit-wtid-found",
+  //                                        "deposit-simple",
+  //                                        0,
+  //                                        MHD_HTTP_ACCEPTED,
+  //                                        NULL),
+  //   /* Try resolving a deposit's WTID for a failed deposit.
+  //    * As the deposit failed, the answer should be that the
+  //    * exchange does NOT know about the deposit.
+  //    */
+  //   TALER_TESTING_cmd_track_transaction ("deposit-wtid-failing",
+  //                                        "deposit-double-2",
+  //                                        0,
+  //                                        MHD_HTTP_NOT_FOUND,
+  //                                        NULL),
+  //   /* Try resolving an undefined (all zeros) WTID; this
+  //    * should fail as obviously the exchange didn't use that
+  //    * WTID value for any transaction.
+  //    */
+  //   TALER_TESTING_cmd_track_transfer_empty ("wire-deposit-failing",
+  //                                           NULL,
+  //                                           MHD_HTTP_NOT_FOUND),
+  //   /* Run transfers. Note that _actual_ aggregation will NOT
+  //    * happen here, as each deposit operation is run with a
+  //    * fresh merchant public key, so the aggregator will treat
+  //    * them as "different" merchants and do the wire transfers
+  //    * individually. */
+  //   CMD_EXEC_AGGREGATOR ("run-aggregator"),
+  //   /**
+  //    * Check all the transfers took place.
+  //    */
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-499c",
+  //                                          cred.exchange_url,
+  //                                          "EUR:4.98",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-499c2",
+  //                                          cred.exchange_url,
+  //                                          "EUR:4.97",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c1",
+  //                                          cred.exchange_url,
+  //                                          "EUR:0.98",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c2",
+  //                                          cred.exchange_url,
+  //                                          "EUR:0.98",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c3",
+  //                                          cred.exchange_url,
+  //                                          "EUR:0.98",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c4",
+  //                                          cred.exchange_url,
+  //                                          "EUR:0.98",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-08c",
+  //                                          cred.exchange_url,
+  //                                          "EUR:0.08",
+  //                                          cred.exchange_payto,
+  //                                          cred.user43_payto),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-08c2",
+  //                                          cred.exchange_url,
+  //                                          "EUR:0.08",
+  //                                          cred.exchange_payto,
+  //                                          cred.user43_payto),
+  //   /* In case of CS, one transaction above succeeded that
+  //      failed for RSA, hence we need to check for an extra transfer here */
+  //   uses_cs
+  //   ? TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-98c",
+  //                                            cred.exchange_url,
+  //                                            "EUR:0.98",
+  //                                            cred.exchange_payto,
+  //                                            cred.user42_payto)
+  //   : TALER_TESTING_cmd_sleep ("dummy",
+  //                              0),
+  //   TALER_TESTING_cmd_check_bank_empty ("check_bank_empty"),
+  //   TALER_TESTING_cmd_track_transaction ("deposit-wtid-ok",
+  //                                        "deposit-simple",
+  //                                        0,
+  //                                        MHD_HTTP_OK,
+  //                                        "check_bank_transfer-499c"),
+  //   TALER_TESTING_cmd_track_transfer ("wire-deposit-success-bank",
+  //                                     "check_bank_transfer-99c1",
+  //                                     MHD_HTTP_OK,
+  //                                     "EUR:0.98",
+  //                                     "EUR:0.01"),
+  //   TALER_TESTING_cmd_track_transfer ("wire-deposits-success-wtid",
+  //                                     "deposit-wtid-ok",
+  //                                     MHD_HTTP_OK,
+  //                                     "EUR:4.98",
+  //                                     "EUR:0.01"),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // /**
+  //  * This block checks whether a wire deadline
+  //  * very far in the future does NOT get aggregated now.
+  //  */
+  // struct TALER_TESTING_Command unaggregation[] = {
+  //   TALER_TESTING_cmd_check_bank_empty ("far-future-aggregation-a"),
+  //   CMD_TRANSFER_TO_EXCHANGE ("create-reserve-unaggregated",
+  //                             "EUR:5.01"),
+  //   /* "consume" reserve creation transfer.  */
+  //   TALER_TESTING_cmd_check_bank_admin_transfer (
+  //     "check-create-reserve-unaggregated",
+  //     "EUR:5.01",
+  //     cred.user42_payto,
+  //     cred.exchange_payto,
+  //     "create-reserve-unaggregated"),
+  //   CMD_EXEC_WIREWATCH ("wirewatch-unaggregated"),
+  //   TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-unaggregated",
+  //                                      "create-reserve-unaggregated",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_deposit ("deposit-unaggregated",
+  //                              "withdraw-coin-unaggregated",
+  //                              0,
+  //                              cred.user43_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_relative_multiply (
+  //                                GNUNET_TIME_UNIT_YEARS,
+  //                                3000),
+  //                              "EUR:5",
+  //                              MHD_HTTP_OK),
+  //   CMD_EXEC_AGGREGATOR ("aggregation-attempt"),
+
+  //   TALER_TESTING_cmd_check_bank_empty (
+  //     "far-future-aggregation-b"),
+
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // struct TALER_TESTING_Command refresh_age[] = {
+  //   /* Fill reserve with EUR:5, 1ct is for fees. */
+  //   CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-age-1",
+  //                             "EUR:6.01"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer (
+  //     "ck-refresh-create-reserve-age-1",
+  //     "EUR:6.01",
+  //     cred.user42_payto,
+  //     cred.exchange_payto,
+  //     "refresh-create-reserve-age-1"),
+  //   /**
+  //    * Make previous command effective.
+  //    */
+  //   CMD_EXEC_WIREWATCH ("wirewatch-age-2"),
+  //   /**
+  //    * Withdraw EUR:7 with age restriction for age 13.
+  //    */
+  //   TALER_TESTING_cmd_withdraw_amount ("refresh-withdraw-coin-age-1",
+  //                                      "refresh-create-reserve-age-1",
+  //                                      "EUR:5",
+  //                                      13,
+  //                                      MHD_HTTP_OK),
+  //   /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin
+  //    * (in full) (merchant would receive EUR:0.99 due to 1 ct
+  //    * deposit fee)
+  //    */
+  //   TALER_TESTING_cmd_deposit ("refresh-deposit-partial-age",
+  //                              "refresh-withdraw-coin-age-1",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":\"EUR:1\"}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:1",
+  //                              MHD_HTTP_OK),
+  //   /**
+  //    * Melt the rest of the coin's value
+  //    * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
+  //   TALER_TESTING_cmd_melt_double ("refresh-melt-age-1",
+  //                                  "refresh-withdraw-coin-age-1",
+  //                                  MHD_HTTP_OK,
+  //                                  NULL),
+  //   /**
+  //    * Complete (successful) melt operation, and
+  //    * withdraw the coins
+  //    */
+  //   TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-age-1",
+  //                                     "refresh-melt-age-1",
+  //                                     MHD_HTTP_OK),
+  //   /**
+  //    * Do it again to check idempotency
+  //    */
+  //   TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-age-1-idempotency",
+  //                                     "refresh-melt-age-1",
+  //                                     MHD_HTTP_OK),
+  //   /**
+  //    * Test that /refresh/link works
+  //    */
+  //   TALER_TESTING_cmd_refresh_link ("refresh-link-age-1",
+  //                                   "refresh-reveal-age-1",
+  //                                   MHD_HTTP_OK),
+  //   /**
+  //    * Try to spend a refreshed EUR:1 coin
+  //    */
+  //   TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-age-1a",
+  //                              "refresh-reveal-age-1-idempotency",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":3}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:1",
+  //                              MHD_HTTP_OK),
+  //   /**
+  //    * Try to spend a refreshed EUR:0.1 coin
+  //    */
+  //   TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-age-1b",
+  //                              "refresh-reveal-age-1",
+  //                              3,
+  //                              cred.user43_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":3}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:0.1",
+  //                              MHD_HTTP_OK),
+  //   /* Test running a failing melt operation (same operation
+  //    * again must fail) */
+  //   TALER_TESTING_cmd_melt ("refresh-melt-failing-age",
+  //                           "refresh-withdraw-coin-age-1",
+  //                           MHD_HTTP_CONFLICT,
+  //                           NULL),
+  //   /* Test running a failing melt operation (on a coin that
+  //      was itself revealed and subsequently deposited) */
+  //   TALER_TESTING_cmd_melt ("refresh-melt-failing-age-2",
+  //                           "refresh-reveal-age-1",
+  //                           MHD_HTTP_CONFLICT,
+  //                           NULL),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  /**
+   * This block exercises the aggretation logic by making two payments
+   * to the same merchant.
+   */
+  // struct TALER_TESTING_Command aggregation[] = {
+  //   CMD_TRANSFER_TO_EXCHANGE ("create-reserve-aggtest",
+  //                             "EUR:5.01"),
+  //   /* "consume" reserve creation transfer.  */
+  //   TALER_TESTING_cmd_check_bank_admin_transfer (
+  //     "check-create-reserve-aggtest",
+  //     "EUR:5.01",
+  //     cred.user42_payto,
+  //     cred.exchange_payto,
+  //     "create-reserve-aggtest"),
+  //   CMD_EXEC_WIREWATCH ("wirewatch-aggtest"),
+  //   TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-aggtest",
+  //                                      "create-reserve-aggtest",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_deposit ("deposit-aggtest-1",
+  //                              "withdraw-coin-aggtest",
+  //                              0,
+  //                              cred.user43_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:2",
+  //                              MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_deposit_with_ref ("deposit-aggtest-2",
+  //                                       "withdraw-coin-aggtest",
+  //                                       0,
+  //                                       cred.user43_payto,
+  //                                       "{\"items\":[{\"name\":\"foo 
bar\",\"value\":1}]}",
+  //                                       GNUNET_TIME_UNIT_ZERO,
+  //                                       "EUR:2",
+  //                                       MHD_HTTP_OK,
+  //                                       "deposit-aggtest-1"),
+  //   CMD_EXEC_AGGREGATOR ("aggregation-aggtest"),
+  //   TALER_TESTING_cmd_check_bank_transfer ("check-bank-transfer-aggtest",
+  //                                          cred.exchange_url,
+  //                                          "EUR:3.97",
+  //                                          cred.exchange_payto,
+  //                                          cred.user43_payto),
+  //   TALER_TESTING_cmd_check_bank_empty ("check-bank-empty-aggtest"),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // struct TALER_TESTING_Command refund[] = {
+  //   /**
+  //    * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
+  //    * config.
+  //    */
+  //   CMD_TRANSFER_TO_EXCHANGE ("create-reserve-r1",
+  //                             "EUR:5.01"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-r1",
+  //                                                "EUR:5.01",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                "create-reserve-r1"),
+  //   /**
+  //    * Run wire-watch to trigger the reserve creation.
+  //    */
+  //   CMD_EXEC_WIREWATCH ("wirewatch-3"),
+  //   /* Withdraw a 5 EUR coin, at fee of 1 ct */
+  //   TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-r1",
+  //                                      "create-reserve-r1",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   /**
+  //    * Spend 5 EUR of the 5 EUR coin (in full) (merchant would
+  //    * receive EUR:4.99 due to 1 ct deposit fee)
+  //    */
+  //   TALER_TESTING_cmd_deposit ("deposit-refund-1",
+  //                              "withdraw-coin-r1",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":\"EUR:5\"}]}",
+  //                              GNUNET_TIME_UNIT_MINUTES,
+  //                              "EUR:5",
+  //                              MHD_HTTP_OK),
+  //   /**
+  //    * Run transfers. Should do nothing as refund deadline blocks it
+  //    */
+  //   CMD_EXEC_AGGREGATOR ("run-aggregator-refund"),
+  //   /* Check that aggregator didn't do anything, as expected.
+  //    * Note, this operation takes two commands: one to "flush"
+  //    * the preliminary transfer (used to withdraw) from the
+  //    * fakebank and the second to actually check there are not
+  //    * other transfers around. */
+  //   TALER_TESTING_cmd_check_bank_empty ("check_bank_transfer-pre-refund"),
+  //   TALER_TESTING_cmd_refund_with_id ("refund-ok",
+  //                                     MHD_HTTP_OK,
+  //                                     "EUR:3",
+  //                                     "deposit-refund-1",
+  //                                     3),
+  //   TALER_TESTING_cmd_refund_with_id ("refund-ok-double",
+  //                                     MHD_HTTP_OK,
+  //                                     "EUR:3",
+  //                                     "deposit-refund-1",
+  //                                     3),
+  //   /* Previous /refund(s) had id == 0.  */
+  //   TALER_TESTING_cmd_refund_with_id ("refund-conflicting",
+  //                                     MHD_HTTP_CONFLICT,
+  //                                     "EUR:5",
+  //                                     "deposit-refund-1",
+  //                                     1),
+  //   TALER_TESTING_cmd_deposit ("deposit-refund-insufficient-refund",
+  //                              "withdraw-coin-r1",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":\"EUR:4\"}]}",
+  //                              GNUNET_TIME_UNIT_MINUTES,
+  //                              "EUR:4",
+  //                              MHD_HTTP_CONFLICT),
+  //   TALER_TESTING_cmd_refund_with_id ("refund-ok-increase",
+  //                                     MHD_HTTP_OK,
+  //                                     "EUR:2",
+  //                                     "deposit-refund-1",
+  //                                     2),
+  //   /**
+  //    * Spend 4.99 EUR of the refunded 4.99 EUR coin (1ct gone
+  //    * due to refund) (merchant would receive EUR:4.98 due to
+  //    * 1 ct deposit fee) */
+  //   TALER_TESTING_cmd_deposit ("deposit-refund-2",
+  //                              "withdraw-coin-r1",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"more ice 
cream\",\"value\":\"EUR:5\"}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:4.99",
+  //                              MHD_HTTP_OK),
+  //   /**
+  //    * Run transfers. This will do the transfer as refund deadline
+  //    * was 0
+  //    */
+  //   CMD_EXEC_AGGREGATOR ("run-aggregator-3"),
+  //   /**
+  //    * Check that deposit did run.
+  //    */
+  //   TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-pre-refund",
+  //                                          cred.exchange_url,
+  //                                          "EUR:4.97",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   /**
+  //    * Run failing refund, as past deadline & aggregation.
+  //    */
+  //   TALER_TESTING_cmd_refund ("refund-fail",
+  //                             MHD_HTTP_GONE,
+  //                             "EUR:4.99",
+  //                             "deposit-refund-2"),
+  //   TALER_TESTING_cmd_check_bank_empty ("check-empty-after-refund"),
+  //   /**
+  //    * Test refunded coins are never executed, even past
+  //    * refund deadline
+  //    */
+  //   CMD_TRANSFER_TO_EXCHANGE ("create-reserve-rb",
+  //                             "EUR:5.01"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-rb",
+  //                                                "EUR:5.01",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                "create-reserve-rb"),
+  //   CMD_EXEC_WIREWATCH ("wirewatch-rb"),
+  //   TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-rb",
+  //                                      "create-reserve-rb",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_deposit ("deposit-refund-1b",
+  //                              "withdraw-coin-rb",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"ice 
cream\",\"value\":\"EUR:5\"}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:5",
+  //                              MHD_HTTP_OK),
+  //   /**
+  //    * Trigger refund (before aggregator had a chance to execute
+  //    * deposit, even though refund deadline was zero).
+  //    */
+  //   TALER_TESTING_cmd_refund ("refund-ok-fast",
+  //                             MHD_HTTP_OK,
+  //                             "EUR:5",
+  //                             "deposit-refund-1b"),
+  //   /**
+  //    * Run transfers. This will do the transfer as refund deadline
+  //    * was 0, except of course because the refund succeeded, the
+  //    * transfer should no longer be done.
+  //    */
+  //   CMD_EXEC_AGGREGATOR ("run-aggregator-3b"),
+  //   /* check that aggregator didn't do anything, as expected */
+  //   TALER_TESTING_cmd_check_bank_empty ("check-refund-fast-not-run"),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  // struct TALER_TESTING_Command recoup[] = {
+  //   /**
+  //    * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
+  //    * config.
+  //    */
+  //   CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-1",
+  //                             "EUR:15.02"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer (
+  //     "recoup-create-reserve-1-check",
+  //     "EUR:15.02",
+  //     cred.user42_payto,
+  //     cred.exchange_payto,
+  //     "recoup-create-reserve-1"),
+  //   /**
+  //    * Run wire-watch to trigger the reserve creation.
+  //    */
+  //   CMD_EXEC_WIREWATCH ("wirewatch-4"),
+  //   /* Withdraw a 5 EUR coin, at fee of 1 ct */
+  //   TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-1",
+  //                                      "recoup-create-reserve-1",
+  //                                      "EUR:5",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   /* Withdraw a 10 EUR coin, at fee of 1 ct */
+  //   TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-1b",
+  //                                      "recoup-create-reserve-1",
+  //                                      "EUR:10",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   /* melt 10 EUR coin to get 5 EUR refreshed coin */
+  //   TALER_TESTING_cmd_melt ("recoup-melt-coin-1b",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:5",
+  //                           NULL),
+  //   TALER_TESTING_cmd_refresh_reveal ("recoup-reveal-coin-1b",
+  //                                     "recoup-melt-coin-1b",
+  //                                     MHD_HTTP_OK),
+  //   /* Revoke both 5 EUR coins */
+  //   TALER_TESTING_cmd_revoke ("revoke-0-EUR:5",
+  //                             MHD_HTTP_OK,
+  //                             "recoup-withdraw-coin-1",
+  //                             config_file),
+  //   /* Recoup coin to reserve */
+  //   TALER_TESTING_cmd_recoup ("recoup-1",
+  //                             MHD_HTTP_OK,
+  //                             "recoup-withdraw-coin-1",
+  //                             "EUR:5"),
+  //   /* Check the money is back with the reserve */
+  //   TALER_TESTING_cmd_status ("recoup-reserve-status-1",
+  //                             "recoup-create-reserve-1",
+  //                             "EUR:5.0",
+  //                             MHD_HTTP_OK),
+  //   /* Recoup-refresh coin to 10 EUR coin */
+  //   TALER_TESTING_cmd_recoup_refresh ("recoup-1b",
+  //                                     MHD_HTTP_OK,
+  //                                     "recoup-reveal-coin-1b",
+  //                                     "recoup-melt-coin-1b",
+  //                                     "EUR:5"),
+  //   /* melt 10 EUR coin *again* to get 1 EUR refreshed coin */
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1a",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_refresh_reveal ("recoup-reveal-coin-1a",
+  //                                     "recoup-remelt-coin-1a",
+  //                                     MHD_HTTP_OK),
+  //   /* Try melting for more than the residual value to provoke an error */
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1b",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1c",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1d",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1e",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1f",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1g",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1h",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1i",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_OK,
+  //                           "EUR:1",
+  //                           NULL),
+  //   TALER_TESTING_cmd_melt ("recoup-remelt-coin-1b-failing",
+  //                           "recoup-withdraw-coin-1b",
+  //                           MHD_HTTP_CONFLICT,
+  //                           "EUR:1",
+  //                           NULL),
+  //   /* Re-withdraw from this reserve */
+  //   TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2",
+  //                                      "recoup-create-reserve-1",
+  //                                      "EUR:1",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   /**
+  //    * This withdrawal will test the logic to create a "recoup"
+  //    * element to insert into the reserve's history.
+  //    */
+  //   TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2-over",
+  //                                      "recoup-create-reserve-1",
+  //                                      "EUR:10",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_CONFLICT),
+  //   TALER_TESTING_cmd_status ("recoup-reserve-status-2",
+  //                             "recoup-create-reserve-1",
+  //                             "EUR:3.99",
+  //                             MHD_HTTP_OK),
+  //   /* These commands should close the reserve because
+  //    * the aggregator is given a config file that overrides
+  //    * the reserve expiration time (making it now-ish) */
+  //   CMD_TRANSFER_TO_EXCHANGE ("short-lived-reserve",
+  //                             "EUR:5.01"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer 
("check-short-lived-reserve",
+  //                                                "EUR:5.01",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                "short-lived-reserve"),
+  //   TALER_TESTING_cmd_exec_wirewatch2 ("short-lived-aggregation",
+  //                                      config_file_expire_reserve_now,
+  //                                      "exchange-account-2"),
+  //   TALER_TESTING_cmd_exec_closer ("close-reserves",
+  //                                  config_file_expire_reserve_now,
+  //                                  "EUR:5",
+  //                                  "EUR:0.01",
+  //                                  "short-lived-reserve"),
+  //   TALER_TESTING_cmd_exec_transfer ("close-reserves-transfer",
+  //                                    config_file_expire_reserve_now),
+
+  //   TALER_TESTING_cmd_status ("short-lived-status",
+  //                             "short-lived-reserve",
+  //                             "EUR:0",
+  //                             MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_withdraw_amount ("expired-withdraw",
+  //                                      "short-lived-reserve",
+  //                                      "EUR:1",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_CONFLICT),
+  //   TALER_TESTING_cmd_check_bank_transfer 
("check_bank_short-lived_reimburse",
+  //                                          cred.exchange_url,
+  //                                          "EUR:5",
+  //                                          cred.exchange_payto,
+  //                                          cred.user42_payto),
+  //   /* Fill reserve with EUR:2.02, as withdraw fee is 1 ct per
+  //    * config, then withdraw two coin, partially spend one, and
+  //    * then have the rest paid back.  Check deposit of other coin
+  //    * fails.  Do not use EUR:5 here as the EUR:5 coin was
+  //    * revoked and we did not bother to create a new one... */
+  //   CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-2",
+  //                             "EUR:2.02"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer 
("ck-recoup-create-reserve-2",
+  //                                                "EUR:2.02",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                "recoup-create-reserve-2"),
+  //   /* Make previous command effective. */
+  //   CMD_EXEC_WIREWATCH ("wirewatch-5"),
+  //   /* Withdraw a 1 EUR coin, at fee of 1 ct */
+  //   TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2a",
+  //                                      "recoup-create-reserve-2",
+  //                                      "EUR:1",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   /* Withdraw a 1 EUR coin, at fee of 1 ct */
+  //   TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2b",
+  //                                      "recoup-create-reserve-2",
+  //                                      "EUR:1",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_deposit ("recoup-deposit-partial",
+  //                              "recoup-withdraw-coin-2a",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"more ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:0.5",
+  //                              MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_revoke ("revoke-1-EUR:1",
+  //                             MHD_HTTP_OK,
+  //                             "recoup-withdraw-coin-2a",
+  //                             config_file),
+  //   /* Check recoup is failing for the coin with the reused coin key
+  //      (fails either because of denomination conflict (RSA) or
+  //      double-spending (CS))*/
+  //   TALER_TESTING_cmd_recoup ("recoup-2x",
+  //                             MHD_HTTP_CONFLICT,
+  //                             "withdraw-coin-1x",
+  //                             "EUR:1"),
+  //   TALER_TESTING_cmd_recoup ("recoup-2",
+  //                             MHD_HTTP_OK,
+  //                             "recoup-withdraw-coin-2a",
+  //                             "EUR:0.5"),
+  //   /* Idempotency of recoup (withdrawal variant) */
+  //   TALER_TESTING_cmd_recoup ("recoup-2b",
+  //                             MHD_HTTP_OK,
+  //                             "recoup-withdraw-coin-2a",
+  //                             "EUR:0.5"),
+  //   TALER_TESTING_cmd_deposit ("recoup-deposit-revoked",
+  //                              "recoup-withdraw-coin-2b",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"more ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:1",
+  //                              MHD_HTTP_GONE),
+  //   /* Test deposit fails after recoup, with proof in recoup */
+
+  //   /* Note that, the exchange will never return the coin's transaction
+  //    * history with recoup data, as we get a 410 on the DK! */
+  //   TALER_TESTING_cmd_deposit ("recoup-deposit-partial-after-recoup",
+  //                              "recoup-withdraw-coin-2a",
+  //                              0,
+  //                              cred.user42_payto,
+  //                              "{\"items\":[{\"name\":\"extra ice 
cream\",\"value\":1}]}",
+  //                              GNUNET_TIME_UNIT_ZERO,
+  //                              "EUR:0.5",
+  //                              MHD_HTTP_GONE),
+  //   /* Test that revoked coins cannot be withdrawn */
+  //   CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-3",
+  //                             "EUR:1.01"),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer (
+  //     "check-recoup-create-reserve-3",
+  //     "EUR:1.01",
+  //     cred.user42_payto,
+  //     cred.exchange_payto,
+  //     "recoup-create-reserve-3"),
+  //   CMD_EXEC_WIREWATCH ("wirewatch-6"),
+  //   TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-3-revoked",
+  //                                      "recoup-create-reserve-3",
+  //                                      "EUR:1",
+  //                                      0, /* age restriction off */
+  //                                      MHD_HTTP_GONE),
+  //   /* check that we are empty before the rejection test */
+  //   TALER_TESTING_cmd_check_bank_empty ("check-empty-again"),
+
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+  /**
+   * Test batch withdrawal plus spending.
+   */
+  // struct TALER_TESTING_Command batch_withdraw[] = {
+  //   /**
+  //    * Move money to the exchange's bank account.
+  //    */
+  //   CMD_TRANSFER_TO_EXCHANGE ("create-batch-reserve-1",
+  //                             "EUR:6.03"),
+  //   TALER_TESTING_cmd_reserve_poll ("poll-batch-reserve-1",
+  //                                   "create-batch-reserve-1",
+  //                                   "EUR:6.03",
+  //                                   GNUNET_TIME_UNIT_MINUTES,
+  //                                   MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_check_bank_admin_transfer 
("check-create-batch-reserve-1",
+  //                                                "EUR:6.03",
+  //                                                cred.user42_payto,
+  //                                                cred.exchange_payto,
+  //                                                "create-batch-reserve-1"),
+  //   /*
+  //    * Make a reserve exist, according to the previous
+  //    * transfer.
+  //    */
+  //   CMD_EXEC_WIREWATCH ("wirewatch-batch-1"),
+  //   TALER_TESTING_cmd_reserve_poll_finish ("finish-poll-batch-reserve-1",
+  //                                          GNUNET_TIME_UNIT_SECONDS,
+  //                                          "poll-batch-reserve-1"),
+  //   /**
+  //    * Withdraw EUR:5 AND EUR:1.
+  //    */
+  //   TALER_TESTING_cmd_batch_withdraw ("batch-withdraw-coin-1",
+  //                                     "create-batch-reserve-1",
+  //                                     0,  /* age restriction off */
+  //                                     MHD_HTTP_OK,
+  //                                     "EUR:5",
+  //                                     "EUR:1",
+  //                                     NULL),
+  //   /**
+  //    * Check the reserve is (almost) depleted.
+  //    */
+  //   TALER_TESTING_cmd_status ("status-batch-1",
+  //                             "create-batch-reserve-1",
+  //                             "EUR:0.01",
+  //                             MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_reserve_history ("history-batch-1",
+  //                                      "create-batch-reserve-1",
+  //                                      "EUR:0.01",
+  //                                      MHD_HTTP_OK),
+  //   /**
+  //    * Spend the coins.
+  //    */
+  //   TALER_TESTING_cmd_batch_deposit ("batch-deposit-1",
+  //                                    cred.user42_payto,
+  //                                    "{\"items\":[{\"name\":\"ice 
cream\",\"value\":5}]}",
+  //                                    GNUNET_TIME_UNIT_ZERO,
+  //                                    MHD_HTTP_OK,
+  //                                    "batch-withdraw-coin-1#0",
+  //                                    "EUR:5",
+  //                                    "batch-withdraw-coin-1#1",
+  //                                    "EUR:1",
+  //                                    NULL),
+  //   TALER_TESTING_cmd_coin_history ("coin-history-batch-1",
+  //                                   "batch-withdraw-coin-1#0",
+  //                                   "EUR:0.0",
+  //                                   MHD_HTTP_OK),
+  //   TALER_TESTING_cmd_end ()
+  // };
+
+
+#define RESERVE_OPEN_CLOSE_CHUNK 4
+#define RESERVE_OPEN_CLOSE_ITERATIONS 3
+
+  struct TALER_TESTING_Command 
reserve_open_close[(RESERVE_OPEN_CLOSE_ITERATIONS
+                                                   * RESERVE_OPEN_CLOSE_CHUNK)
+                                                  + 1];
+
+  (void) cls;
+  for (unsigned int i = 0;
+       i < RESERVE_OPEN_CLOSE_ITERATIONS;
+       i++)
+  {
+    reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 0]
+      = CMD_TRANSFER_TO_EXCHANGE ("reserve-open-close-key",
+                                  "EUR:20");
+    reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 1]
+      = TALER_TESTING_cmd_exec_wirewatch2 ("reserve-open-close-wirewatch",
+                                           config_file_expire_reserve_now,
+                                           "exchange-account-2");
+    reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 2]
+      = TALER_TESTING_cmd_exec_closer ("reserve-open-close-aggregation",
+                                       config_file_expire_reserve_now,
+                                       "EUR:19.99",
+                                       "EUR:0.01",
+                                       "reserve-open-close-key");
+    reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 3]
+      = TALER_TESTING_cmd_status ("reserve-open-close-status",
+                                  "reserve-open-close-key",
+                                  "EUR:0",
+                                  MHD_HTTP_OK);
+  }
+  reserve_open_close[RESERVE_OPEN_CLOSE_ITERATIONS * RESERVE_OPEN_CLOSE_CHUNK]
+    = TALER_TESTING_cmd_end ();
+
+  {
+    struct TALER_TESTING_Command commands[] = {
+      TALER_TESTING_cmd_system_start ("start-taler",
+                                      config_file,
+                                      "-D",
+                                      NULL),
+      TALER_TESTING_cmd_get_donau ("get-donau",
+                                      cred.cfg,
+                                      NULL,
+                                      true,
+                                      true),
+      /* End the suite. */
+      TALER_TESTING_cmd_end ()
+    };
+
+    TALER_TESTING_run (is,
+                       commands);
+  }
 }
 
 
@@ -84,12 +1260,15 @@ main (int argc,
     GNUNET_asprintf (&config_file,
                      "test_donau_api-%s.conf",
                      cipher);
+    //GNUNET_asprintf (&config_file_expireDreserve_now,
+      //               "test_donau_api_expire_reserve_now-%s.conf",
+        //             cipher);
     GNUNET_free (cipher);
   }
-  return DONAU_TESTING_main (argv,
+  return TALER_TESTING_main (argv,
                              "INFO",
                              config_file,
-                             "donau-account-2",
+                             "exchange-account-2",
                              TALER_TESTING_BS_FAKEBANK,
                              &cred,
                              &run,
@@ -97,4 +1276,4 @@ main (int argc,
 }
 
 
-/* end of test_donau_api.c */
+/* end of test_exchange_api.c */

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