gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant] branch master updated: towards implementin


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch master updated: towards implementing #4935: make sure all of the fee data is available for the /pay handler (but not yet checked)
Date: Sun, 05 Mar 2017 20:11:53 +0100

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 09b01a1  towards implementing #4935: make sure all of the fee data is 
available for the /pay handler (but not yet checked)
09b01a1 is described below

commit 09b01a179daf0de4ad2a14d22f584c105d7de22c
Author: Christian Grothoff <address@hidden>
AuthorDate: Sun Mar 5 20:11:51 2017 +0100

    towards implementing #4935: make sure all of the fee data is available for 
the /pay handler (but not yet checked)
---
 src/backend/taler-merchant-httpd.c                 |  10 +-
 src/backend/taler-merchant-httpd_exchanges.c       | 337 ++++++++++++++++++++-
 src/backend/taler-merchant-httpd_exchanges.h       |   4 +
 src/backend/taler-merchant-httpd_pay.c             | 121 +++++---
 .../taler-merchant-httpd_track-transaction.c       |   3 +
 src/backend/taler-merchant-httpd_track-transfer.c  |   3 +
 6 files changed, 414 insertions(+), 64 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index f13b891..cb08301 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -632,7 +632,7 @@ get_instance (struct json_t *json)
  * @param config configuration handle
  * @param allowed which wire format is allowed/expected?
  * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors
- * (for example, if no "defaul" instance is defined)
+ * (for example, if no "default" instance is defined)
  */
 static unsigned int
 iterate_instances (const struct GNUNET_CONFIGURATION_Handle *config,
@@ -716,7 +716,6 @@ run (void *cls,
   char *wireformat;
   int fh;
 
-  wireformat = NULL;
   result = GNUNET_SYSERR;
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                  NULL);
@@ -763,6 +762,7 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
+  wireformat = NULL;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (config,
                                              "merchant",
@@ -775,10 +775,10 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
-  iterate_instances (config, wireformat);
-
+  iterate_instances (config,
+                     wireformat);
   GNUNET_free (wireformat);
+
   if (NULL ==
       (db = TALER_MERCHANTDB_plugin_load (config)))
   {
diff --git a/src/backend/taler-merchant-httpd_exchanges.c 
b/src/backend/taler-merchant-httpd_exchanges.c
index 176c8ad..c7e88c7 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
+  (C) 2014-2017 INRIA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -84,6 +84,11 @@ struct TMH_EXCHANGES_FindOperation
   struct Exchange *my_exchange;
 
   /**
+   * Wire method we care about for fees.
+   */
+  char *wire_method;
+
+  /**
    * Task scheduled to asynchronously return the result to
    * the find continuation.
    */
@@ -93,6 +98,35 @@ struct TMH_EXCHANGES_FindOperation
 
 
 /**
+ * Information about wire transfer fees of an exchange, by wire method.
+ */
+struct FeesByWireMethod
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct FeesByWireMethod *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct FeesByWireMethod *prev;
+
+  /**
+   * Wire method these fees are for.
+   */
+  char *wire_method;
+
+  /**
+   * Applicable fees, NULL if unknown/error.
+   */
+  struct TALER_EXCHANGE_WireAggregateFees *af;
+
+};
+
+
+/**
  * Exchange
  */
 struct Exchange
@@ -129,6 +163,26 @@ struct Exchange
   struct TALER_EXCHANGE_Handle *conn;
 
   /**
+   * Active /wire request to the exchange, or NULL.
+   */
+  struct TALER_EXCHANGE_WireHandle *wire_request;
+
+  /**
+   * Task to re-run /wire after some delay.
+   */
+  struct GNUNET_SCHEDULER_Task *wire_task;
+
+  /**
+   * Head of wire fees from /wire request.
+   */
+  struct FeesByWireMethod *wire_fees_head;
+
+  /**
+   * Tail of wire fees from /wire request.
+   */
+  struct FeesByWireMethod *wire_fees_tail;
+
+  /**
    * Master public key, guaranteed to be set ONLY for
    * trusted exchanges.
    */
@@ -239,6 +293,237 @@ retry_exchange (void *cls)
 
 
 /**
+ * Function called with information about the wire fees
+ * for each wire method.  Stores the wire fees with the
+ * exchange for laster use.
+ *
+ * @param cls closure
+ * @param wire_method name of the wire method (i.e. "sepa")
+ * @param fees fee structure for this method
+ */
+static void
+process_wire_fees (void *cls,
+                   const char *wire_method,
+                   const struct TALER_EXCHANGE_WireAggregateFees *fees)
+{
+  struct Exchange *exchange = cls;
+  struct FeesByWireMethod *f;
+  struct TALER_EXCHANGE_WireAggregateFees *endp;
+  struct TALER_EXCHANGE_WireAggregateFees *af;
+
+  for (f = exchange->wire_fees_head; NULL != f; f = f->next)
+    if (0 == strcasecmp (wire_method,
+                         f->wire_method))
+      break;
+  if (NULL == f)
+  {
+    f = GNUNET_new (struct FeesByWireMethod);
+    f->wire_method = GNUNET_strdup (wire_method);
+    GNUNET_CONTAINER_DLL_insert (exchange->wire_fees_head,
+                                 exchange->wire_fees_tail,
+                                 f);
+  }
+  endp = f->af;
+  while ( (NULL != endp) &&
+          (NULL != endp->next) )
+    endp = endp->next;
+  while ( (NULL != endp) &&
+          (fees->start_date.abs_value_us < endp->end_date.abs_value_us) )
+    fees = fees->next;
+  if ( (NULL != endp) &&
+       (fees->start_date.abs_value_us != endp->end_date.abs_value_us) )
+  {
+    /* Hole in the fee structure, not allowed! */
+    GNUNET_break_op (0);
+    return;
+  }
+  while (NULL != fees)
+  {
+    af = GNUNET_new (struct TALER_EXCHANGE_WireAggregateFees);
+    *af = *fees;
+    af->next = NULL;
+    if (NULL == endp)
+      f->af = af;
+    else
+      endp->next = af;
+    endp = af;
+    // FIXME: also preserve `fees` in backend DB (under wire method + exchange 
master pub!)
+    fees = fees->next;
+  }
+}
+
+
+/**
+ * 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 #GNUNET_YES if we need /wire data from @a exchange
+ */
+static int
+process_find_operations (struct Exchange *exchange)
+{
+  struct TMH_EXCHANGES_FindOperation *fo;
+  struct TMH_EXCHANGES_FindOperation *fn;
+  struct GNUNET_TIME_Absolute now;
+  int need_wire;
+
+  now = GNUNET_TIME_absolute_get ();
+  need_wire = GNUNET_NO;
+  for (fo = exchange->fo_head; NULL != fo; fo = fn)
+  {
+    const struct TALER_Amount *wire_fee;
+
+    fn = fo->next;
+    if (NULL != fo->wire_method)
+    {
+      struct FeesByWireMethod *fbw;
+      struct TALER_EXCHANGE_WireAggregateFees *af;
+
+      /* Find fee structure for our wire method */
+      for (fbw = exchange->wire_fees_head; NULL != fbw; fbw = fbw->next)
+        if (0 == strcasecmp (fbw->wire_method,
+                             fo->wire_method) )
+          break;
+      if (NULL == fbw)
+      {
+        need_wire = GNUNET_YES;
+        continue;
+      }
+      /* Advance through list up to current time */
+      while ( (NULL != (af = fbw->af)) &&
+              (now.abs_value_us >= af->end_date.abs_value_us) )
+      {
+        fbw->af = af->next;
+        GNUNET_free (af);
+      }
+      if (NULL == af)
+      {
+        need_wire = GNUNET_YES;
+        continue;
+      }
+      if (af->start_date.abs_value_us > now.abs_value_us)
+      {
+        /* Disagreement on the current time */
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Exchange's earliest fee is %s adhead of our time. Clock 
skew issue?\n",
+                    GNUNET_STRINGS_relative_time_to_string 
(GNUNET_TIME_absolute_get_remaining (af->start_date),
+                                                            GNUNET_YES));
+        continue;
+      }
+      /* found fee, great! */
+      wire_fee = &af->wire_fee;
+    }
+    else
+    {
+      /* no wire transfer method given, so we yield no fee */
+      wire_fee = NULL;
+    }
+    GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
+                                 exchange->fo_tail,
+                                 fo);
+    fo->fc (fo->fc_cls,
+            exchange->conn,
+            wire_fee,
+            exchange->trusted);
+    GNUNET_free_non_null (fo->wire_method);
+    GNUNET_free (fo);
+  }
+  return need_wire;
+}
+
+
+/**
+ * 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.
+ *
+ * @param cls a `struct Exchange` to check
+ */
+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.
+ *
+ * @param cls closure, a `struct Exchange`
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
request;
+ *                    0 if the exchange's reply is bogus (fails to follow the 
protocol)
+ * @param ec taler-specific error code, #TALER_EC_NONE on success
+ * @param obj the received JSON reply, if successful this should be the wire
+ *            format details as provided by /wire, or NULL if the
+ *            reply was not in JSON format.
+ */
+static void
+handle_wire_data (void *cls,
+                  unsigned int http_status,
+                  enum TALER_ErrorCode ec,
+                  const json_t *obj)
+{
+  struct Exchange *exchange = cls;
+
+  exchange->wire_request = NULL;
+  if (MHD_HTTP_OK != http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to obtain /wire details from `%s': %d\n",
+                exchange->uri,
+                ec);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_EXCHANGE_wire_get_fees (&exchange->master_pub,
+                                    obj,
+                                    &process_wire_fees,
+                                    exchange))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  if (GNUNET_YES ==
+      process_find_operations (exchange))
+  {
+    /* need to run /wire again, with some delay */
+    GNUNET_assert (NULL == exchange->wire_task);
+    exchange->wire_task = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_UNIT_MINUTES,
+                                                        &wire_task_cb,
+                                                        exchange);
+  }
+}
+
+
+/**
+ * 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.
+ *
+ * @param cls a `struct Exchange` to check
+ */
+static void
+wire_task_cb (void *cls)
+{
+  struct Exchange *exchange = cls;
+
+  exchange->wire_task = NULL;
+  if (GNUNET_YES !=
+      process_find_operations (exchange))
+    return; /* no more need */
+  GNUNET_assert (NULL == exchange->wire_request);
+  exchange->wire_request = TALER_EXCHANGE_wire (exchange->conn,
+                                                &handle_wire_data,
+                                                exchange);
+}
+
+
+/**
  * Function called with information about who is auditing
  * a particular exchange and what key the exchange is using.
  *
@@ -257,13 +542,22 @@ keys_mgmt_cb (void *cls,
               const struct TALER_EXCHANGE_Keys *keys)
 {
   struct Exchange *exchange = cls;
-  struct TMH_EXCHANGES_FindOperation *fo;
   struct GNUNET_TIME_Absolute expire;
   struct GNUNET_TIME_Relative delay;
 
   if (NULL == keys)
   {
     exchange->pending = GNUNET_YES;
+    if (NULL != exchange->wire_request)
+    {
+      TALER_EXCHANGE_wire_cancel (exchange->wire_request);
+      exchange->wire_request = NULL;
+    }
+    if (NULL != exchange->wire_task)
+    {
+      GNUNET_SCHEDULER_cancel (exchange->wire_task);
+      exchange->wire_task = NULL;
+    }
     exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Failed to fetch /keys from `%s', retrying in %s\n",
@@ -286,15 +580,14 @@ keys_mgmt_cb (void *cls,
                                     &retry_exchange,
                                     exchange);
   exchange->pending = GNUNET_NO;
-  while (NULL != (fo = exchange->fo_head))
+  if (GNUNET_YES ==
+      process_find_operations (exchange))
   {
-    GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
-                                 exchange->fo_tail,
-                                 fo);
-    fo->fc (fo->fc_cls,
-            exchange->conn,
-            exchange->trusted);
-    GNUNET_free (fo);
+    GNUNET_assert (NULL == exchange->wire_request);
+    GNUNET_assert (NULL == exchange->wire_task);
+    exchange->wire_request = TALER_EXCHANGE_wire (exchange->conn,
+                                                  &handle_wire_data,
+                                                  exchange);
   }
 }
 
@@ -319,6 +612,7 @@ return_result (void *cls)
               exchange->uri, exchange->trusted);
   fo->fc (fo->fc_cls,
           (GNUNET_SYSERR == exchange->pending) ? NULL : exchange->conn,
+          NULL, /* FIXME: pass fees! */
           exchange->trusted);
   GNUNET_free (fo);
 }
@@ -330,12 +624,14 @@ return_result (void *cls)
  * NULL for the exchange.
  *
  * @param chosen_exchange URI of the exchange we would like to talk to
+ * @param wire_method the wire method we will use with @a chosen_exchange, 
NULL for none
  * @param fc function to call with the handles for the exchange
  * @param fc_cls closure for @a fc
  * @return NULL on error
  */
 struct TMH_EXCHANGES_FindOperation *
 TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
+                             const char *wire_method,
                             TMH_EXCHANGES_FindContinuation fc,
                             void *fc_cls)
 {
@@ -387,6 +683,8 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
   fo->fc = fc;
   fo->fc_cls = fc_cls;
   fo->my_exchange = exchange;
+  if (NULL != wire_method)
+    fo->wire_method = GNUNET_strdup (wire_method);
   GNUNET_CONTAINER_DLL_insert (exchange->fo_head,
                                exchange->fo_tail,
                                fo);
@@ -429,6 +727,7 @@ TMH_EXCHANGES_find_exchange_cancel (struct 
TMH_EXCHANGES_FindOperation *fo)
   GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
                                exchange->fo_tail,
                                fo);
+  GNUNET_free_non_null (fo->wire_method);
   GNUNET_free (fo);
 }
 
@@ -443,7 +742,7 @@ TMH_EXCHANGES_find_exchange_cancel (struct 
TMH_EXCHANGES_FindOperation *fo)
  */
 static void
 accept_exchanges (void *cls,
-                 const char *section)
+                  const char *section)
 {
   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   char *uri;
@@ -561,10 +860,26 @@ TMH_EXCHANGES_done ()
     GNUNET_CONTAINER_DLL_remove (exchange_head,
                                  exchange_tail,
                                  exchange);
+    if (NULL != exchange->wire_request)
+    {
+      TALER_EXCHANGE_wire_cancel (exchange->wire_request);
+      exchange->wire_request = NULL;
+    }
+    if (NULL != exchange->wire_task)
+    {
+      GNUNET_SCHEDULER_cancel (exchange->wire_task);
+      exchange->wire_task = NULL;
+    }
     if (NULL != exchange->conn)
+    {
       TALER_EXCHANGE_disconnect (exchange->conn);
+      exchange->conn = NULL;
+    }
     if (NULL != exchange->retry_task)
+    {
       GNUNET_SCHEDULER_cancel (exchange->retry_task);
+      exchange->retry_task = NULL;
+    }
     GNUNET_free (exchange->uri);
     GNUNET_free (exchange);
   }
diff --git a/src/backend/taler-merchant-httpd_exchanges.h 
b/src/backend/taler-merchant-httpd_exchanges.h
index 0e705a4..6b763ae 100644
--- a/src/backend/taler-merchant-httpd_exchanges.h
+++ b/src/backend/taler-merchant-httpd_exchanges.h
@@ -60,11 +60,13 @@ TMH_EXCHANGES_done (void);
  *
  * @param cls closure
  * @param eh handle to the exchange context
+ * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if 
not available
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 typedef void
 (*TMH_EXCHANGES_FindContinuation)(void *cls,
                                   struct TALER_EXCHANGE_Handle *eh,
+                                  const struct TALER_Amount *wire_fee,
                                   int exchange_trusted);
 
 
@@ -80,11 +82,13 @@ struct TMH_EXCHANGES_FindOperation;
  * NULL for the exchange.
  *
  * @param chosen_exchange URI of the exchange we would like to talk to
+ * @param wire_method the wire method we will use with @a chosen_exchange, 
NULL for none
  * @param fc function to call with the handles for the exchange
  * @param fc_cls closure for @a fc
  */
 struct TMH_EXCHANGES_FindOperation *
 TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
+                             const char *wire_method,
                              TMH_EXCHANGES_FindContinuation fc,
                              void *fc_cls);
 
diff --git a/src/backend/taler-merchant-httpd_pay.c 
b/src/backend/taler-merchant-httpd_pay.c
index 91860ca..090ae14 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+  (C) 2014, 2015, 2016, 2017 GNUnet e.V. and INRIA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -165,6 +165,34 @@ struct PayContext
   struct TALER_Amount max_fee;
 
   /**
+   * Maximum wire fee the merchant is willing to pay, from @e root.
+   * Note that IF the total fee of the exchange is higher, that is
+   * acceptable to the merchant if the customer is willing to
+   * pay the amorized difference.  Wire fees are charged over an
+   * aggregate of several translations, hence unlike the deposit
+   * fees, they are amortized over several customer's transactions.
+   * The contract specifies under @e wire_fee_amortization how many
+   * customer's transactions he expects the wire fees to be amortized
+   * over on average.  Thus, if the wire fees are larger than
+   * @e max_wire_fee, each customer is expected to contribute
+   * $\frac{actual-wire-fee - max_wire_fee}{wire_fee_amortization}$.
+   * The customer's contribution may be further reduced by the
+   * difference between @e max_fee and the sum of the deposit fees.
+   *
+   * Default is that the merchant is unwilling to pay any wire fees.
+   */
+  struct TALER_Amount max_wire_fee;
+
+  /**
+   * Number of transactions that the wire fees are expected to be
+   * amortized over.  Never zero, defaults (conservateively) to 1.
+   * May be higher if merchants expect many small transactions to
+   * be aggregated and thus wire fees to be reasonably amortized
+   * due to aggregation.
+   */
+  uint32_t wire_fee_amortization;
+
+  /**
    * Amount from @e root.  This is the amount the merchant expects
    * to make, minus @e max_fee.
    */
@@ -526,11 +554,13 @@ pay_context_cleanup (struct TM_HandlerContext *hc)
  *
  * @param cls the `struct PayContext`
  * @param mh NULL if exchange was not found to be acceptable
+ * @param wire_fee current applicable fee for dealing with @a mh, NULL if not 
available
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 static void
 process_pay_with_exchange (void *cls,
                            struct TALER_EXCHANGE_Handle *mh,
+                           const struct TALER_Amount *wire_fee,
                            int exchange_trusted)
 {
   struct PayContext *pc = cls;
@@ -552,7 +582,6 @@ process_pay_with_exchange (void *cls,
     return;
   }
   pc->mh = mh;
-
   keys = TALER_EXCHANGE_get_keys (mh);
   if (NULL == keys)
   {
@@ -874,40 +903,13 @@ check_transaction_exists (void *cls,
   }
 }
 
+
+// FIXME: declare in proper header!
 extern struct MerchantInstance *
 get_instance (struct json_t *json);
 
 
 /**
- * Just a stub used to double-check if a transaction
- * has been correctly inserted into db.
- *
- * @param cls closure
- * @param transaction_id of the contract
- * @param merchant's public key
- * @param exchange_uri URI of the exchange
- * @param h_contract hash of the contract
- * @param h_wire hash of our wire details
- * @param timestamp time of the confirmation
- * @param refund refund deadline
- * @param total_amount total amount we receive for the contract after fees
- */
-static void
-transaction_double_check (void *cls,
-                         const struct TALER_MerchantPublicKeyP *merchant_pub,
-                          const char *exchange_uri,
-                          const struct GNUNET_HashCode *h_proposal_data,
-                          const struct GNUNET_HashCode *h_wire,
-                          struct GNUNET_TIME_Absolute timestamp,
-                          struct GNUNET_TIME_Absolute refund,
-                          const struct TALER_Amount *total_amount)
-{
-  return;
-}
-
-
-
-/**
  * Try to parse the pay request into the given pay context.
  *
  * Schedules an error response in the connection on failure.
@@ -968,7 +970,7 @@ parse_pay (struct MHD_Connection *connection,
     GNUNET_JSON_parse_free (spec);
     if (MHD_YES !=
         TMH_RESPONSE_reply_internal_error (connection,
-                                           TALER_EC_NONE,
+                                           
TALER_EC_PAY_FAILED_COMPUTE_PROPOSAL_HASH,
                                            "Can not hash proposal"))
     {
       GNUNET_break (0);
@@ -984,10 +986,9 @@ parse_pay (struct MHD_Connection *connection,
     GNUNET_JSON_parse_free (spec);
     /* invalid contract */
     GNUNET_break (0);
-    // FIXME: define proper EC for this!
     if (MHD_YES !=
         TMH_RESPONSE_reply_internal_error (connection,
-                                           TALER_EC_NONE,
+                                           TALER_EC_PAY_MERCHANT_FIELD_MISSING,
                                            "No merchant field in contract"))
     {
       GNUNET_break (0);
@@ -1015,12 +1016,10 @@ parse_pay (struct MHD_Connection *connection,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "/pay: picked instance %s with key %s\n",
               pc->mi->id,
-              GNUNET_STRINGS_data_to_string_alloc (&pc->mi->pubkey, sizeof 
(pc->mi->pubkey)));
+              GNUNET_STRINGS_data_to_string_alloc (&pc->mi->pubkey,
+                                                   sizeof (pc->mi->pubkey)));
 
   pc->chosen_exchange = GNUNET_strdup (chosen_exchange);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Parsed JSON for /pay.\n");
-
   {
     struct GNUNET_JSON_Specification espec[] = {
       GNUNET_JSON_spec_absolute_time ("refund_deadline",
@@ -1060,9 +1059,42 @@ parse_pay (struct MHD_Connection *connection,
     }
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "parsed timestamps\n");
+  /* parse optional details */
+  {
+    struct GNUNET_JSON_Specification espec[] = {
+      TALER_JSON_spec_amount ("max_wire_fee",
+                              &pc->max_wire_fee),
+      GNUNET_JSON_spec_end()
+    };
+
+    res = TMH_PARSE_json_data (connection,
+                               pc->proposal_data,
+                               espec);
+    if (GNUNET_YES != res)
+    {
+      /* default is we cover no fee */
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_amount_get_zero (pc->max_fee.currency,
+                                            &pc->max_wire_fee));
+    }
+  }
+  {
+    struct GNUNET_JSON_Specification espec[] = {
+      GNUNET_JSON_spec_uint32 ("wire_fee_amortization",
+                              &pc->wire_fee_amortization),
+      GNUNET_JSON_spec_end()
+    };
 
+    res = TMH_PARSE_json_data (connection,
+                               pc->proposal_data,
+                               espec);
+    if ( (GNUNET_YES != res) ||
+         (0 == pc->wire_fee_amortization) )
+    {
+      /* default is no amortization */
+      pc->wire_fee_amortization = 1;
+    }
+  }
 
   pc->coins_cnt = json_array_size (coins);
   if (0 == pc->coins_cnt)
@@ -1140,8 +1172,6 @@ handler_pay_json (struct MHD_Connection *connection,
   if (GNUNET_OK != ret)
     return ret;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "parsed '/pay' body\n");
-
   /* Check if this payment attempt has already succeeded */
   if (GNUNET_SYSERR ==
       db->find_payments (db->cls,
@@ -1232,18 +1262,13 @@ handler_pay_json (struct MHD_Connection *connection,
                                                
TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR,
                                                "Merchant database error");
     }
-  if (GNUNET_OK != db->find_transaction (db->cls,
-                                         &pc->h_proposal_data,
-                                        &pc->mi->pubkey,
-                                         &transaction_double_check,
-                                         NULL))
-    GNUNET_break (0);
   }
 
   MHD_suspend_connection (connection);
 
   /* Find the responsible exchange, this may take a while... */
   pc->fo = TMH_EXCHANGES_find_exchange (pc->chosen_exchange,
+                                        NULL, /* FIXME: wire method! */
                                         &process_pay_with_exchange,
                                         pc);
 
diff --git a/src/backend/taler-merchant-httpd_track-transaction.c 
b/src/backend/taler-merchant-httpd_track-transaction.c
index b0dffaf..7eeadd0 100644
--- a/src/backend/taler-merchant-httpd_track-transaction.c
+++ b/src/backend/taler-merchant-httpd_track-transaction.c
@@ -679,11 +679,13 @@ trace_coins (struct TrackTransactionContext *tctx)
  *
  * @param cls the `struct TrackTransactionContext`
  * @param eh NULL if exchange was not found to be acceptable
+ * @param wire_fee NULL (we did not specify a wire method)
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 static void
 process_track_transaction_with_exchange (void *cls,
                                          struct TALER_EXCHANGE_Handle *eh,
+                                         const struct TALER_Amount *wire_fee,
                                          int exchange_trusted)
 {
   struct TrackTransactionContext *tctx = cls;
@@ -987,6 +989,7 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh,
               "Suspending /track/transaction handling while working with the 
exchange\n");
   MHD_suspend_connection (connection);
   tctx->fo = TMH_EXCHANGES_find_exchange (tctx->exchange_uri,
+                                          NULL,
                                           
&process_track_transaction_with_exchange,
                                           tctx);
 
diff --git a/src/backend/taler-merchant-httpd_track-transfer.c 
b/src/backend/taler-merchant-httpd_track-transfer.c
index 029eec5..3635c1d 100644
--- a/src/backend/taler-merchant-httpd_track-transfer.c
+++ b/src/backend/taler-merchant-httpd_track-transfer.c
@@ -415,11 +415,13 @@ wire_transfer_cb (void *cls,
  *
  * @param cls the `struct TrackTransferContext`
  * @param eh NULL if exchange was not found to be acceptable
+ * @param wire_fee NULL (we did not specify a wire method)
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 static void
 process_track_transfer_with_exchange (void *cls,
                                       struct TALER_EXCHANGE_Handle *eh,
+                                      const struct TALER_Amount *wire_fee,
                                       int exchange_trusted)
 {
   struct TrackTransferContext *rctx = cls;
@@ -623,6 +625,7 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh,
               "Suspending /track/transfer handling while working with the 
exchange\n");
   MHD_suspend_connection (connection);
   rctx->fo = TMH_EXCHANGES_find_exchange (uri,
+                                          NULL,
                                           
&process_track_transfer_with_exchange,
                                           rctx);
   rctx->timeout_task

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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