gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated: -more merchant clean up


From: gnunet
Subject: [taler-merchant] branch master updated: -more merchant clean up
Date: Wed, 05 Jul 2023 13:16:55 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new c4b27ca9 -more merchant clean up
c4b27ca9 is described below

commit c4b27ca9b9a5ef4291257e4a8b8f4bac56720b89
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Jul 5 13:16:48 2023 +0200

    -more merchant clean up
---
 src/backend/taler-merchant-httpd.c                 |   40 +
 src/backend/taler-merchant-httpd.h                 |    2 +-
 src/backend/taler-merchant-httpd_exchanges.c       | 1025 ++++++++++----------
 src/backend/taler-merchant-httpd_exchanges.h       |   91 +-
 src/backend/taler-merchant-httpd_helper.c          |  206 ++--
 .../taler-merchant-httpd_post-orders-ID-abort.c    |    4 +-
 .../taler-merchant-httpd_post-orders-ID-pay.c      |  127 +--
 .../taler-merchant-httpd_post-orders-ID-refund.c   |    4 +-
 .../taler-merchant-httpd_post-tips-ID-pickup.c     |    6 +-
 ...r-merchant-httpd_private-get-instances-ID-kyc.c |    4 +-
 .../taler-merchant-httpd_private-get-orders-ID.c   |    4 +-
 .../taler-merchant-httpd_private-get-reserves-ID.c |   25 +-
 .../taler-merchant-httpd_private-post-reserves.c   |    4 +-
 src/backend/taler-merchant-httpd_reserves.c        |    2 +-
 14 files changed, 777 insertions(+), 767 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 00e4689c..1c8b80d0 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -145,6 +145,17 @@ static uint16_t port;
  * Should a "Connection: close" header be added to each HTTP response?
  */
 static int merchant_connection_close;
+/**
+ * Context for all exchange operations (useful to the event loop).
+ * FIXME: rename, move to taler-merchant-httpd.c
+ */
+struct GNUNET_CURL_Context *TMH_curl_ctx;
+
+/**
+ * Context for integrating #TMH_curl_ctx with the
+ * GNUnet event loop.
+ */
+static struct GNUNET_CURL_RescheduleContext *merchant_curl_rc;
 
 /**
  * Global return code
@@ -329,6 +340,16 @@ do_shutdown (void *cls)
     TMH_by_id_map = NULL;
   }
   TALER_TEMPLATING_done ();
+  if (NULL != TMH_curl_ctx)
+  {
+    GNUNET_CURL_fini (TMH_curl_ctx);
+    TMH_curl_ctx = NULL;
+  }
+  if (NULL != merchant_curl_rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (merchant_curl_rc);
+    merchant_curl_rc = NULL;
+  }
 }
 
 
@@ -1915,6 +1936,25 @@ run (void *cls,
   result = GNUNET_SYSERR;
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                  NULL);
+
+  TMH_curl_ctx
+    = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                        &merchant_curl_rc);
+  if (NULL == TMH_curl_ctx)
+  {
+    GNUNET_break (0);
+    result = GNUNET_SYSERR;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  merchant_curl_rc = GNUNET_CURL_gnunet_rc_create (TMH_curl_ctx);
+  /* Disable 100 continue processing */
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_CURL_append_header (TMH_curl_ctx,
+                                           MHD_HTTP_HEADER_EXPECT ":"));
+  GNUNET_CURL_enable_async_scope_header (TMH_curl_ctx,
+                                         "Taler-Correlation-Id");
+
   if (GNUNET_OK !=
       TALER_config_get_currency (cfg,
                                  &TMH_currency))
diff --git a/src/backend/taler-merchant-httpd.h 
b/src/backend/taler-merchant-httpd.h
index 732c1bf3..e262b314 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -639,7 +639,7 @@ extern int TMH_force_audit;
 /**
  * Context for all CURL operations (useful to the event loop)
  */
-extern struct GNUNET_CURL_Context *merchant_curl_ctx;
+extern struct GNUNET_CURL_Context *TMH_curl_ctx;
 
 /**
  * Handle to the database backend.
diff --git a/src/backend/taler-merchant-httpd_exchanges.c 
b/src/backend/taler-merchant-httpd_exchanges.c
index 665607c1..ff4360b0 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -66,18 +66,18 @@
 /**
  * Information we keep for a pending #MMH_EXCHANGES_keys4exchange() operation.
  */
-struct TMH_EXCHANGES_Find2Operation
+struct TMH_EXCHANGES_KeysOperation
 {
 
   /**
    * Kept in a DLL.
    */
-  struct TMH_EXCHANGES_Find2Operation *next;
+  struct TMH_EXCHANGES_KeysOperation *next;
 
   /**
    * Kept in a DLL.
    */
-  struct TMH_EXCHANGES_Find2Operation *prev;
+  struct TMH_EXCHANGES_KeysOperation *prev;
 
   /**
    * Function to call with the result.
@@ -254,7 +254,7 @@ struct ExchangeAccount
 
 
 /**
- * Exchange
+ * Internal representation for an exchange
  */
 struct TMH_Exchange
 {
@@ -272,12 +272,12 @@ struct TMH_Exchange
   /**
    * Head of FOs pending for this exchange.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo2_head;
+  struct TMH_EXCHANGES_KeysOperation *keys_head;
 
   /**
    * Tail of FOs pending for this exchange.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo2_tail;
+  struct TMH_EXCHANGES_KeysOperation *keys_tail;
 
   /**
    * Head of /wire pending for this exchange.
@@ -289,6 +289,11 @@ struct TMH_Exchange
    */
   struct TMH_EXCHANGES_WireOperation *w_tail;
 
+  /**
+   * Request to /keys needed for our /wire operation.
+   */
+  struct TMH_EXCHANGES_KeysOperation *ko;
+
   /**
    * Head of accounts of this exchange.
    */
@@ -335,8 +340,7 @@ struct TMH_Exchange
   struct FeesByWireMethod *wire_fees_tail;
 
   /**
-   * Master public key, guaranteed to be set ONLY for
-   * trusted exchanges.
+   * Master public key of the exchange.
    */
   struct TALER_MasterPublicKeyP master_pub;
 
@@ -377,16 +381,17 @@ struct TMH_Exchange
 
 
 /**
- * Context for all exchange operations (useful to the event loop).
- * FIXME: rename, move to taler-merchant-httpd.c
+ * Opaque wire details abstraction returned to a client after successfully
+ * obtaining /wire.
  */
-struct GNUNET_CURL_Context *merchant_curl_ctx;
+struct TMH_ExchangeWireDetails
+{
+  /**
+   * Internal representation of the exchange
+   */
+  struct TMH_Exchange *exchange;
+};
 
-/**
- * Context for integrating #merchant_curl_ctx with the
- * GNUnet event loop.
- */
-static struct GNUNET_CURL_RescheduleContext *merchant_curl_rc;
 
 /**
  * Head of exchanges we know about.
@@ -405,19 +410,6 @@ static struct TMH_Exchange *exchange_tail;
  */
 static int trusted_exchange_count;
 
-/**
- * Function called with information about who is auditing
- * a particular exchange and what key the exchange is using.
- *
- * @param cls closure, will be `struct TMH_Exchange`
- * @param kr response details
- * @param[in] keys keys object returned
- */
-static void
-keys_mgmt_cb (void *cls,
-              const struct TALER_EXCHANGE_KeysResponse *kr,
-              struct TALER_EXCHANGE_Keys *keys);
-
 
 /**
  * Free data structures within @a ea, but not @a ea
@@ -474,6 +466,36 @@ purge_exchange_accounts (struct TMH_Exchange *exchange)
 }
 
 
+/**
+ * Lookup exchange by @a exchange_url. Create one
+ * if it does not exist.
+ *
+ * @param exchange_url base URL to match against
+ * @return fresh entry if exchange was not yet known
+ */
+static struct TMH_Exchange *
+lookup_exchange (const char *exchange_url)
+{
+  struct TMH_Exchange *exchange;
+
+  for (exchange = exchange_head;
+       NULL != exchange;
+       exchange = exchange->next)
+    if (0 == strcmp (exchange->url,
+                     exchange_url))
+      return exchange;
+  exchange = GNUNET_new (struct TMH_Exchange);
+  exchange->url = GNUNET_strdup (exchange_url);
+  GNUNET_CONTAINER_DLL_insert (exchange_head,
+                               exchange_tail,
+                               exchange);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "The exchange `%s' is new\n",
+              exchange_url);
+  return exchange;
+}
+
+
 /**
  * Set the list of accounts of @a exchange.
  *
@@ -536,10 +558,24 @@ set_exchange_accounts (
 
 
 /**
- * Retry getting information from the given exchange in
- * the closure.
+ * Function called with information about who is auditing
+ * a particular exchange and what key the exchange is using.
+ *
+ * @param cls closure, will be `struct TMH_Exchange`
+ * @param kr response details
+ * @param[in] keys keys object returned
+ */
+static void
+keys_mgmt_cb (
+  void *cls,
+  const struct TALER_EXCHANGE_KeysResponse *kr,
+  struct TALER_EXCHANGE_Keys *keys);
+
+
+/**
+ * Retry getting keys from the given exchange in the closure.
  *
- * @param cls the exchange
+ * @param cls the `struct TMH_Exchange *`
  */
 static void
 retry_exchange (void *cls)
@@ -549,18 +585,31 @@ retry_exchange (void *cls)
   /* might be a scheduled reload and not our first attempt */
   exchange->retry_task = NULL;
   if (NULL != exchange->conn)
-    return;
+    return; /* already trying */
+  if ( (NULL != exchange->keys) &&
+       (GNUNET_TIME_absolute_is_future (
+          exchange->keys->key_data_expiration.abs_time)) )
+    return; /* still have a valid reply */
+  /* increment exponential-backoff */
+  exchange->retry_delay
+    = RETRY_BACKOFF (exchange->retry_delay);
+  /* No download until both backoff and #FORCED_RELOAD_DELAY
+     are satisfied again */
+  exchange->first_retry
+    = GNUNET_TIME_relative_to_absolute (
+        GNUNET_TIME_relative_max (
+          exchange->retry_delay,
+          FORCED_RELOAD_DELAY));
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting to exchange %s in retry_exchange()\n",
+              "Fetching /keys from exchange %s in retry_exchange()\n",
               exchange->url);
-  if ( (NULL == exchange->keys) ||
-       (GNUNET_TIME_absolute_is_past (
-          exchange->keys->key_data_expiration.abs_time)) )
-    exchange->conn = TALER_EXCHANGE_get_keys (merchant_curl_ctx,
-                                              exchange->url,
-                                              exchange->keys,
-                                              &keys_mgmt_cb,
-                                              exchange);
+  exchange->conn
+    = TALER_EXCHANGE_get_keys (
+        TMH_curl_ctx,
+        exchange->url,
+        exchange->keys,
+        &keys_mgmt_cb,
+        exchange);
   /* Note: while the API spec says 'returns NULL on error', the implementation
      actually never returns NULL. */
   GNUNET_break (NULL != exchange->conn);
@@ -568,9 +617,200 @@ retry_exchange (void *cls)
 
 
 /**
- * Function called with information about the wire fees
- * for each wire method.  Stores the wire fees with the
- * exchange for later use.
+ * Check if we have any remaining pending requests for the
+ * given @a exchange, and if we have the required data, call
+ * the callback.
+ *
+ * @param exchange the exchange to check for pending find operations
+ * @return true if we need /wire data from @a exchange
+ */
+static bool
+process_find_operations (struct TMH_Exchange *exchange)
+{
+  struct TMH_EXCHANGES_KeysOperation *fn2;
+  struct TMH_EXCHANGES_WireOperation *wn;
+  struct GNUNET_TIME_Timestamp now;
+
+  fn2 = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Processing find operations for `%s'\n",
+              exchange->url);
+  for (struct TMH_EXCHANGES_KeysOperation *fo = exchange->keys_head;
+       NULL != fo;
+       fo = fn2)
+  {
+    fn2 = fo->next;
+    fo->fc (fo->fc_cls,
+            exchange->keys);
+    TMH_EXCHANGES_keys4exchange_cancel (fo);
+  }
+  if (! exchange->have_wire)
+    return true;
+  now = GNUNET_TIME_timestamp_get ();
+  for (struct FeesByWireMethod *fbw = exchange->wire_fees_head;
+       NULL != fbw;
+       fbw = fbw->next)
+  {
+    bool removed = false;
+
+    while ( (NULL != fbw->af) &&
+            (GNUNET_TIME_timestamp_cmp (fbw->af->end_date,
+                                        <,
+                                        now)) )
+    {
+      struct TALER_EXCHANGE_WireAggregateFees *af = fbw->af;
+
+      fbw->af = af->next;
+      GNUNET_free (af);
+      removed = true;
+    }
+    if (NULL == fbw->af)
+    {
+      /* Disagreement on the current time */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Exchange has no wire fees configured for `%s' wire 
method\n",
+                  fbw->wire_method);
+      if (removed)
+      {
+        exchange->have_wire = false;
+        return true; /* We just removed previous fees, try fetching update */
+      }
+    }
+    if (GNUNET_TIME_timestamp_cmp (fbw->af->start_date,
+                                   >,
+                                   now))
+    {
+      /* Disagreement on the current time */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Exchange's earliest fee is %s ahead of our time. Clock skew 
issue?\n",
+                  GNUNET_TIME_relative2s (
+                    GNUNET_TIME_absolute_get_remaining (
+                      fbw->af->start_date.abs_time),
+                    true));
+    }
+  }
+
+  if (! exchange->have_wire)
+    return true; /* need /wire response to continue */
+  {
+    struct TMH_ExchangeWireDetails wd = {
+      .exchange = exchange
+    };
+
+    wn = NULL;
+    for (struct TMH_EXCHANGES_WireOperation *w = exchange->w_head;
+         NULL != w;
+         w = wn)
+    {
+      wn = w->next;
+      w->fc (w->fc_cls,
+             &wd);
+      TMH_EXCHANGES_wire4exchange_cancel (w);
+    }
+  }
+  return false;
+}
+
+
+/**
+ * Task to asynchronously return keys operation result to caller.
+ *
+ * @param cls a `struct TMH_EXCHANGES_KeysOperation`
+ */
+static void
+return_keys (void *cls)
+{
+  struct TMH_EXCHANGES_KeysOperation *fo = cls;
+  struct TMH_Exchange *exchange = fo->my_exchange;
+
+  fo->at = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Returning key data for %s instantly\n",
+              exchange->url);
+  process_find_operations (exchange);
+}
+
+
+struct TMH_EXCHANGES_KeysOperation *
+TMH_EXCHANGES_keys4exchange (
+  const char *chosen_exchange,
+  TMH_EXCHANGES_Find2Continuation fc,
+  void *fc_cls)
+{
+  struct TMH_Exchange *exchange;
+  struct TMH_EXCHANGES_KeysOperation *fo;
+
+  if (NULL == TMH_curl_ctx)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Trying to find chosen exchange `%s'\n",
+              chosen_exchange);
+  exchange = lookup_exchange (chosen_exchange);
+  fo = GNUNET_new (struct TMH_EXCHANGES_KeysOperation);
+  fo->fc = fc;
+  fo->fc_cls = fc_cls;
+  fo->my_exchange = exchange;
+  GNUNET_CONTAINER_DLL_insert (exchange->keys_head,
+                               exchange->keys_tail,
+                               fo);
+  if ( (NULL != exchange->keys) &&
+       (GNUNET_TIME_absolute_is_future (
+          exchange->keys->key_data_expiration.abs_time)) )
+  {
+    /* We have a valid reply, immediately return result */
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "The exchange `%s' is ready\n",
+                exchange->url);
+    GNUNET_assert (NULL == fo->at);
+    fo->at = GNUNET_SCHEDULER_add_now (&return_keys,
+                                       fo);
+    return fo;
+  }
+  if ( (NULL == exchange->retry_task) &&
+       (NULL == exchange->conn) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "No valid keys, fetching /keys at %s\n",
+                GNUNET_TIME_absolute2s (exchange->first_retry));
+    exchange->retry_task
+      = GNUNET_SCHEDULER_add_at (exchange->first_retry,
+                                 &retry_exchange,
+                                 exchange);
+    return fo;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Next /keys request scheduled for %s\n",
+              GNUNET_TIME_absolute2s (
+                exchange->first_retry));
+  /* No activity to launch, we are already doing so. */
+  return fo;
+}
+
+
+void
+TMH_EXCHANGES_keys4exchange_cancel (
+  struct TMH_EXCHANGES_KeysOperation *fo)
+{
+  struct TMH_Exchange *exchange = fo->my_exchange;
+
+  if (NULL != fo->at)
+  {
+    GNUNET_SCHEDULER_cancel (fo->at);
+    fo->at = NULL;
+  }
+  GNUNET_CONTAINER_DLL_remove (exchange->keys_head,
+                               exchange->keys_tail,
+                               fo);
+  GNUNET_free (fo);
+}
+
+
+/**
+ * Function called with information about the wire fees for each wire method.
+ * Stores the wire fees with the exchange for later use.
  *
  * @param exchange connection to the exchange
  * @param master_pub public key of the exchange
@@ -910,118 +1150,41 @@ get_wire_fees (struct TMH_Exchange *exchange,
 /**
  * Check if we have any remaining pending requests for the
  * given @a exchange, and if we have the required data, call
- * the callback.
+ * the callback.  If requests without /wire data remain,
+ * retry the /wire request after some delay.
  *
- * @param exchange the exchange to check for pending find operations
- * @return true if we need /wire data from @a exchange
+ * Must only be called if 'exchange->keys' is non-NULL.
+ *
+ * @param cls a `struct TMH_Exchange` to check
  */
-static bool
-process_find_operations (struct TMH_Exchange *exchange)
+static void
+wire_task_cb (void *cls);
+
+
+/**
+ * Callbacks of this type are used to serve the result of submitting a
+ * wire format inquiry request to a exchange.
+ *
+ * If the request fails to generate a valid response from the
+ * exchange, @a http_status will also be zero.
+ *
+ * Must only be called if 'exchange->keys' is non-NULL.
+ *
+ * @param cls closure, a `struct TMH_Exchange`
+ * @param wr response details
+ */
+static void
+handle_wire_data (void *cls,
+                  const struct TALER_EXCHANGE_WireResponse *wr)
 {
-  struct TMH_EXCHANGES_Find2Operation *fn2;
-  struct TMH_EXCHANGES_WireOperation *wn;
-  struct GNUNET_TIME_Timestamp now;
+  struct TMH_Exchange *exchange = cls;
+  const struct TALER_EXCHANGE_Keys *keys;
+  enum TALER_ErrorCode ecx;
 
-  fn2 = NULL;
-  for (struct TMH_EXCHANGES_Find2Operation *fo = exchange->fo2_head;
-       NULL != fo;
-       fo = fn2)
-  {
-    fo->fc (fo->fc_cls,
-            exchange->keys);
-    fn2 = fo->next;
-    TMH_EXCHANGES_keys4exchange_cancel (fo);
-  }
-  if (! exchange->have_wire)
-    return true;
-  now = GNUNET_TIME_timestamp_get ();
-  for (struct FeesByWireMethod *fbw = exchange->wire_fees_head;
-       NULL != fbw;
-       fbw = fbw->next)
-  {
-    bool removed = false;
-
-    while ( (NULL != fbw->af) &&
-            (GNUNET_TIME_timestamp_cmp (fbw->af->end_date,
-                                        <,
-                                        now)) )
-    {
-      struct TALER_EXCHANGE_WireAggregateFees *af = fbw->af;
-
-      fbw->af = af->next;
-      GNUNET_free (af);
-      removed = true;
-    }
-    if (NULL == fbw->af)
-    {
-      /* Disagreement on the current time */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Exchange has no wire fees configured for `%s' wire 
method\n",
-                  fbw->wire_method);
-      if (removed)
-      {
-        exchange->have_wire = false;
-        return true; /* We just removed previous fees, try fetching update */
-      }
-    }
-    if (GNUNET_TIME_timestamp_cmp (fbw->af->start_date,
-                                   >,
-                                   now))
-    {
-      /* Disagreement on the current time */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Exchange's earliest fee is %s ahead of our time. Clock skew 
issue?\n",
-                  GNUNET_TIME_relative2s (
-                    GNUNET_TIME_absolute_get_remaining (
-                      fbw->af->start_date.abs_time),
-                    true));
-    }
-  }
-
-  if (! exchange->have_wire)
-    return true; /* need /wire response to continue */
-  wn = NULL;
-  for (struct TMH_EXCHANGES_WireOperation *w = exchange->w_head;
-       NULL != w;
-       w = wn)
-  {
-    w->fc (w->fc_cls,
-           exchange);
-    wn = w->next;
-    TMH_EXCHANGES_wire4exchange_cancel (w);
-  }
-  return false;
-}
-
-
-static void
-wire_task_cb (void *cls);
-
-
-/**
- * Callbacks of this type are used to serve the result of submitting a
- * wire format inquiry request to a exchange.
- *
- * If the request fails to generate a valid response from the
- * exchange, @a http_status will also be zero.
- *
- * Must only be called if 'exchange->keys' is non-NULL.
- *
- * @param cls closure, a `struct TMH_Exchange`
- * @param wr response details
- */
-static void
-handle_wire_data (void *cls,
-                  const struct TALER_EXCHANGE_WireResponse *wr)
-{
-  struct TMH_Exchange *exchange = cls;
-  const struct TALER_EXCHANGE_Keys *keys;
-  enum TALER_ErrorCode ecx;
-
-  exchange->wire_request = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Received /wire response\n");
-  if (MHD_HTTP_OK != wr->hr.http_status)
+  exchange->wire_request = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Received /wire response\n");
+  if (MHD_HTTP_OK != wr->hr.http_status)
   {
     struct TMH_EXCHANGES_WireOperation *w;
 
@@ -1053,15 +1216,15 @@ handle_wire_data (void *cls,
   if (TALER_EC_NONE != ecx)
   {
     /* Report hard failure to all callbacks! */
-    struct TMH_EXCHANGES_Find2Operation *fo2;
+    struct TMH_EXCHANGES_KeysOperation *keys;
 
     GNUNET_break_op (0);
     exchange->have_wire = false;
-    while (NULL != (fo2 = exchange->fo2_head))
+    while (NULL != (keys = exchange->keys_head))
     {
-      fo2->fc (fo2->fc_cls,
-               NULL);
-      TMH_EXCHANGES_keys4exchange_cancel (fo2);
+      keys->fc (keys->fc_cls,
+                NULL);
+      TMH_EXCHANGES_keys4exchange_cancel (keys);
     }
     return;
   }
@@ -1091,16 +1254,6 @@ handle_wire_data (void *cls,
 }
 
 
-/**
- * Check if we have any remaining pending requests for the
- * given @a exchange, and if we have the required data, call
- * the callback.  If requests without /wire data remain,
- * retry the /wire request after some delay.
- *
- * Must only be called if 'exchange->keys' is non-NULL.
- *
- * @param cls a `struct TMH_Exchange` to check
- */
 static void
 wire_task_cb (void *cls)
 {
@@ -1113,7 +1266,7 @@ wire_task_cb (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Initiating /wire download\n");
   exchange->wire_request
-    = TALER_EXCHANGE_wire (merchant_curl_ctx,
+    = TALER_EXCHANGE_wire (TMH_curl_ctx,
                            exchange->url,
                            exchange->keys,
                            &handle_wire_data,
@@ -1172,8 +1325,8 @@ free_exchange_entry (struct TMH_Exchange *exchange)
     GNUNET_SCHEDULER_cancel (exchange->retry_task);
     exchange->retry_task = NULL;
   }
-  GNUNET_assert (NULL == exchange->fo2_head);
-  GNUNET_assert (NULL == exchange->fo2_tail);
+  GNUNET_assert (NULL == exchange->keys_head);
+  GNUNET_assert (NULL == exchange->keys_tail);
   GNUNET_assert (NULL == exchange->w_head);
   GNUNET_assert (NULL == exchange->w_tail);
   GNUNET_free (exchange->url);
@@ -1192,7 +1345,7 @@ static void
 fail_and_retry (struct TMH_Exchange *exchange,
                 const struct TALER_EXCHANGE_HttpResponse *hr)
 {
-  struct TMH_EXCHANGES_Find2Operation *fo2;
+  struct TMH_EXCHANGES_KeysOperation *keys;
   struct TMH_EXCHANGES_WireOperation *w;
 
   if (NULL != exchange->wire_request)
@@ -1205,11 +1358,11 @@ fail_and_retry (struct TMH_Exchange *exchange,
     GNUNET_SCHEDULER_cancel (exchange->wire_task);
     exchange->wire_task = NULL;
   }
-  while (NULL != (fo2 = exchange->fo2_head))
+  while (NULL != (keys = exchange->keys_head))
   {
-    fo2->fc (fo2->fc_cls,
-             NULL);
-    TMH_EXCHANGES_keys4exchange_cancel (fo2);
+    keys->fc (keys->fc_cls,
+              NULL);
+    TMH_EXCHANGES_keys4exchange_cancel (keys);
   }
   while (NULL != (w = exchange->w_head))
   {
@@ -1233,14 +1386,24 @@ fail_and_retry (struct TMH_Exchange *exchange,
                                                       true));
   if (NULL != exchange->retry_task)
     GNUNET_SCHEDULER_cancel (exchange->retry_task);
-  exchange->first_retry = GNUNET_TIME_relative_to_absolute (
-    exchange->retry_delay);
-  exchange->retry_task = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay,
-                                                       &retry_exchange,
-                                                       exchange);
+  exchange->first_retry
+    = GNUNET_TIME_relative_to_absolute (
+        exchange->retry_delay);
+  exchange->retry_task
+    = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay,
+                                    &retry_exchange,
+                                    exchange);
 }
 
 
+/**
+ * Function called with the result of a
+ * /keys request to the exchange.
+ *
+ * @param cls a `struct TMH_Exchange *`
+ * @param kr response details
+ * @param[in] keys key data now owned by this function
+ */
 static void
 keys_mgmt_cb (void *cls,
               const struct TALER_EXCHANGE_KeysResponse *kr,
@@ -1293,13 +1456,14 @@ keys_mgmt_cb (void *cls,
     enum GNUNET_DB_QueryStatus qs;
 
     TMH_db->preflight (TMH_db->cls);
-    qs = TMH_db->insert_exchange_signkey (TMH_db->cls,
-                                          &keys->master_pub,
-                                          &sign_key->key,
-                                          sign_key->valid_from,
-                                          sign_key->valid_until,
-                                          sign_key->valid_legal,
-                                          &sign_key->master_sig);
+    qs = TMH_db->insert_exchange_signkey (
+      TMH_db->cls,
+      &keys->master_pub,
+      &sign_key->key,
+      sign_key->valid_from,
+      sign_key->valid_until,
+      sign_key->valid_legal,
+      &sign_key->master_sig);
     /* 0 is OK, we may already have the key in the DB! */
     if (0 > qs)
     {
@@ -1315,7 +1479,7 @@ keys_mgmt_cb (void *cls,
   delay = GNUNET_TIME_absolute_get_remaining (
     keys->key_data_expiration.abs_time);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "/keys response from expires at %s! Retrying at that time!\n",
+              "/keys response expires at %s! Retrying at that time!\n",
               GNUNET_TIME_absolute2s (
                 keys->key_data_expiration.abs_time));
   delay = GNUNET_TIME_relative_max (delay,
@@ -1327,6 +1491,7 @@ keys_mgmt_cb (void *cls,
     = GNUNET_SCHEDULER_add_delayed (delay,
                                     &retry_exchange,
                                     exchange);
+
   if ( (process_find_operations (exchange)) &&
        (NULL == exchange->wire_request) &&
        (NULL == exchange->wire_task) )
@@ -1335,7 +1500,7 @@ keys_mgmt_cb (void *cls,
                 "Got key data, but also need wire data. Will request /wire 
now\n");
     exchange->wire_request
       = TALER_EXCHANGE_wire (
-          merchant_curl_ctx,
+          TMH_curl_ctx,
           exchange->url,
           exchange->keys,
           &handle_wire_data,
@@ -1344,22 +1509,6 @@ keys_mgmt_cb (void *cls,
 }
 
 
-/**
- * Task to return find operation result asynchronously to caller.
- *
- * @param cls a `struct TMH_EXCHANGES_Find2Operation`
- */
-static void
-return_result2 (void *cls)
-{
-  struct TMH_EXCHANGES_Find2Operation *fo = cls;
-  struct TMH_Exchange *exchange = fo->my_exchange;
-
-  fo->at = NULL;
-  process_find_operations (exchange);
-}
-
-
 /**
  * Task to return find operation result asynchronously to caller.
  *
@@ -1376,115 +1525,6 @@ return_wire_result (void *cls)
 }
 
 
-/**
- * Lookup exchange by @a exchange_url.
- *
- * @param exchange_url base URL to match against
- * @return NULL if exchange is not yet known
- */
-static struct TMH_Exchange *
-lookup_exchange (const char *exchange_url)
-{
-  for (struct TMH_Exchange *exchange = exchange_head;
-       NULL != exchange;
-       exchange = exchange->next)
-    if (0 == strcmp (exchange->url,
-                     exchange_url))
-      return exchange;
-  return NULL;
-}
-
-
-struct TMH_EXCHANGES_Find2Operation *
-TMH_EXCHANGES_keys4exchange (
-  const char *chosen_exchange,
-  TMH_EXCHANGES_Find2Continuation fc,
-  void *fc_cls)
-{
-  struct TMH_Exchange *exchange;
-  struct TMH_EXCHANGES_Find2Operation *fo;
-
-  if (NULL == merchant_curl_ctx)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Trying to find chosen exchange `%s'\n",
-              chosen_exchange);
-  /* Check if the exchange is known */
-  exchange = lookup_exchange (chosen_exchange);
-  if (NULL == exchange)
-  {
-    /* This is a new exchange */
-    exchange = GNUNET_new (struct TMH_Exchange);
-    exchange->url = GNUNET_strdup (chosen_exchange);
-    GNUNET_CONTAINER_DLL_insert (exchange_head,
-                                 exchange_tail,
-                                 exchange);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "The exchange `%s' is new\n",
-                chosen_exchange);
-  }
-
-  fo = GNUNET_new (struct TMH_EXCHANGES_Find2Operation);
-  fo->fc = fc;
-  fo->fc_cls = fc_cls;
-  fo->my_exchange = exchange;
-  GNUNET_CONTAINER_DLL_insert (exchange->fo2_head,
-                               exchange->fo2_tail,
-                               fo);
-
-  if (GNUNET_TIME_absolute_is_past (exchange->first_retry))
-  {
-    /* increment exponential-backoff */
-    exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
-    /* do not allow forced check until both backoff and #FORCED_RELOAD_DELAY
-       are satisfied again */
-    exchange->first_retry
-      = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_max (
-                                            exchange->retry_delay,
-                                            FORCED_RELOAD_DELAY));
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "/keys retry forced, waiting until %s\n",
-                GNUNET_TIME_absolute2s (exchange->first_retry));
-
-    if (NULL == exchange->retry_task)
-      exchange->retry_task
-        = GNUNET_SCHEDULER_add_now (&retry_exchange,
-                                    exchange);
-    return fo;
-  }
-
-  if (NULL != exchange->keys)
-  {
-    /* We are not currently waiting for a reply, immediately
-       return result */
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "The exchange `%s' is ready\n",
-                exchange->url);
-    GNUNET_assert (NULL == fo->at);
-    fo->at = GNUNET_SCHEDULER_add_now (&return_result2,
-                                       fo);
-    return fo;
-  }
-
-  /* If new or resumed, (re)try fetching /keys */
-  if ( (NULL == exchange->keys) &&
-       (NULL == exchange->retry_task) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Do not have current /keys data for `%s'. Will request /keys 
now\n",
-                exchange->url);
-    exchange->retry_task = GNUNET_SCHEDULER_add_now (&retry_exchange,
-                                                     exchange);
-    return fo;
-  }
-  /* No activity to launch, we are already doing so */
-  return fo;
-}
-
-
 struct TMH_EXCHANGES_WireOperation *
 TMH_EXCHANGES_wire4exchange (
   const char *chosen_exchange,
@@ -1494,7 +1534,7 @@ TMH_EXCHANGES_wire4exchange (
   struct TMH_Exchange *exchange;
   struct TMH_EXCHANGES_WireOperation *w;
 
-  if (NULL == merchant_curl_ctx)
+  if (NULL == TMH_curl_ctx)
   {
     GNUNET_break (0);
     return NULL;
@@ -1502,21 +1542,7 @@ TMH_EXCHANGES_wire4exchange (
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Trying to find chosen exchange `%s'\n",
               chosen_exchange);
-  /* Check if the exchange is known */
   exchange = lookup_exchange (chosen_exchange);
-  if (NULL == exchange)
-  {
-    /* This is a new exchange */
-    exchange = GNUNET_new (struct TMH_Exchange);
-    exchange->url = GNUNET_strdup (chosen_exchange);
-    GNUNET_CONTAINER_DLL_insert (exchange_head,
-                                 exchange_tail,
-                                 exchange);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "The exchange `%s' is new\n",
-                chosen_exchange);
-  }
-
   w = GNUNET_new (struct TMH_EXCHANGES_WireOperation);
   w->fc = fc;
   w->fc_cls = fc_cls;
@@ -1536,56 +1562,42 @@ TMH_EXCHANGES_wire4exchange (
                                       w);
     return w;
   }
-
-  if (NULL == exchange->wire_request)
+  if (NULL != exchange->wire_request)
+    return w; /* /wire request is active, do nothing */
+  if ( (NULL != exchange->keys) &&
+       (GNUNET_TIME_absolute_is_future (
+          exchange->keys->key_data_expiration.abs_time)) )
   {
-    if (NULL == exchange->conn)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Requesting /keys from `%s' to connect\n",
-                  exchange->url);
-      exchange->conn = TALER_EXCHANGE_get_keys (merchant_curl_ctx,
-                                                exchange->url,
-                                                exchange->keys,
-                                                &keys_mgmt_cb,
-                                                exchange);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Requesting /wire from `%s'\n",
-                  exchange->url);
-      exchange->wire_request
-        = TALER_EXCHANGE_wire (merchant_curl_ctx,
-                               exchange->url,
-                               exchange->keys,
-                               &handle_wire_data,
-                               exchange);
-    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Requesting /wire from `%s'\n",
+                exchange->url);
+    exchange->wire_request
+      = TALER_EXCHANGE_wire (TMH_curl_ctx,
+                             exchange->url,
+                             exchange->keys,
+                             &handle_wire_data,
+                             exchange);
+    return w;
   }
-  return w;
-}
-
-
-void
-TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_Find2Operation *fo)
-{
-  struct TMH_Exchange *exchange = fo->my_exchange;
+  if ( (NULL == exchange->keys) &&
+       ( (NULL != exchange->conn) ||
+         (NULL != exchange->retry_task) ) )
+    return w; /* /keys request active, do nothing */
 
-  if (NULL != fo->at)
-  {
-    GNUNET_SCHEDULER_cancel (fo->at);
-    fo->at = NULL;
-  }
-  GNUNET_CONTAINER_DLL_remove (exchange->fo2_head,
-                               exchange->fo2_tail,
-                               fo);
-  GNUNET_free (fo);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "No valid keys, fetching /keys at %s\n",
+              GNUNET_TIME_absolute2s (exchange->first_retry));
+  exchange->retry_task
+    = GNUNET_SCHEDULER_add_at (exchange->first_retry,
+                               &retry_exchange,
+                               exchange);
+  return w;
 }
 
 
 void
-TMH_EXCHANGES_wire4exchange_cancel (struct TMH_EXCHANGES_WireOperation *w)
+TMH_EXCHANGES_wire4exchange_cancel (
+  struct TMH_EXCHANGES_WireOperation *w)
 {
   struct TMH_Exchange *exchange = w->my_exchange;
 
@@ -1601,10 +1613,128 @@ TMH_EXCHANGES_wire4exchange_cancel (struct 
TMH_EXCHANGES_WireOperation *w)
 }
 
 
+enum GNUNET_GenericReturnValue
+TMH_EXCHANGES_lookup_wire_fee (
+  const struct TMH_ExchangeWireDetails *wd,
+  const char *wire_method,
+  struct TALER_Amount *wire_fee)
+{
+  struct TMH_Exchange *exchange = wd->exchange;
+  const struct FeesByWireMethod *fbm;
+  const struct TALER_EXCHANGE_WireAggregateFees *af;
+
+  if (! exchange->have_wire)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  fbm = get_wire_fees (exchange,
+                       GNUNET_TIME_timestamp_get (),
+                       wire_method);
+  if (NULL == fbm)
+    return GNUNET_NO;
+  af = fbm->af;
+  *wire_fee = af->fees.wire;
+  return GNUNET_OK;
+}
+
+
+enum GNUNET_GenericReturnValue
+TMH_exchange_check_debit (
+  const struct TMH_ExchangeWireDetails *wd,
+  const struct TMH_WireMethod *wm)
+{
+  struct TMH_Exchange *ex = wd->exchange;
+  for (struct ExchangeAccount *acc = ex->acc_head;
+       NULL != acc;
+       acc = acc->next)
+  {
+    bool ok = true;
+
+    if (0 != strcmp (acc->wire_method,
+                     wm->wire_method))
+      continue;
+    if (NULL != acc->conversion_url)
+      continue; /* never use accounts with conversion */
+    for (struct Restriction *r = acc->d_head;
+         NULL != r;
+         r = r->next)
+    {
+      switch (r->type)
+      {
+      case TALER_EXCHANGE_AR_INVALID:
+        GNUNET_break (0);
+        ok = false;
+        break;
+      case TALER_EXCHANGE_AR_DENY:
+        ok = false;
+        break;
+      case TALER_EXCHANGE_AR_REGEX:
+        if (0 != regexec (&r->details.regex.ex,
+                          wm->payto_uri,
+                          0, NULL, 0))
+          ok = false;
+        break;
+      }
+      if (! ok)
+        break;
+    }
+
+    if (ok)
+      return GNUNET_OK;
+  }
+  return GNUNET_NO;
+}
+
+
+json_t *
+TMH_exchange_get_acceptable (const struct TMH_WireMethod *wm)
+{
+  json_t *te = json_array ();
+
+  GNUNET_assert (NULL != te);
+  for (struct TMH_Exchange *exchange = exchange_head;
+       NULL != exchange;
+       exchange = exchange->next)
+  {
+    json_t *j_exchange;
+    unsigned int priority;
+
+    if (! exchange->trusted)
+      continue;
+    priority = 512; /* medium */
+    if (exchange->have_wire)
+    {
+      struct TMH_ExchangeWireDetails wd = {
+        .exchange = exchange
+      };
+
+      if (GNUNET_OK ==
+          TMH_exchange_check_debit (&wd,
+                                    wm))
+        priority = 1024; /* high */
+      else
+        priority = 0; /* negative response */
+    }
+    j_exchange = GNUNET_JSON_PACK (
+      GNUNET_JSON_pack_string ("url",
+                               exchange->url),
+      GNUNET_JSON_pack_uint64 ("priority",
+                               priority),
+      GNUNET_JSON_pack_data_auto ("master_pub",
+                                  &exchange->master_pub));
+    GNUNET_assert (NULL != j_exchange);
+    GNUNET_assert (0 ==
+                   json_array_append_new (te,
+                                          j_exchange));
+  }
+  return te;
+}
+
+
 /**
  * Function called on each configuration section. Finds sections
- * about exchanges, parses the entries and tries to connect to
- * it in order to fetch /keys.
+ * about exchanges, parses the entries.
  *
  * @param cls closure, with a `const struct GNUNET_CONFIGURATION_Handle *`
  * @param section name of the section
@@ -1677,7 +1807,7 @@ accept_exchanges (void *cls,
       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
                                  section,
                                  "MASTER_KEY",
-                                 _ ("ill-formed EdDSA key"));
+                                 "malformed EdDSA key");
     }
     GNUNET_free (mks);
   }
@@ -1686,7 +1816,6 @@ accept_exchanges (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "MASTER_KEY missing in section '%s', not trusting exchange\n",
                 section);
-
   }
   GNUNET_CONTAINER_DLL_insert (exchange_head,
                                exchange_tail,
@@ -1697,54 +1826,9 @@ accept_exchanges (void *cls,
 }
 
 
-enum GNUNET_GenericReturnValue
-TMH_EXCHANGES_lookup_wire_fee (const char *exchange_url,
-                               const char *wire_method,
-                               struct TALER_Amount *wire_fee)
-{
-  struct TMH_Exchange *exchange;
-  const struct FeesByWireMethod *fbm;
-  const struct TALER_EXCHANGE_WireAggregateFees *af;
-
-  exchange = lookup_exchange (exchange_url);
-  if (NULL == exchange)
-  {
-    return GNUNET_SYSERR;
-  }
-  if (! exchange->have_wire)
-  {
-    return GNUNET_SYSERR;
-  }
-  fbm = get_wire_fees (exchange,
-                       GNUNET_TIME_timestamp_get (),
-                       wire_method);
-  if (NULL == fbm)
-    return GNUNET_NO;
-  af = fbm->af;
-  *wire_fee = af->fees.wire;
-  return GNUNET_OK;
-}
-
-
 enum GNUNET_GenericReturnValue
 TMH_EXCHANGES_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
-  merchant_curl_ctx
-    = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
-                        &merchant_curl_rc);
-  if (NULL == merchant_curl_ctx)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  merchant_curl_rc = GNUNET_CURL_gnunet_rc_create (merchant_curl_ctx);
-  /* Disable 100 continue processing */
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CURL_append_header (merchant_curl_ctx,
-                                           MHD_HTTP_HEADER_EXPECT ":"));
-
-  GNUNET_CURL_enable_async_scope_header (merchant_curl_ctx,
-                                         "Taler-Correlation-Id");
   /* get exchanges from the merchant configuration and try to connect to them 
*/
   GNUNET_CONFIGURATION_iterate_sections (cfg,
                                          &accept_exchanges,
@@ -1759,103 +1843,6 @@ TMH_EXCHANGES_done ()
 {
   while (NULL != exchange_head)
     free_exchange_entry (exchange_head);
-  if (NULL != merchant_curl_ctx)
-  {
-    GNUNET_CURL_fini (merchant_curl_ctx);
-    merchant_curl_ctx = NULL;
-  }
-  if (NULL != merchant_curl_rc)
-  {
-    GNUNET_CURL_gnunet_rc_destroy (merchant_curl_rc);
-    merchant_curl_rc = NULL;
-  }
-}
-
-
-enum GNUNET_GenericReturnValue
-TMH_exchange_check_debit (struct TMH_Exchange *ex,
-                          const struct TMH_WireMethod *wm)
-{
-  for (struct ExchangeAccount *acc = ex->acc_head;
-       NULL != acc;
-       acc = acc->next)
-  {
-    bool ok = true;
-
-    if (0 != strcmp (acc->wire_method,
-                     wm->wire_method))
-      continue;
-    if (NULL != acc->conversion_url)
-      continue; /* never use accounts with conversion */
-    for (struct Restriction *r = acc->d_head;
-         NULL != r;
-         r = r->next)
-    {
-      switch (r->type)
-      {
-      case TALER_EXCHANGE_AR_INVALID:
-        GNUNET_break (0);
-        ok = false;
-        break;
-      case TALER_EXCHANGE_AR_DENY:
-        ok = false;
-        break;
-      case TALER_EXCHANGE_AR_REGEX:
-        if (0 != regexec (&r->details.regex.ex,
-                          wm->payto_uri,
-                          0, NULL, 0))
-          ok = false;
-        break;
-      }
-      if (! ok)
-        break;
-    }
-
-    if (ok)
-      return GNUNET_OK;
-  }
-  return GNUNET_NO;
-}
-
-
-json_t *
-TMH_exchange_get_acceptable (const struct TMH_WireMethod *wm)
-{
-  json_t *te = json_array ();
-
-  GNUNET_assert (NULL != te);
-  for (struct TMH_Exchange *exchange = exchange_head;
-       NULL != exchange;
-       exchange = exchange->next)
-  {
-    json_t *j_exchange;
-    unsigned int priority;
-
-    if (! exchange->trusted)
-      continue;
-    priority = 512; /* medium */
-    if (exchange->have_wire)
-    {
-      if (GNUNET_OK ==
-          TMH_exchange_check_debit (exchange,
-                                    wm))
-        priority = 1024; /* high */
-      else
-        priority = 0; /* negative response */
-    }
-    j_exchange = GNUNET_JSON_PACK (
-      GNUNET_JSON_pack_string ("url",
-                               exchange->url),
-      GNUNET_JSON_pack_uint64 ("priority",
-                               priority),
-      GNUNET_JSON_pack_data_auto ("master_pub",
-                                  &exchange->master_pub));
-    GNUNET_assert (NULL != j_exchange);
-    GNUNET_assert (0 ==
-                   json_array_append_new (te,
-                                          j_exchange));
-  }
-  return te;
 }
 
 
diff --git a/src/backend/taler-merchant-httpd_exchanges.h 
b/src/backend/taler-merchant-httpd_exchanges.h
index 5fc57a3e..2a2e9b13 100644
--- a/src/backend/taler-merchant-httpd_exchanges.h
+++ b/src/backend/taler-merchant-httpd_exchanges.h
@@ -36,21 +36,6 @@
 struct TMH_Exchange;
 
 
-/**
- * Check if we would trust @a ex to deposit funds
- * into our account @a wm. Checks that both @a ex
- * is trusted and that @a ex allows wire transfers
- * into the account given in @a wm.
- *
- * @param ex the exchange to check
- * @param wm the wire method to check with
- * @return #GNUNET_OK if such a debit can happen
- */
-enum GNUNET_GenericReturnValue
-TMH_exchange_check_debit (struct TMH_Exchange *ex,
-                          const struct TMH_WireMethod *wm);
-
-
 /**
  * Return the list of exchanges we would find
  * acceptable for a payment given the @a wire_method.
@@ -95,6 +80,12 @@ typedef void
   struct TALER_EXCHANGE_Keys *keys);
 
 
+/**
+ * Abstraction of wire knowledge returned internally.
+ */
+struct TMH_ExchangeWireDetails;
+
+
 /**
  * Function called with the result of a #TMH_EXCHANGES_wire4exchange()
  * operation.
@@ -105,13 +96,13 @@ typedef void
 typedef void
 (*TMH_EXCHANGES_WireContinuation)(
   void *cls,
-  struct TMH_Exchange *wire);
+  const struct TMH_ExchangeWireDetails *wire);
 
 
 /**
  * Information we keep for a pending #MMH_EXCHANGES_keys4exchange() operation.
  */
-struct TMH_EXCHANGES_Find2Operation;
+struct TMH_EXCHANGES_KeysOperation;
 
 /**
  * Information we keep for a pending #MMH_EXCHANGES_wire4exchange() operation.
@@ -126,10 +117,20 @@ struct TMH_EXCHANGES_WireOperation;
  * @param fc function to call with the handles for the exchange
  * @param fc_cls closure for @a fc
  */
-struct TMH_EXCHANGES_Find2Operation *
-TMH_EXCHANGES_keys4exchange (const char *exchange,
-                             TMH_EXCHANGES_Find2Continuation fc,
-                             void *fc_cls);
+struct TMH_EXCHANGES_KeysOperation *
+TMH_EXCHANGES_keys4exchange (
+  const char *exchange,
+  TMH_EXCHANGES_Find2Continuation fc,
+  void *fc_cls);
+
+
+/**
+ * Abort pending keys details lookup operation.
+ *
+ * @param fo handle to operation to abort
+ */
+void
+TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_KeysOperation *fo);
 
 
 /**
@@ -140,9 +141,20 @@ TMH_EXCHANGES_keys4exchange (const char *exchange,
  * @param fc_cls closure for @a fc
  */
 struct TMH_EXCHANGES_WireOperation *
-TMH_EXCHANGES_wire4exchange (const char *exchange,
-                             TMH_EXCHANGES_WireContinuation fc,
-                             void *fc_cls);
+TMH_EXCHANGES_wire4exchange (
+  const char *exchange,
+  TMH_EXCHANGES_WireContinuation fc,
+  void *fc_cls);
+
+
+/**
+ * Abort pending wire details lookup operation.
+ *
+ * @param fo handle to operation to abort
+ */
+void
+TMH_EXCHANGES_wire4exchange_cancel (
+  struct TMH_EXCHANGES_WireOperation *fo);
 
 
 /**
@@ -157,27 +169,26 @@ TMH_EXCHANGES_wire4exchange (const char *exchange,
  *         #GNUNET_SYSERR if @a exchange_url did not yet respond properly to 
our /wire request
  */
 enum GNUNET_GenericReturnValue
-TMH_EXCHANGES_lookup_wire_fee (const char *exchange_url,
-                               const char *wire_method,
-                               struct TALER_Amount *wire_fee);
+TMH_EXCHANGES_lookup_wire_fee (
+  const struct TMH_ExchangeWireDetails *wd,
+  const char *wire_method,
+  struct TALER_Amount *wire_fee);
 
 
 /**
- * Abort pending keys details lookup operation.
- *
- * @param fo handle to operation to abort
- */
-void
-TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_Find2Operation *fo);
-
-
-/**
- * Abort pending wire details lookup operation.
+ * Check if we would trust @a ex to deposit funds
+ * into our account @a wm. Checks that both @a ex
+ * is trusted and that @a ex allows wire transfers
+ * into the account given in @a wm.
  *
- * @param fo handle to operation to abort
+ * @param wd the wire details of the exchange to check
+ * @param wm the wire method to check with
+ * @return #GNUNET_OK if such a debit can happen
  */
-void
-TMH_EXCHANGES_wire4exchange_cancel (struct TMH_EXCHANGES_WireOperation *fo);
+enum GNUNET_GenericReturnValue
+TMH_exchange_check_debit (
+  const struct TMH_ExchangeWireDetails *wd,
+  const struct TMH_WireMethod *wm);
 
 
 #endif
diff --git a/src/backend/taler-merchant-httpd_helper.c 
b/src/backend/taler-merchant-httpd_helper.c
index 407323e2..172cb0a1 100644
--- a/src/backend/taler-merchant-httpd_helper.c
+++ b/src/backend/taler-merchant-httpd_helper.c
@@ -732,111 +732,6 @@ TMH_trigger_webhook (const char *instance,
 }
 
 
-/**
- * Closure for #add_matching_account().
- */
-struct ExchangeMatchContext
-{
-  /**
-   * Wire method to match, NULL for all.
-   */
-  const char *wire_method;
-
-  /**
-   * Array of accounts to return.
-   */
-  json_t *accounts;
-};
-
-
-/**
- * If the given account is feasible, add it to the array
- * of accounts we return.
- *
- * @param cls a `struct PostReserveContext`
- * @param payto_uri URI of the account
- * @param conversion_url URL of a conversion service
- * @param debit_restrictions restrictions for debits from account
- * @param credit_restrictions restrictions for credits to account
- * @param master_sig signature affirming the account
- */
-static void
-add_matching_account (void *cls,
-                      const char *payto_uri,
-                      const char *conversion_url,
-                      const json_t *debit_restrictions,
-                      const json_t *credit_restrictions,
-                      const struct TALER_MasterSignatureP *master_sig)
-{
-  struct ExchangeMatchContext *rc = cls;
-  char *method;
-
-  method = TALER_payto_get_method (payto_uri);
-  if ( (NULL == rc->wire_method) ||
-       (0 == strcmp (method,
-                     rc->wire_method)) )
-  {
-    json_t *acc;
-
-    acc = GNUNET_JSON_PACK (
-      GNUNET_JSON_pack_string ("payto_uri",
-                               payto_uri),
-      GNUNET_JSON_pack_data_auto ("master_sig",
-                                  master_sig),
-      GNUNET_JSON_pack_allow_null (
-        GNUNET_JSON_pack_string ("conversion_url",
-                                 conversion_url)),
-      GNUNET_JSON_pack_array_incref ("credit_restrictions",
-                                     (json_t *) credit_restrictions),
-      GNUNET_JSON_pack_array_incref ("debit_restrictions",
-                                     (json_t *) debit_restrictions)
-      );
-    GNUNET_assert (0 ==
-                   json_array_append_new (rc->accounts,
-                                          acc));
-  }
-  GNUNET_free (method);
-}
-
-
-/**
- * Return JSON array with all of the exchange accounts
- * that support the given @a wire_method.
- *
- * FIXME: bad API, doesn't inherently ensure that we
- * actually did request /wire before!
- * => move into t-m-h_exchanges.c and integrate with /wire
- * logic there!
- *
- * @param master_pub master public key to match exchange by
- * @param wire_method NULL for any
- * @return JSON array with information about all matching accounts
- */
-json_t *
-TMH_exchange_accounts_by_method (
-  const struct TALER_MasterPublicKeyP *master_pub,
-  const char *wire_method)
-{
-  struct ExchangeMatchContext emc = {
-    .wire_method = wire_method,
-    .accounts = json_array ()
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  GNUNET_assert (NULL != emc.accounts);
-  qs = TMH_db->select_accounts_by_exchange (TMH_db->cls,
-                                            master_pub,
-                                            &add_matching_account,
-                                            &emc);
-  if (qs < 0)
-  {
-    json_decref (emc.accounts);
-    return NULL;
-  }
-  return emc.accounts;
-}
-
-
 enum GNUNET_GenericReturnValue
 TMH_base_url_by_connection (struct MHD_Connection *connection,
                             const char *instance,
@@ -948,3 +843,104 @@ TMH_taler_uri_by_connection (struct MHD_Connection 
*connection,
   }
   return GNUNET_OK;
 }
+
+
+/**
+ * Closure for #add_matching_account().
+ */
+struct ExchangeMatchContext
+{
+  /**
+   * Wire method to match, NULL for all.
+   */
+  const char *wire_method;
+
+  /**
+   * Array of accounts to return.
+   */
+  json_t *accounts;
+};
+
+
+/**
+ * If the given account is feasible, add it to the array
+ * of accounts we return.
+ *
+ * @param cls a `struct PostReserveContext`
+ * @param payto_uri URI of the account
+ * @param conversion_url URL of a conversion service
+ * @param debit_restrictions restrictions for debits from account
+ * @param credit_restrictions restrictions for credits to account
+ * @param master_sig signature affirming the account
+ */
+static void
+add_matching_account (
+  void *cls,
+  const char *payto_uri,
+  const char *conversion_url,
+  const json_t *debit_restrictions,
+  const json_t *credit_restrictions,
+  const struct TALER_MasterSignatureP *master_sig)
+{
+  struct ExchangeMatchContext *rc = cls;
+  char *method;
+
+  method = TALER_payto_get_method (payto_uri);
+  if ( (NULL == rc->wire_method) ||
+       (0 == strcmp (method,
+                     rc->wire_method)) )
+  {
+    json_t *acc;
+
+    acc = GNUNET_JSON_PACK (
+      GNUNET_JSON_pack_string ("payto_uri",
+                               payto_uri),
+      GNUNET_JSON_pack_data_auto ("master_sig",
+                                  master_sig),
+      GNUNET_JSON_pack_allow_null (
+        GNUNET_JSON_pack_string ("conversion_url",
+                                 conversion_url)),
+      GNUNET_JSON_pack_array_incref ("credit_restrictions",
+                                     (json_t *) credit_restrictions),
+      GNUNET_JSON_pack_array_incref ("debit_restrictions",
+                                     (json_t *) debit_restrictions)
+      );
+    GNUNET_assert (0 ==
+                   json_array_append_new (rc->accounts,
+                                          acc));
+  }
+  GNUNET_free (method);
+}
+
+
+/**
+ * Return JSON array with all of the exchange accounts
+ * that support the given @a wire_method.
+ *
+ * @param master_pub master public key to match exchange by
+ * @param wire_method NULL for any
+ * @return JSON array with information about all matching accounts
+ */
+json_t *
+TMH_exchange_accounts_by_method (
+  const struct TALER_MasterPublicKeyP *master_pub,
+  const char *wire_method)
+{
+  struct ExchangeMatchContext emc = {
+    .wire_method = wire_method,
+    .accounts = json_array ()
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  GNUNET_assert (NULL != emc.accounts);
+  qs = TMH_db->select_accounts_by_exchange (TMH_db->cls,
+                                            master_pub,
+                                            &add_matching_account,
+                                            &emc);
+  if (qs < 0)
+  {
+    json_decref (emc.accounts);
+    return NULL;
+  }
+  return emc.accounts;
+}
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
index f5d76436..f63404b4 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
@@ -176,7 +176,7 @@ struct AbortContext
    * the exchange used for this transaction; NULL if no operation is
    * pending.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * URL of the exchange used for the last @e fo.
@@ -532,7 +532,7 @@ process_abort_with_exchange (void *cls,
     rdi->processed = true;
     ac->pending--;
     rdi->rh = TALER_EXCHANGE_refund (
-      merchant_curl_ctx,
+      TMH_curl_ctx,
       ac->current_exchange,
       keys,
       &rdi->amount_with_fee,
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index 3a051a3c..75bc4345 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -173,7 +173,7 @@ struct ExchangeGroup
    * the exchange used for this transaction; NULL if no operation is
    * pending.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * Handle for operation to lookup /wire from
@@ -188,6 +188,12 @@ struct ExchangeGroup
    */
   const char *exchange_url;
 
+  /**
+   * Wire fee that applies to this exchange for the
+   * given payment context's wire method.
+   */
+  struct TALER_Amount wire_fee;
+
   /**
    * true if we already tried a forced /keys download.
    */
@@ -454,7 +460,7 @@ struct KycContext
   /**
    * Looking for the exchange.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * Exchange this is about.
@@ -636,20 +642,19 @@ resume_pay_with_response (struct PayContext *pc,
  * Resume payment processing with an error.
  *
  * @param pc operation to resume
- * @param http_status http status code to return
  * @param ec taler error code to return
  * @param msg human readable error message
  */
 static void
 resume_pay_with_error (struct PayContext *pc,
-                       unsigned int http_status,
                        enum TALER_ErrorCode ec,
                        const char *msg)
 {
-  resume_pay_with_response (pc,
-                            http_status,
-                            TALER_MHD_make_error (ec,
-                                                  msg));
+  resume_pay_with_response (
+    pc,
+    TALER_ErrorCode_get_http_status_safe (ec),
+    TALER_MHD_make_error (ec,
+                          msg));
 }
 
 
@@ -795,7 +800,7 @@ process_kyc_with_exchange (
     return;
   }
   kc->dg = TALER_EXCHANGE_deposits_get (
-    merchant_curl_ctx,
+    TMH_curl_ctx,
     kc->exchange_url,
     keys,
     &kc->mi->merchant_priv,
@@ -1007,7 +1012,6 @@ handle_batch_deposit_ok (struct ExchangeGroup *eg,
         GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
         /* Forward error including 'proof' for the body */
         resume_pay_with_error (pc,
-                               MHD_HTTP_INTERNAL_SERVER_ERROR,
                                TALER_EC_GENERIC_DB_STORE_FAILED,
                                "insert_deposit");
         return;
@@ -1023,7 +1027,6 @@ handle_batch_deposit_ok (struct ExchangeGroup *eg,
     {
       GNUNET_break (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              TALER_EC_GENERIC_DB_COMMIT_FAILED,
                              "insert_deposit");
     }
@@ -1032,7 +1035,6 @@ handle_batch_deposit_ok (struct ExchangeGroup *eg,
   if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   {
     resume_pay_with_error (pc,
-                           MHD_HTTP_INTERNAL_SERVER_ERROR,
                            TALER_EC_GENERIC_DB_SOFT_FAILURE,
                            "insert_deposit");
     return;
@@ -1160,6 +1162,7 @@ process_pay_with_keys (
   unsigned int group_size;
 
   eg->fo = NULL;
+  GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Processing payment with exchange %s\n",
               eg->exchange_url);
@@ -1168,11 +1171,10 @@ process_pay_with_keys (
   {
     GNUNET_break_op (0);
     pc->pending_at_eg--;
-    resume_pay_with_response (
+    resume_pay_with_error (
       pc,
-      MHD_HTTP_GATEWAY_TIMEOUT,
-      TALER_MHD_MAKE_JSON_PACK (
-        TALER_JSON_pack_ec (TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT)));
+      TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
+      NULL);
     return;
   }
 
@@ -1286,7 +1288,8 @@ AGE_FAIL:
                                  &dc->cdd.h_age_commitment);
       GNUNET_free (dc->age_commitment.keys);
     }
-    else if (is_age_restricted_denom && dc->no_h_age_commitment)
+    else if (is_age_restricted_denom &&
+             dc->no_h_age_commitment)
     {
       /* The contract did not ask for a minimum_age but the client paid
        * with a coin that has age restriction enabled.  We lack the hash
@@ -1336,7 +1339,6 @@ AGE_FAIL:
     for (unsigned int i = 0; i<pc->coins_cnt; i++)
     {
       struct DepositConfirmation *dc = &pc->dc[i];
-      enum GNUNET_GenericReturnValue ret;
 
       if (dc->found_in_db)
         continue;
@@ -1344,36 +1346,13 @@ AGE_FAIL:
                        eg->exchange_url))
         continue;
       cdds[i] = dc->cdd;
-      ret = TMH_EXCHANGES_lookup_wire_fee (dc->exchange_url,
-                                           pc->wm->wire_method,
-                                           &dc->wire_fee);
-      if (GNUNET_OK != ret)
-      {
-        enum TALER_ErrorCode ec;
-
-        fprintf (stderr,
-                 "%d\n",
-                 ret);
-        ec = (GNUNET_NO == ret)
-          ? TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED
-          : TALER_EC_MERCHANT_GENERIC_EXCHANGE_WIRE_REQUEST_FAILED;
-        pc->pending_at_eg--;
-        GNUNET_break_op (0);
-        resume_pay_with_response (
-          pc,
-          TALER_ErrorCode_get_http_status_safe (ec),
-          TALER_MHD_MAKE_JSON_PACK (
-            TALER_JSON_pack_ec (ec),
-            GNUNET_JSON_pack_string ("wire_method",
-                                     pc->wm->wire_method)));
-        return;
-      }
+      dc->wire_fee = eg->wire_fee;
     }
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Initiating batch deposit with %u coins\n",
                 group_size);
     eg->bdh = TALER_EXCHANGE_batch_deposit (
-      merchant_curl_ctx,
+      TMH_curl_ctx,
       eg->exchange_url,
       keys,
       &dcd,
@@ -1413,23 +1392,24 @@ AGE_FAIL:
 static void
 process_pay_with_wire (
   void *cls,
-  struct TMH_Exchange *wire)
+  const struct TMH_ExchangeWireDetails *wire)
 {
   struct ExchangeGroup *eg = cls;
   struct PayContext *pc = eg->pc;
+  struct TMH_HandlerContext *hc = pc->hc;
+  enum GNUNET_GenericReturnValue ret;
 
   eg->gwo = NULL;
+  GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id);
   if (NULL == wire)
   {
     GNUNET_break_op (0);
     pc->pending_at_eg--;
     /* FIXME: define more specific error code... */
-    resume_pay_with_response (
+    resume_pay_with_error (
       pc,
-      MHD_HTTP_BAD_GATEWAY,
-      TALER_MHD_MAKE_JSON_PACK (
-        TALER_JSON_pack_ec (
-          TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE)));
+      TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE,
+      NULL);
     return;
   }
   if (GNUNET_OK !=
@@ -1438,16 +1418,32 @@ process_pay_with_wire (
   {
     GNUNET_break_op (0);
     pc->pending_at_eg--;
-    resume_pay_with_response (
+    resume_pay_with_error (
       pc,
-      MHD_HTTP_CONFLICT,
-      TALER_MHD_MAKE_JSON_PACK (
-        TALER_JSON_pack_ec (
-          TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED)));
+      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED,
+      NULL);
+    return;
+  }
+  ret = TMH_EXCHANGES_lookup_wire_fee (wire,
+                                       pc->wm->wire_method,
+                                       &eg->wire_fee);
+  if (GNUNET_OK != ret)
+  {
+    enum TALER_ErrorCode ec;
+
+    ec = (GNUNET_NO == ret)
+      ? TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED
+      : TALER_EC_MERCHANT_GENERIC_EXCHANGE_WIRE_REQUEST_FAILED;
+    pc->pending_at_eg--;
+    GNUNET_break_op (0);
+    resume_pay_with_error (
+      pc,
+      ec,
+      pc->wm->wire_method);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Fetching /keys for %s\n",
+              "Got /wire for %s, now going for /keys\n",
               eg->exchange_url);
   eg->fo = TMH_EXCHANGES_keys4exchange (eg->exchange_url,
                                         &process_pay_with_keys,
@@ -1457,7 +1453,6 @@ process_pay_with_wire (
     GNUNET_break (0);
     pc->pending_at_eg--;
     resume_pay_with_error (pc,
-                           MHD_HTTP_INTERNAL_SERVER_ERROR,
                            
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LOOKUP_FAILED,
                            "Failed to lookup exchange by URL");
     return;
@@ -1503,7 +1498,6 @@ start_batch_deposits (struct PayContext *pc)
     {
       GNUNET_break (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LOOKUP_FAILED,
                              "Failed to lookup exchange by URL");
       return;
@@ -1665,7 +1659,6 @@ check_payment_sufficient (struct PayContext *pc)
       GNUNET_break (0);
       /* Overflow in these amounts? Very strange. */
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
                              "Overflow adding up amounts");
       return false;
@@ -1676,7 +1669,6 @@ check_payment_sufficient (struct PayContext *pc)
     {
       GNUNET_break_op (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_BAD_REQUEST,
                              
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT,
                              "Deposit fees exceed coin's contribution");
       return false;
@@ -1703,7 +1695,6 @@ check_payment_sufficient (struct PayContext *pc)
       {
         GNUNET_break_op (0);
         resume_pay_with_error (pc,
-                               MHD_HTTP_CONFLICT,
                                TALER_EC_GENERIC_CURRENCY_MISMATCH,
                                total_wire_fee.currency);
         return false;
@@ -1715,7 +1706,6 @@ check_payment_sufficient (struct PayContext *pc)
       {
         GNUNET_break (0);
         resume_pay_with_error (pc,
-                               MHD_HTTP_INTERNAL_SERVER_ERROR,
                                
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED,
                                "could not add exchange wire fee to total");
         return false;
@@ -1750,7 +1740,6 @@ check_payment_sufficient (struct PayContext *pc)
   {
     GNUNET_break (0);
     resume_pay_with_error (pc,
-                           MHD_HTTP_CONFLICT,
                            TALER_EC_GENERIC_CURRENCY_MISMATCH,
                            total_wire_fee.currency);
     return false;
@@ -1787,7 +1776,6 @@ check_payment_sufficient (struct PayContext *pc)
   {
     GNUNET_break (0);
     resume_pay_with_error (pc,
-                           MHD_HTTP_INTERNAL_SERVER_ERROR,
                            
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
                            "Overflow adding up amounts");
     return false;
@@ -1815,7 +1803,6 @@ check_payment_sufficient (struct PayContext *pc)
     {
       GNUNET_break (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
                              "Overflow adding up amounts");
       return false;
@@ -1839,7 +1826,6 @@ check_payment_sufficient (struct PayContext *pc)
   {
     GNUNET_break (0);
     resume_pay_with_error (pc,
-                           MHD_HTTP_INTERNAL_SERVER_ERROR,
                            
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS,
                            "refunded amount exceeds total payments");
     return false;
@@ -1854,7 +1840,6 @@ check_payment_sufficient (struct PayContext *pc)
     {
       GNUNET_break_op (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_PAYMENT_REQUIRED,
                              TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDED,
                              "contract not paid up due to refunds");
     }
@@ -1863,7 +1848,6 @@ check_payment_sufficient (struct PayContext *pc)
     {
       GNUNET_break_op (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_NOT_ACCEPTABLE,
                              
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES,
                              "contract not paid up due to fees (client may 
have calculated them badly)");
     }
@@ -1871,7 +1855,6 @@ check_payment_sufficient (struct PayContext *pc)
     {
       GNUNET_break_op (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_NOT_ACCEPTABLE,
                              
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT,
                              "payment insufficient");
     }
@@ -1982,7 +1965,6 @@ execute_pay_transaction (struct PayContext *pc)
   {
     GNUNET_break (0);
     resume_pay_with_error (pc,
-                           MHD_HTTP_INTERNAL_SERVER_ERROR,
                            TALER_EC_GENERIC_DB_SOFT_FAILURE,
                            NULL);
     return;
@@ -2013,7 +1995,6 @@ execute_pay_transaction (struct PayContext *pc)
   {
     GNUNET_break (0);
     resume_pay_with_error (pc,
-                           MHD_HTTP_INTERNAL_SERVER_ERROR,
                            TALER_EC_GENERIC_DB_START_FAILED,
                            NULL);
     return;
@@ -2039,7 +2020,6 @@ execute_pay_transaction (struct PayContext *pc)
       /* Always report on hard error as well to enable diagnostics */
       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              TALER_EC_GENERIC_DB_FETCH_FAILED,
                              "lookup deposits");
       return;
@@ -2067,7 +2047,6 @@ execute_pay_transaction (struct PayContext *pc)
       /* Always report on hard error as well to enable diagnostics */
       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              TALER_EC_GENERIC_DB_FETCH_FAILED,
                              "lookup refunds");
       return;
@@ -2117,7 +2096,6 @@ execute_pay_transaction (struct PayContext *pc)
       }
       GNUNET_break (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              TALER_EC_GENERIC_DB_STORE_FAILED,
                              "mark contract paid");
       return;
@@ -2153,7 +2131,6 @@ execute_pay_transaction (struct PayContext *pc)
       }
       GNUNET_break (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              TALER_EC_GENERIC_DB_STORE_FAILED,
                              "failed to trigger webhooks");
       return;
@@ -2175,7 +2152,6 @@ execute_pay_transaction (struct PayContext *pc)
       }
       GNUNET_break (0);
       resume_pay_with_error (pc,
-                             MHD_HTTP_INTERNAL_SERVER_ERROR,
                              TALER_EC_GENERIC_DB_COMMIT_FAILED,
                              NULL);
       return;
@@ -2740,7 +2716,6 @@ handle_pay_timeout (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Resuming pay with error after timeout\n");
   resume_pay_with_error (pc,
-                         MHD_HTTP_GATEWAY_TIMEOUT,
                          TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
                          NULL);
 }
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-refund.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-refund.c
index a20f6b12..ded6ff9d 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-refund.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-refund.c
@@ -51,7 +51,7 @@ struct CoinRefund
   /**
    * Request to connect to the target exchange.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * Handle for the refund operation with the exchange.
@@ -456,7 +456,7 @@ exchange_found_cb (void *cls,
     return;
   }
   cr->rh = TALER_EXCHANGE_refund (
-    merchant_curl_ctx,
+    TMH_curl_ctx,
     cr->exchange_url,
     keys,
     &cr->refund_amount,
diff --git a/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c 
b/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c
index a87ea710..e8f9ba45 100644
--- a/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c
+++ b/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c
@@ -73,7 +73,7 @@ struct PlanchetOperation
   /**
    * Find operation (while active), later NULL.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * Withdraw handle (NULL while @e fo is active).
@@ -145,7 +145,7 @@ struct PickupContext
   /**
    * Find operation (while active), later NULL.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * Which reserve are we draining?
@@ -409,7 +409,7 @@ do_withdraw (void *cls,
     TALER_MHD_daemon_trigger ();   /* we resumed, kick MHD */
     return;
   }
-  po->w2h = TALER_EXCHANGE_withdraw2 (merchant_curl_ctx,
+  po->w2h = TALER_EXCHANGE_withdraw2 (TMH_curl_ctx,
                                       pc->exchange_url,
                                       keys,
                                       &po->pd,
diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c 
b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
index 7c2f7a2c..f5b9d36e 100644
--- a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
+++ b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
@@ -73,7 +73,7 @@ struct ExchangeKycRequest
   /**
    * Find operation where we connect to the respective exchange.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * KYC request this exchange request is made for.
@@ -676,7 +676,7 @@ kyc_with_exchange (void *cls,
   TALER_payto_hash (ekr->payto_uri,
                     &h_payto);
   ekr->kyc = TALER_EXCHANGE_kyc_check (
-    merchant_curl_ctx,
+    TMH_curl_ctx,
     ekr->exchange_url,
     keys,
     ekr->exchange_kyc_serial,
diff --git a/src/backend/taler-merchant-httpd_private-get-orders-ID.c 
b/src/backend/taler-merchant-httpd_private-get-orders-ID.c
index 788c7bf1..6d2140d0 100644
--- a/src/backend/taler-merchant-httpd_private-get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-orders-ID.c
@@ -73,7 +73,7 @@ struct TransferQuery
   /**
    * Handle for ongoing exchange operation.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * Overall request this TQ belongs with.
@@ -614,7 +614,7 @@ exchange_found_cb (void *cls,
     return;
   }
   tq->dgh = TALER_EXCHANGE_deposits_get (
-    merchant_curl_ctx,
+    TMH_curl_ctx,
     tq->exchange_url,
     keys,
     &gorc->hc->instance->merchant_priv,
diff --git a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c 
b/src/backend/taler-merchant-httpd_private-get-reserves-ID.c
index 27ea2be1..4eaa6538 100644
--- a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-reserves-ID.c
@@ -70,18 +70,19 @@ struct GetReserveContext
  * @param tips information about the tips created by this reserve
  */
 static void
-handle_reserve_details (void *cls,
-                        struct GNUNET_TIME_Timestamp creation_time,
-                        struct GNUNET_TIME_Timestamp expiration_time,
-                        const struct TALER_Amount *merchant_initial_amount,
-                        const struct TALER_Amount *exchange_initial_amount,
-                        const struct TALER_Amount *picked_up_amount,
-                        const struct TALER_Amount *committed_amount,
-                        bool active,
-                        const struct TALER_MasterPublicKeyP *master_pub,
-                        const char *exchange_url,
-                        unsigned int tips_length,
-                        const struct TALER_MERCHANTDB_TipDetails *tips)
+handle_reserve_details (
+  void *cls,
+  struct GNUNET_TIME_Timestamp creation_time,
+  struct GNUNET_TIME_Timestamp expiration_time,
+  const struct TALER_Amount *merchant_initial_amount,
+  const struct TALER_Amount *exchange_initial_amount,
+  const struct TALER_Amount *picked_up_amount,
+  const struct TALER_Amount *committed_amount,
+  bool active,
+  const struct TALER_MasterPublicKeyP *master_pub,
+  const char *exchange_url,
+  unsigned int tips_length,
+  const struct TALER_MERCHANTDB_TipDetails *tips)
 {
   struct GetReserveContext *ctx = cls;
   json_t *tips_json;
diff --git a/src/backend/taler-merchant-httpd_private-post-reserves.c 
b/src/backend/taler-merchant-httpd_private-post-reserves.c
index 00e4a4ee..5ca8e768 100644
--- a/src/backend/taler-merchant-httpd_private-post-reserves.c
+++ b/src/backend/taler-merchant-httpd_private-post-reserves.c
@@ -86,7 +86,7 @@ struct PostReserveContext
   /**
    * Handle for contacting the exchange for /keys.
    */
-  struct TMH_EXCHANGES_Find2Operation *fo;
+  struct TMH_EXCHANGES_KeysOperation *fo;
 
   /**
    * Handle for contacting the exchange for /wire.
@@ -223,7 +223,7 @@ resume_request (struct PostReserveContext *rc)
  */
 static void
 wire_cb (void *cls,
-         struct TMH_Exchange *wire)
+         const struct TMH_ExchangeWireDetails *wire)
 {
   struct PostReserveContext *rc = cls;
 
diff --git a/src/backend/taler-merchant-httpd_reserves.c 
b/src/backend/taler-merchant-httpd_reserves.c
index 83b70010..31dec87f 100644
--- a/src/backend/taler-merchant-httpd_reserves.c
+++ b/src/backend/taler-merchant-httpd_reserves.c
@@ -226,7 +226,7 @@ try_now (void *cls)
   struct Reserve *r = cls;
 
   r->tt = NULL;
-  r->gh = TALER_EXCHANGE_reserves_get (merchant_curl_ctx,
+  r->gh = TALER_EXCHANGE_reserves_get (TMH_curl_ctx,
                                        r->exchange_url,
                                        &r->reserve_pub,
                                        LONGPOLL_DELAY,

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