gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] 92/277: fix backenddb


From: gnunet
Subject: [taler-merchant] 92/277: fix backenddb
Date: Sun, 05 Jul 2020 20:50:05 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

commit 68fcf5f245b9beccf157f95f06984508df95730a
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Tue May 5 21:24:37 2020 +0200

    fix backenddb
---
 .../taler-merchant-httpd_private-post-transfers.c  | 497 +++++++++++----------
 src/backenddb/merchant-0001.sql                    |  11 +-
 src/backenddb/plugin_merchantdb_postgres.c         | 119 +++--
 src/include/taler_merchantdb_plugin.h              |  19 -
 4 files changed, 318 insertions(+), 328 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.c 
b/src/backend/taler-merchant-httpd_private-post-transfers.c
index 7f55c91..6304761 100644
--- a/src/backend/taler-merchant-httpd_private-post-transfers.c
+++ b/src/backend/taler-merchant-httpd_private-post-transfers.c
@@ -14,8 +14,8 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_track-transfer.c
- * @brief implement API for tracking transfers and wire transfers
+ * @file backend/taler-merchant-httpd_private-post-transfers.c
+ * @brief implement API for registering wire transfers
  * @author Marcello Stanisci
  * @author Christian Grothoff
  */
@@ -23,11 +23,9 @@
 #include <jansson.h>
 #include <taler/taler_signatures.h>
 #include <taler/taler_json_lib.h>
-#include "taler-merchant-httpd.h"
-#include "taler-merchant-httpd_mhd.h"
 #include "taler-merchant-httpd_auditors.h"
 #include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_track-transfer.h"
+#include "taler-merchant-httpd_private-post-transfers.h"
 
 
 /**
@@ -42,20 +40,45 @@
 #define MAX_RETRIES 3
 
 /**
- * Context used for handing /track/transfer requests.
+ * Context used for handing POST /private/transfers requests.
  */
 struct TrackTransferContext
 {
 
   /**
-   * This MUST be first!
+   * Kept in a DLL.
    */
-  struct TM_HandlerContext hc;
+  struct TrackTransferContext *next;
 
   /**
-   * Handle to the exchange.
+   * Kept in a DLL.
    */
-  struct TALER_EXCHANGE_Handle *eh;
+  struct TrackTransferContext *prev;
+
+  /**
+   * Argument for the /wire/transfers request.
+   */
+  struct TALER_WireTransferIdentifierRawP wtid;
+
+  /**
+   * Amount of the wire transfer.
+   */
+  struct TALER_Amount amount;
+
+  /**
+   * URL of the exchange.
+   */
+  char *exchange_url;
+
+  /**
+   * payto:// URI used for the transfer.
+   */
+  char *payto_uri;
+
+  /**
+   * Master public key of the exchange at @e exchange_url.
+   */
+  struct TALER_MasterPublicKeyP master_pub;
 
   /**
    * Handle for the /wire/transfers request.
@@ -89,15 +112,6 @@ struct TrackTransferContext
    */
   struct GNUNET_SCHEDULER_Task *timeout_task;
 
-  /**
-   * URL of the exchange.
-   */
-  char *url;
-
-  /**
-   * Wire method used for the transfer.
-   */
-  char *wire_method;
 
   /**
    * Pointer to the detail that we are currently
@@ -105,21 +119,6 @@ struct TrackTransferContext
    */
   const struct TALER_TrackTransferDetails *current_detail;
 
-  /**
-   * Argument for the /wire/transfers request.
-   */
-  struct TALER_WireTransferIdentifierRawP wtid;
-
-  /**
-   * Full original response we are currently processing.
-   */
-  const json_t *original_response;
-
-  /**
-   * Modified response to return to the frontend.
-   */
-  json_t *deposits_response;
-
   /**
    * Which transaction detail are we currently looking at?
    */
@@ -139,13 +138,32 @@ struct TrackTransferContext
 };
 
 
+/**
+ * Head of list of suspended requests.
+ */
+static struct TrackTransferContext *pth_head;
+
+/**
+ * Tail of list of suspended requests.
+ */
+static struct TrackTransferContext *pth_tail;
+
+
 /**
  * Represents an entry in the table used to sum up
- * individual deposits for each h_contract_terms.
+ * individual deposits for each h_contract_terms/order_id
+ * (as the exchange gives us per coin, and we return
+ * per order).  FIXME: decide whether we do this HERE
+ * or in the DB! (SUM()...)
  */
 struct Entry
 {
 
+  /**
+   * Order of the entry. FIXME: to be used!?
+   */
+  char *order_id;
+
   /**
    * Sum accumulator for deposited value.
    */
@@ -404,13 +422,16 @@ resume_track_transfer_with_response (struct 
TrackTransferContext *rctx,
   rctx->response_code = response_code;
   rctx->response = response;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Resuming /track/transfer handling as exchange interaction is 
done (%u)\n",
+              "Resuming POST /transfers handling as exchange interaction is 
done (%u)\n",
               response_code);
   if (NULL != rctx->timeout_task)
   {
     GNUNET_SCHEDULER_cancel (rctx->timeout_task);
     rctx->timeout_task = NULL;
   }
+  GNUNET_CONTAINER_DLL_remove (pth_head,
+                               pth_tail,
+                               rctx);
   MHD_resume_connection (rctx->connection);
   TMH_trigger_daemon (); /* we resumed, kick MHD */
 }
@@ -419,12 +440,12 @@ resume_track_transfer_with_response (struct 
TrackTransferContext *rctx,
 /**
  * Custom cleanup routine for a `struct TrackTransferContext`.
  *
- * @param hc the `struct TrackTransferContext` to clean up.
+ * @param cls the `struct TrackTransferContext` to clean up.
  */
 static void
-track_transfer_cleanup (struct TM_HandlerContext *hc)
+track_transfer_cleanup (void *cls)
 {
-  struct TrackTransferContext *rctx = (struct TrackTransferContext *) hc;
+  struct TrackTransferContext *rctx = cls;
 
   free_transfer_track_context (rctx);
 }
@@ -511,30 +532,19 @@ check_wire_fee (struct TrackTransferContext *rctx,
                 struct GNUNET_TIME_Absolute execution_time,
                 const struct TALER_Amount *wire_fee)
 {
-  const struct TALER_MasterPublicKeyP *master_pub;
-  struct GNUNET_HashCode h_wire_method;
   struct TALER_Amount expected_fee;
   struct TALER_Amount closing_fee;
   struct TALER_MasterSignatureP master_sig;
   struct GNUNET_TIME_Absolute start_date;
   struct GNUNET_TIME_Absolute end_date;
   enum GNUNET_DB_QueryStatus qs;
-  const struct TALER_EXCHANGE_Keys *keys;
+  char *wire_method;
 
-  keys = TALER_EXCHANGE_get_keys (rctx->eh);
-  if (NULL == keys)
-  {
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-  master_pub = &keys->master_pub;
-  GNUNET_CRYPTO_hash (rctx->wire_method,
-                      strlen (rctx->wire_method) + 1,
-                      &h_wire_method);
+  wire_method = TALER_payto_get_method (rctx->payto_uri);
   db->preflight (db->cls);
   qs = db->lookup_wire_fee (db->cls,
-                            master_pub,
-                            &h_wire_method,
+                            &rctx->master_pub,
+                            wire_method,
                             execution_time,
                             &expected_fee,
                             &closing_fee,
@@ -545,16 +555,19 @@ check_wire_fee (struct TrackTransferContext *rctx,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Failed to find wire fee for `%s' and method `%s' at %s in DB, 
accepting blindly that the fee is %s\n",
-                TALER_B2S (master_pub),
-                rctx->wire_method,
+                TALER_B2S (&rctx->master_pub),
+                wire_method,
                 GNUNET_STRINGS_absolute_time_to_string (execution_time),
                 TALER_amount2s (wire_fee));
+    GNUNET_free (wire_method);
     return GNUNET_NO;
   }
   if (0 <= TALER_amount_cmp (&expected_fee,
                              wire_fee))
+  {
+    GNUNET_free (wire_method);
     return GNUNET_OK; /* expected_fee >= wire_fee */
-
+  }
   /* Wire fee check failed, export proof to client */
   resume_track_transfer_with_response (
     rctx,
@@ -569,8 +582,9 @@ check_wire_fee (struct TrackTransferContext *rctx,
       "start_date", GNUNET_JSON_from_time_abs (start_date),
       "end_date", GNUNET_JSON_from_time_abs (end_date),
       "master_sig", GNUNET_JSON_from_data_auto (&master_sig),
-      "master_pub", GNUNET_JSON_from_data_auto (master_pub),
+      "master_pub", GNUNET_JSON_from_data_auto (&rctx->master_pub),
       "json", json));
+  GNUNET_free (wire_method);
   return GNUNET_SYSERR;
 }
 
@@ -607,7 +621,7 @@ wire_transfer_cb (void *cls,
 
   rctx->wdh = NULL;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Got response code %u from exchange for /track/transfer\n",
+              "Got response code %u from exchange for GET /transfers/$WTID\n",
               hr->http_status);
   if (MHD_HTTP_OK != hr->http_status)
   {
@@ -622,36 +636,33 @@ wire_transfer_cb (void *cls,
         "exchange_reply", hr->reply));
     return;
   }
-  for (unsigned int i = 0; i<MAX_RETRIES; i++)
-  {
-    db->preflight (db->cls);
-    qs = db->store_transfer_to_proof (db->cls,
-                                      rctx->url,
-                                      &rctx->wtid,
-                                      execution_time,
-                                      exchange_pub,
-                                      hr->reply);
-    if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
-      break;
-  }
+  db->preflight (db->cls);
+  qs = db->insert_transfer_details (db->cls,
+                                    rctx->exchange_url,
+                                    rctx->payto_uri,
+                                    &rctx->wtid,
+                                    total_amount,
+                                    wire_fee,
+                                    execution_time,
+                                    details_length,
+                                    details);
   if (0 > qs)
   {
     /* Special report if retries insufficient */
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
     /* Always report on hard error as well to enable diagnostics */
     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
-    resume_track_transfer_with_response
-      (rctx,
+    resume_track_transfer_with_response (
+      rctx,
       MHD_HTTP_INTERNAL_SERVER_ERROR,
-      TALER_MHD_make_json_pack ("{s:I, s:s}",
-                                "code",
-                                (json_int_t)
-                                
TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSFER_ERROR,
-                                "details",
-                                "failed to store response from exchange to 
local database"));
+      TALER_MHD_make_json_pack (
+        "{s:I, s:s}",
+        "code",
+        (json_int_t) TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSFER_ERROR,
+        "details",
+        "failed to store response from exchange to local database"));
     return;
   }
-  rctx->original_response = hr->reply;
 
   if (GNUNET_SYSERR ==
       check_wire_fee (rctx,
@@ -767,27 +778,11 @@ wire_transfer_cb (void *cls,
       return;
     }
   }
-  rctx->original_response = NULL;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "About to call tracks transformator.\n");
-
-  if (NULL == (jresponse =
-                 transform_response (hr->reply,
-                                     rctx)))
-  {
-    resume_track_transfer_with_response
-      (rctx,
-      MHD_HTTP_INTERNAL_SERVER_ERROR,
-      TALER_MHD_make_error (TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR,
-                            "Fail to elaborate the response."));
-    return;
-  }
 
+  /* resume processing, main function will build the response */
   resume_track_transfer_with_response (rctx,
-                                       MHD_HTTP_OK,
-                                       TALER_MHD_make_json (jresponse));
-  json_decref (jresponse);
+                                       0,
+                                       NULL);
 }
 
 
@@ -801,12 +796,12 @@ wire_transfer_cb (void *cls,
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 static void
-process_track_transfer_with_exchange (void *cls,
-                                      const struct
-                                      TALER_EXCHANGE_HttpResponse *hr,
-                                      struct TALER_EXCHANGE_Handle *eh,
-                                      const struct TALER_Amount *wire_fee,
-                                      int exchange_trusted)
+process_track_transfer_with_exchange (
+  void *cls,
+  const struct TALER_EXCHANGE_HttpResponse *hr,
+  struct TALER_EXCHANGE_Handle *eh,
+  const struct TALER_Amount *wire_fee,
+  int exchange_trusted)
 {
   struct TrackTransferContext *rctx = cls;
 
@@ -829,7 +824,20 @@ process_track_transfer_with_exchange (void *cls,
         "exchange_reply", hr->reply));
     return;
   }
-  rctx->eh = eh;
+
+  /* keep master key for later */
+  {
+    const struct TALER_EXCHANGE_Keys *keys;
+
+    keys = TALER_EXCHANGE_get_keys (eh);
+    if (NULL == keys)
+    {
+      GNUNET_break (0);
+      return GNUNET_NO;
+    }
+    rctx->master_pub = keys->master_pub;
+  }
+
   rctx->wdh = TALER_EXCHANGE_transfers_get (eh,
                                             &rctx->wtid,
                                             &wire_transfer_cb,
@@ -837,19 +845,47 @@ process_track_transfer_with_exchange (void *cls,
   if (NULL == rctx->wdh)
   {
     GNUNET_break (0);
-    resume_track_transfer_with_response
-      (rctx,
+    resume_track_transfer_with_response (
+      rctx,
       MHD_HTTP_INTERNAL_SERVER_ERROR,
-      TALER_MHD_make_json_pack ("{s:I, s:s}",
-                                "code",
-                                (json_int_t)
-                                TALER_EC_TRACK_TRANSFER_REQUEST_ERROR,
-                                "error",
-                                "failed to run /transfers/ GET on exchange"));
+      TALER_MHD_make_json_pack (
+        "{s:I, s:s}",
+        "code",
+        (json_int_t) TALER_EC_TRACK_TRANSFER_REQUEST_ERROR,
+        "error",
+        "failed to run GET /transfers/ on exchange"));
   }
 }
 
 
+/**
+ * Function called with information about a wire transfer identifier.
+ * Generate a response array based on the given information.
+ *
+ * @param cls closure, a `json_t` array to update
+ * @param order_id the order to which the deposits belong
+ * @param deposit_value the amount deposited under @a order_id
+ * @param deposit_fee the fee charged for @a deposit_value
+ */
+static void
+proof_cb (void *cls,
+          const char *order_id,
+          const struct TALER_Amount *deposit_value,
+          const struct TALER_Amount *deposit_fee)
+{
+  json_t *ja = cls;
+
+  GNUNET_assert (
+    0 ==
+    json_array_append_new (
+      ja,
+      "{s:s,s:o,s:o}",
+      "order_id", order_id,
+      "deposit_value", TALER_JSON_spec_amount (deposit_value),
+      "deposit_fee", TALER_JSON_spec_amount (deposit_fee)));
+}
+
+
 /**
  * Handle a timeout for the processing of the track transfer request.
  *
@@ -861,14 +897,18 @@ handle_track_transfer_timeout (void *cls)
   struct TrackTransferContext *rctx = cls;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Resuming /track/transfer with error after timeout\n");
+              "Resuming POST /private/transfers with error after timeout\n");
   rctx->timeout_task = NULL;
-
   if (NULL != rctx->fo)
   {
     TMH_EXCHANGES_find_exchange_cancel (rctx->fo);
     rctx->fo = NULL;
   }
+  if (NULL != rctx->wdh)
+  {
+    TALER_EXCHANGE_transfers_get_cancel (rctx->wdh);
+    rctx->wdh = NULL;
+  }
   resume_track_transfer_with_response (rctx,
                                        MHD_HTTP_SERVICE_UNAVAILABLE,
                                        TALER_MHD_make_error (
@@ -878,81 +918,38 @@ handle_track_transfer_timeout (void *cls)
 
 
 /**
- * Function called with information about a wire transfer identifier.
- * Generate a response based on the given @a proof.
- *
- * @param cls closure
- * @param proof proof from exchange about what the wire transfer was for.
- *              should match the `TrackTransactionResponse` format
- *              of the exchange
- */
-static void
-proof_cb (void *cls,
-          const json_t *proof)
-{
-  struct TrackTransferContext *rctx = cls;
-  json_t *transformed_response;
-
-  if (NULL == (transformed_response =
-                 transform_response (proof,
-                                     rctx)))
-  {
-    rctx->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    rctx->response
-      = TALER_MHD_make_error (TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR,
-                              "Fail to elaborate response.");
-    return;
-  }
-
-  rctx->response_code = MHD_HTTP_OK;
-  rctx->response = TALER_MHD_make_json (transformed_response);
-  json_decref (transformed_response);
-}
-
-
-/**
- * Manages a /track/transfer call, thus it calls the /track/wtid
- * offered by the exchange in order to return the set of transfers
+ * Manages a POST /private/transfers call. It calls the /track/wtid
+ * offered by the exchange in order to obtain the set of transfers
  * (of coins) associated with a given wire transfer.
  *
  * @param rh context of the handler
  * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @param mi merchant backend instance, never NULL
+ * @param[in,out] hc context with further information about the request
  * @return MHD result code
  */
 MHD_RESULT
-MH_handler_track_transfer (struct TMH_RequestHandler *rh,
-                           struct MHD_Connection *connection,
-                           void **connection_cls,
-                           const char *upload_data,
-                           size_t *upload_data_size,
-                           struct MerchantInstance *mi)
+TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
+                            struct MHD_Connection *connection,
+                            struct TMH_HandlerContext *hc)
 {
-  struct TrackTransferContext *rctx;
+  struct TrackTransferContext *rctx = hc->ctx;
   const char *str;
   const char *url;
   const char *wire_method;
-  MHD_RESULT ret;
   enum GNUNET_DB_QueryStatus qs;
 
-  if (NULL == *connection_cls)
+  if (NULL == rctx)
   {
     rctx = GNUNET_new (struct TrackTransferContext);
-    rctx->hc.cc = &track_transfer_cleanup;
     rctx->connection = connection;
-    *connection_cls = rctx;
-  }
-  else
-  {
-    /* not first call, recover state */
-    rctx = *connection_cls;
+    hc->ctx = rctx;
+    hc->cleanup_cb = &track_transfer_cleanup;
   }
 
   if (0 != rctx->response_code)
   {
+    MHD_RESULT ret;
+
     /* We are *done* processing the request, just queue the response (!) */
     if (UINT_MAX == rctx->response_code)
     {
@@ -968,13 +965,13 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh,
       rctx->response = NULL;
     }
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Queueing response (%u) for /track/transfer (%s).\n",
+                "Queueing response (%u) for POST /private/transfers (%s).\n",
                 (unsigned int) rctx->response_code,
                 ret ? "OK" : "FAILED");
     return ret;
   }
   if ( (NULL != rctx->fo) ||
-       (NULL != rctx->eh) )
+       (NULL != rctx->wdh) )
   {
     /* likely old MHD version */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -982,66 +979,85 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh,
     return MHD_YES; /* still work in progress */
   }
 
-  url = MHD_lookup_connection_value (connection,
-                                     MHD_GET_ARGUMENT_KIND,
-                                     "exchange");
-  if (NULL == url)
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       TALER_EC_PARAMETER_MISSING,
-                                       "exchange");
-  rctx->url = GNUNET_strdup (url);
-
-  /* FIXME: change again: we probably don't want the wire_method
-     but rather the _account_ (section) here! */
-  wire_method = MHD_lookup_connection_value (connection,
-                                             MHD_GET_ARGUMENT_KIND,
-                                             "wire_method");
-  if (NULL == wire_method)
   {
-    if (1)
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_string ("exchange",
+                               &rctx->exchange_url),
+      GNUNET_JSON_spec_string ("payto_uri",
+                               &rctx->payto_uri),
+      TALER_JSON_spec_amount ("amount",
+                              &rctx->amount),
+      GNUNET_JSON_spec_fixed_auto ("wtid",
+                                   &rctx->wtid),
+      GNUNET_JSON_spec_end ()
+    };
+
+    GNUNET_assert (NULL != mi);
     {
-      /* temporary work-around until demo is adjusted... */
-      GNUNET_break (0);
-      wire_method = "x-taler-bank";
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Client needs fixing, see API change for #4943!\n");
+      enum GNUNET_GenericReturnValue res;
+
+      res = TALER_MHD_parse_json_data (connection,
+                                       hc->request_body,
+                                       spec);
+      if (GNUNET_OK != res)
+        return (GNUNET_NO == res)
+               ? MHD_YES
+               : MHD_NO;
     }
-    else
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_BAD_REQUEST,
-                                         TALER_EC_PARAMETER_MISSING,
-                                         "wire_method");
   }
-  rctx->wire_method = GNUNET_strdup (wire_method);
-  rctx->mi = mi;
-  str = MHD_lookup_connection_value (connection,
-                                     MHD_GET_ARGUMENT_KIND,
-                                     "wtid");
-  if (NULL == str)
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       TALER_EC_PARAMETER_MISSING,
-                                       "wtid");
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_string_to_data (str,
-                                     strlen (str),
-                                     &rctx->wtid,
-                                     sizeof (rctx->wtid)))
+
+  /* Check if reply is already in database! */
   {
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       TALER_EC_PARAMETER_MALFORMED,
-                                       "wtid");
+    json_t *deposit_sums;
+    struct GNUNET_TIME_Absolute execution_time;
+    struct TALER_Amount total_amount;
+    struct TALER_Amount wire_fee;
+
+    deposit_sums = json_array ();
+    GNUNET_assert (NULL != deposit_sums);
+    db->preflight (db->cls);
+    qs = db->lookup_transfer_details (db->cls,
+                                      rctx->exchange_url,
+                                      rctx->payto_uri,
+                                      &rctx->wtid,
+                                      &total_amount,
+                                      &wire_fee,
+                                      &execution_time,
+                                      &transfer_details_cb,
+                                      deposit_sums);
+    if (0 > qs)
+    {
+      /* Simple select queries should not cause serialization issues */
+      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+      /* Always report on hard error as well to enable diagnostics */
+      GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+      json_decref (deposit_sums);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         
TALER_EC_POST_TRANSFERS_DB_LOOKUP_ERROR,
+                                         "Fail to query database about 
proofs");
+    }
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
+    {
+      return TALER_MHD_reply_json_pack (
+        connection,
+        MHD_HTTP_OK,
+        "{s:o,s:o,s:o,s:o}",
+        "total", TALER_JSON_from_amount (&total_amount),
+        "wire_fee", TALER_JSON_from_amount (&wire_fee),
+        "execution_time", GNUNET_JSON_from_time_abs (execution_time),
+        "deposit_sums", deposit_sums);
+    }
+    json_decref (deposit_sums);
   }
 
-  /* Check if reply is already in database! */
-  db->preflight (db->cls);
-  qs = db->find_proof_by_wtid (db->cls,
-                               rctx->url,
-                               &rctx->wtid,
-                               &proof_cb,
-                               rctx);
+  /* reply not in database, ensure the POST is in the database, and
+     start work to obtain the reply from the exchange */
+  qs = db->insert_transfer (db->cls,
+                            rctx->exchange_url,
+                            &rctx->wtid,
+                            &rctx->amount,
+                            rctx->payto_uri);
   if (0 > qs)
   {
     /* Simple select queries should not cause serialization issues */
@@ -1050,30 +1066,17 @@ MH_handler_track_transfer (struct TMH_RequestHandler 
*rh,
     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       
TALER_EC_TRACK_TRANSFER_DB_FETCH_DEPOSIT_ERROR,
-                                       "Fail to query database about proofs");
-  }
-  if (0 != rctx->response_code)
-  {
-    ret = MHD_queue_response (connection,
-                              rctx->response_code,
-                              rctx->response);
-    if (NULL != rctx->response)
-    {
-      MHD_destroy_response (rctx->response);
-      rctx->response = NULL;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Queueing response (%u) for /track/transfer (%s).\n",
-                (unsigned int) rctx->response_code,
-                ret ? "OK" : "FAILED");
-    return ret;
+                                       TALER_EC_POST_TRANSFER_DB_STORE_ERROR,
+                                       "Fail to update database with transfer 
record");
   }
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Suspending /track/transfer handling while working with the 
exchange\n");
+              "Suspending POST /private/transfers handling while working with 
exchange\n");
   MHD_suspend_connection (connection);
-  rctx->fo = TMH_EXCHANGES_find_exchange (url,
+  GNUNET_CONTAINER_DLL_insert (pth_head,
+                               pth_tail,
+                               rctx);
+  rctx->fo = TMH_EXCHANGES_find_exchange (rctx->exchange_url,
                                           NULL,
                                           GNUNET_NO,
                                           
&process_track_transfer_with_exchange,
@@ -1086,4 +1089,4 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh,
 }
 
 
-/* end of taler-merchant-httpd_track-transfer.c */
+/* end of taler-merchant-httpd_private-post-transfers.c */
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index 31903f8..6abc055 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -334,11 +334,20 @@ CREATE TABLE IF NOT EXISTS merchant_refund_proofs
   (refund_serial BIGINT PRIMARY KEY
      REFERENCES merchant_refunds (refund_serial) ON DELETE CASCADE
   ,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64)
+  ,execution_time INT8 NOT NULL
+  ,total_amount_val INT8 NOT NULL
+  ,total_amount_frac INT4 NOT NULL
+  ,wire_fee_val INT8 NOT NULL
+  ,wire_fee_frac INT4 NOT NULL
   ,signkey_serial BIGINT NOT NULL
      REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE 
CASCADE
 );
 COMMENT ON TABLE merchant_refund_proofs
   IS 'Refunds confirmed by the exchange (not all approved refunds are grabbed 
by the wallet)';
+COMMENT ON COLUMN merchant_refund_proofs.execution_time
+  IS 'When did the exchange claim to execute the wire transfer';
+COMMENT ON COLUMN merchant_refund_proofs.total_amount_val
+  IS 'Amount the exchange claims to have deducted from the merchant balance; 
actual transfer amount is this minus the wire fee';
 
 -------------------- Wire transfers ---------------------------
 
@@ -408,7 +417,7 @@ CREATE TABLE IF NOT EXISTS merchant_deposit_to_transfer
   ,signkey_serial BIGINT NOT NULL
      REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE 
CASCADE
   ,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64)
-  ,UNIQUE(coin_pub,wtid)
+  ,UNIQUE(deposit_serial,credit_serial)
 );
 COMMENT ON TABLE merchant_deposit_to_transfer
   IS 'Mapping of deposits to (possibly unconfirmed) wire transfers';
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index f95f346..1599642 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -2444,6 +2444,45 @@ postgres_increase_refund (void *cls,
 }
 
 
+/**
+ * Retrieve the order ID that was used to pay for a resource within a session.
+ *
+ * @param cls closure
+ * @param instance_id identifying the instance
+ * @param fulfillment_url URL that canonically identifies the resource
+ *        being paid for
+ * @param session_id session id
+ * @param[out] order_id where to store the order ID that was used when
+ *             paying for the resource URL
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+postgres_lookup_order_by_fulfillment (void *cls,
+                                      const char *instance_id,
+                                      const char *fulfillment_url,
+                                      const char *session_id,
+                                      char **order_id)
+{
+  struct PostgresClosure *pg = cls;
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (fulfillment_url),
+    GNUNET_PQ_query_param_string (session_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_string ("order_id",
+                                  order_id),
+    GNUNET_PQ_result_spec_end
+  };
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"lookup_order_by_fulfillment",
+                                                   params,
+                                                   rs);
+}
+
+
 /* ********************* OLD API ************************** */
 
 /**
@@ -2559,47 +2598,6 @@ postgres_insert_session_info (void *cls,
 }
 
 
-/**
- * Retrieve the order ID that was used to pay for a resource within a session.
- *
- * @param cls closure
- * @param[out] order_id where to store the order ID that was used when
- *             paying for the resource URL
- * @param session_id session id
- * @param fulfillment_url URL that canonically identifies the resource
- *        being paid for
- * @param merchant_pub public key of the merchant, identifying the instance
- * @return transaction status
- */
-enum GNUNET_DB_QueryStatus
-postgres_find_session_info (void *cls,
-                            char **order_id,
-                            const char *session_id,
-                            const char *fulfillment_url,
-                            const struct TALER_MerchantPublicKeyP 
*merchant_pub)
-{
-  struct PostgresClosure *pg = cls;
-
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (fulfillment_url),
-    GNUNET_PQ_query_param_string (session_id),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_string ("order_id",
-                                  order_id),
-    GNUNET_PQ_result_spec_end
-  };
-  // We don't clean up the result spec since we want
-  // to keep around the memory for order_id.
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "find_session_info",
-                                                   params,
-                                                   rs);
-}
-
-
 /**
  * Insert mapping of @a coin_pub and @a h_contract_terms to
  * corresponding @a wtid.
@@ -3619,26 +3617,24 @@ postgres_put_refund_proof (
 static enum GNUNET_DB_QueryStatus
 postgres_store_wire_fee_by_exchange (
   void *cls,
-  const struct
-  TALER_MasterPublicKeyP *exchange_pub,
-  const struct
-  GNUNET_HashCode *h_wire_method,
+  const struct TALER_MasterPublicKeyP *master_pub,
+  const struct GNUNET_HashCode *h_wire_method,
   const struct TALER_Amount *wire_fee,
   const struct TALER_Amount *closing_fee,
   struct GNUNET_TIME_Absolute start_date,
   struct GNUNET_TIME_Absolute end_date,
   const struct
-  TALER_MasterSignatureP *exchange_sig)
+  TALER_MasterSignatureP *master_sig)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+    GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_auto_from_type (h_wire_method),
     TALER_PQ_query_param_amount (wire_fee),
     TALER_PQ_query_param_amount (closing_fee),
     GNUNET_PQ_query_param_absolute_time (&start_date),
     GNUNET_PQ_query_param_absolute_time (&end_date),
-    GNUNET_PQ_query_param_auto_from_type (exchange_sig),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
     GNUNET_PQ_query_param_end
   };
 
@@ -3646,7 +3642,7 @@ postgres_store_wire_fee_by_exchange (
   check_connection (pg);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Storing wire fee for %s starting at %s of %s\n",
-              TALER_B2S (exchange_pub),
+              TALER_B2S (master_pub),
               GNUNET_STRINGS_absolute_time_to_string (start_date),
               TALER_amount2s (wire_fee));
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
@@ -5634,6 +5630,18 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             "           FROM merchant_instances"
                             "          WHERE merchant_id=$1))",
                             2),
+    /* for postgres_lookup_order_by_fulfillment() */
+    GNUNET_PQ_make_prepare ("lookup_order_by_fulfillment",
+                            "SELECT"
+                            " order_id"
+                            " FROM merchant_contract_terms"
+                            " WHERE fulfillment_url=$2"
+                            "   AND session_id=$3"
+                            "   AND merchant_serial="
+                            "        (SELECT merchant_serial"
+                            "           FROM merchant_instances"
+                            "          WHERE merchant_id=$1)",
+                            3),
 
     /* OLD API: */
 
@@ -5725,15 +5733,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             " FROM merchant_refunds"
                             " WHERE coin_pub=$1",
                             1),
-    GNUNET_PQ_make_prepare ("find_session_info",
-                            "SELECT"
-                            " order_id"
-                            " FROM merchant_session_info"
-                            " WHERE"
-                            " fulfillment_url=$1"
-                            " AND session_id=$2"
-                            " AND merchant_pub=$3",
-                            2),
     GNUNET_PQ_make_prepare ("find_refunds_from_contract_terms_hash",
                             "SELECT"
                             " coin_pub"
@@ -6023,7 +6022,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->refund_coin = &postgres_refund_coin;
   plugin->lookup_order_status = &postgres_lookup_order_status;
   plugin->increase_refund = &postgres_increase_refund;
-
+  plugin->lookup_order_by_fulfillment = &postgres_lookup_order_by_fulfillment;
 /* OLD API: */
   plugin->find_contract_terms_from_hash =
     &postgres_find_contract_terms_from_hash;
@@ -6041,8 +6040,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->lookup_wire_fee = &postgres_lookup_wire_fee;
   plugin->get_refund_proof = &postgres_get_refund_proof;
   plugin->put_refund_proof = &postgres_put_refund_proof;
-  plugin->insert_session_info = &postgres_insert_session_info;
-  plugin->find_session_info = &postgres_find_session_info;
   plugin->enable_tip_reserve_TR = &postgres_enable_tip_reserve_TR;
   plugin->authorize_tip_TR = &postgres_authorize_tip_TR;
   plugin->lookup_tip_by_id = &postgres_lookup_tip_by_id;
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index cefc373..eb4b272 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -1196,25 +1196,6 @@ struct TALER_MERCHANTDB_Plugin
   /* ****************** OLD API ******************** */
 
 
-  /**
-   * Store the order ID that was used to pay for a resource within a session.
-   *
-   * @param cls closure
-   * @param session_id session id
-   * @param fulfillment_url URL that canonically identifies the resource
-   *        being paid for
-   * @param order_id the order ID that was used when paying for the resource 
URL
-   * @param merchant_pub public key of the merchant, identifying the instance
-   * @return transaction status
-   */
-  enum GNUNET_DB_QueryStatus
-  (*insert_session_info)(void *cls,
-                         const char *session_id,
-                         const char *fulfillment_url,
-                         const char *order_id,
-                         const struct TALER_MerchantPublicKeyP *merchant_pub);
-
-
   /**
    * Retrieve proposal data given its hashcode
    *

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