gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: first rough-cut implementation o


From: gnunet
Subject: [taler-exchange] branch master updated: first rough-cut implementation of POST /reserves//status
Date: Mon, 21 Mar 2022 02:39:45 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new f5f15e65 first rough-cut implementation of POST /reserves//status
f5f15e65 is described below

commit f5f15e6531bb7072a02cb976771a43803bd044f6
Author: Christian Grothoff <grothoff@gnunet.org>
AuthorDate: Mon Mar 21 02:39:36 2022 +0100

    first rough-cut implementation of POST /reserves//status
---
 contrib/gana                                       |   2 +-
 src/exchange/Makefile.am                           |   1 +
 src/exchange/taler-exchange-httpd.c                |  84 ++++++++-
 src/exchange/taler-exchange-httpd_deposit.c        |  12 --
 src/exchange/taler-exchange-httpd_mhd.h            |   2 +-
 src/exchange/taler-exchange-httpd_reserves_get.c   |  88 +++++----
 .../taler-exchange-httpd_reserves_status.c         | 199 +++++++++++++++++++++
 ...hd.h => taler-exchange-httpd_reserves_status.h} |  36 ++--
 src/exchange/taler-exchange-httpd_responses.c      | 122 +------------
 src/exchange/taler-exchange-httpd_responses.h      |   7 +-
 src/exchange/taler-exchange-httpd_withdraw.c       |  35 +---
 src/exchange/taler-exchange-httpd_withdraw.h       |  10 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |  43 +++++
 src/include/taler_exchangedb_plugin.h              |  14 ++
 14 files changed, 410 insertions(+), 245 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index baeb8203..4cfefdf3 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit baeb820366b88befd6f5aa2a551e2827ef406daf
+Subproject commit 4cfefdf374de55fe9be3f0f039c7a13f496ab970
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index 3a07b6f4..2923aa2d 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -108,6 +108,7 @@ taler_exchange_httpd_SOURCES = \
   taler-exchange-httpd_refreshes_reveal.c 
taler-exchange-httpd_refreshes_reveal.h \
   taler-exchange-httpd_refund.c taler-exchange-httpd_refund.h \
   taler-exchange-httpd_reserves_get.c taler-exchange-httpd_reserves_get.h \
+  taler-exchange-httpd_reserves_status.c 
taler-exchange-httpd_reserves_status.h \
   taler-exchange-httpd_responses.c taler-exchange-httpd_responses.h \
   taler-exchange-httpd_terms.c taler-exchange-httpd_terms.h \
   taler-exchange-httpd_transfers_get.c taler-exchange-httpd_transfers_get.h \
diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index f0dc365a..676135fa 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -48,6 +48,7 @@
 #include "taler-exchange-httpd_refreshes_reveal.h"
 #include "taler-exchange-httpd_refund.h"
 #include "taler-exchange-httpd_reserves_get.h"
+#include "taler-exchange-httpd_reserves_status.h"
 #include "taler-exchange-httpd_terms.h"
 #include "taler-exchange-httpd_transfers_get.h"
 #include "taler-exchange-httpd_wire.h"
@@ -212,6 +213,19 @@ typedef MHD_RESULT
                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
                  const json_t *root);
 
+/**
+ * Signature of functions that handle operations on reserves.
+ *
+ * @param rc request context
+ * @param reserve_pub the public key of the reserve
+ * @param root uploaded JSON data
+ * @return MHD result code
+ */
+typedef MHD_RESULT
+(*ReserveOpHandler)(struct TEH_RequestContext *rc,
+                    const struct TALER_ReservePublicKeyP *reserve_pub,
+                    const json_t *root);
+
 
 /**
  * Generate a 404 "not found" reply on @a connection with
@@ -237,8 +251,7 @@ r404 (struct MHD_Connection *connection,
  *
  * @param rc request context
  * @param root uploaded JSON data
- * @param args array of additional options (first must be the
- *         reserve public key, the second one should be "withdraw")
+ * @param args array of additional options
  * @return MHD result code
  */
 static MHD_RESULT
@@ -309,6 +322,71 @@ handle_post_coins (struct TEH_RequestContext *rc,
 }
 
 
+/**
+ * Handle a "/reserves/$RESERVE_PUB/$OP" POST request.  Parses the 
"reserve_pub"
+ * EdDSA key of the reserve and demultiplexes based on $OP.
+ *
+ * @param rc request context
+ * @param root uploaded JSON data
+ * @param args array of additional options
+ * @return MHD result code
+ */
+static MHD_RESULT
+handle_post_reserves (struct TEH_RequestContext *rc,
+                      const json_t *root,
+                      const char *const args[2])
+{
+  struct TALER_ReservePublicKeyP reserve_pub;
+  static const struct
+  {
+    /**
+     * Name of the operation (args[1])
+     */
+    const char *op;
+
+    /**
+     * Function to call to perform the operation.
+     */
+    ReserveOpHandler handler;
+
+  } h[] = {
+    {
+      .op = "withdraw",
+      .handler = &TEH_handler_withdraw
+    },
+    {
+      .op = "status",
+      .handler = &TEH_handler_reserves_status
+    },
+    {
+      .op = NULL,
+      .handler = NULL
+    },
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (args[0],
+                                     strlen (args[0]),
+                                     &reserve_pub,
+                                     sizeof (reserve_pub)))
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       
TALER_EC_EXCHANGE_GENERIC_RESERVE_PUB_MALFORMED,
+                                       args[0]);
+  }
+  for (unsigned int i = 0; NULL != h[i].op; i++)
+    if (0 == strcmp (h[i].op,
+                     args[1]))
+      return h[i].handler (rc,
+                           &reserve_pub,
+                           root);
+  return r404 (rc->connection,
+               args[1]);
+}
+
+
 /**
  * Increments our request counter and checks if this
  * process should commit suicide.
@@ -947,7 +1025,7 @@ handle_mhd_request (void *cls,
     {
       .url = "reserves",
       .method = MHD_HTTP_METHOD_POST,
-      .handler.post = &TEH_handler_withdraw,
+      .handler.post = &handle_post_reserves,
       .nargs = 2
     },
     /* coins */
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index a2e22f2e..00353a40 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -205,18 +205,6 @@ deposit_transaction (void *cls,
 }
 
 
-/**
- * Handle a "/coins/$COIN_PUB/deposit" request.  Parses the JSON, and, if
- * successful, passes the JSON data to #deposit_transaction() to
- * further check the details of the operation specified.  If everything checks
- * out, this will ultimately lead to the "/deposit" being executed, or
- * rejected.
- *
- * @param connection the MHD connection to handle
- * @param coin_pub public key of the coin
- * @param root uploaded JSON data
- * @return MHD result code
-  */
 MHD_RESULT
 TEH_handler_deposit (struct MHD_Connection *connection,
                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
diff --git a/src/exchange/taler-exchange-httpd_mhd.h 
b/src/exchange/taler-exchange-httpd_mhd.h
index 270b0539..563975be 100644
--- a/src/exchange/taler-exchange-httpd_mhd.h
+++ b/src/exchange/taler-exchange-httpd_mhd.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2020 Taler Systems SA
+  Copyright (C) 2014-2022 Taler Systems SA
 
   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
diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c 
b/src/exchange/taler-exchange-httpd_reserves_get.c
index 4b1bbdde..0b5db7c8 100644
--- a/src/exchange/taler-exchange-httpd_reserves_get.c
+++ b/src/exchange/taler-exchange-httpd_reserves_get.c
@@ -164,37 +164,6 @@ db_event_cb (void *cls,
 }
 
 
-/**
- * Send reserve history to client.
- *
- * @param connection connection to the client
- * @param rh reserve history to return
- * @return MHD result code
- */
-static MHD_RESULT
-reply_reserve_history_success (struct MHD_Connection *connection,
-                               const struct TALER_EXCHANGEDB_ReserveHistory 
*rh)
-{
-  json_t *json_history;
-  struct TALER_Amount balance;
-
-  json_history = TEH_RESPONSE_compile_reserve_history (rh,
-                                                       &balance);
-  if (NULL == json_history)
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       
TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
-                                       NULL);
-  return TALER_MHD_REPLY_JSON_PACK (
-    connection,
-    MHD_HTTP_OK,
-    TALER_JSON_pack_amount ("balance",
-                            &balance),
-    GNUNET_JSON_pack_array_steal ("history",
-                                  json_history));
-}
-
-
 /**
  * Closure for #reserve_history_transaction.
  */
@@ -205,10 +174,18 @@ struct ReserveHistoryContext
    */
   struct TALER_ReservePublicKeyP reserve_pub;
 
+#ifndef MBOSS_DONE
   /**
    * History of the reserve, set in the callback.
+   * FIXME: get rid of this once benchmarking is done!
    */
   struct TALER_EXCHANGEDB_ReserveHistory *rh;
+#endif
+
+  /**
+   * Balance of the reserve, set in the callback.
+   */
+  struct TALER_Amount balance;
 
 };
 
@@ -226,23 +203,37 @@ struct ReserveHistoryContext
  * @param cls a `struct ReserveHistoryContext *`
  * @param connection MHD request which triggered the transaction
  * @param[out] mhd_ret set to MHD response status for @a connection,
- *             if transaction failed (!); unused
+ *             if transaction failed (!)
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-reserve_history_transaction (void *cls,
+reserve_balance_transaction (void *cls,
                              struct MHD_Connection *connection,
                              MHD_RESULT *mhd_ret)
 {
   struct ReserveHistoryContext *rsc = cls;
-  struct TALER_Amount balance;
-
-  (void) connection;
-  (void) mhd_ret;
-  return TEH_plugin->get_reserve_history (TEH_plugin->cls,
-                                          &rsc->reserve_pub,
-                                          &balance,
-                                          &rsc->rh);
+  enum GNUNET_DB_QueryStatus qs;
+
+#ifdef MBOSS_DONE
+  qs = TEH_plugin->get_reserve_balance (TEH_plugin->cls,
+                                        &rsc->reserve_pub,
+                                        &rsc->balance);
+#else
+  qs = TEH_plugin->get_reserve_history (TEH_plugin->cls,
+                                        &rsc->reserve_pub,
+                                        &rsc->balance,
+                                        &rsc->rh);
+#endif
+  if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+  {
+    GNUNET_break (0);
+    *mhd_ret
+      = TALER_MHD_reply_with_error (connection,
+                                    MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                    TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                    "get_reserve_balance");
+  }
+  return qs;
 }
 
 
@@ -314,10 +305,10 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc,
   rsc.rh = NULL;
   if (GNUNET_OK !=
       TEH_DB_run_transaction (rc->connection,
-                              "get reserve history",
+                              "get reserve balance",
                               TEH_MT_REQUEST_OTHER,
                               &mhd_ret,
-                              &reserve_history_transaction,
+                              &reserve_balance_transaction,
                               &rsc))
   {
     if (NULL != eh)
@@ -335,7 +326,7 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc,
     {
       return TALER_MHD_reply_with_error (rc->connection,
                                          MHD_HTTP_NOT_FOUND,
-                                         
TALER_EC_EXCHANGE_RESERVES_GET_STATUS_UNKNOWN,
+                                         
TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN,
                                          args[0]);
     }
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -358,10 +349,15 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc,
   if (NULL != eh)
     TEH_plugin->event_listen_cancel (TEH_plugin->cls,
                                      eh);
-  mhd_ret = reply_reserve_history_success (rc->connection,
-                                           rsc.rh);
+  mhd_ret = TALER_MHD_REPLY_JSON_PACK (
+    rc->connection,
+    MHD_HTTP_OK,
+    TALER_JSON_pack_amount ("balance",
+                            &rsc.balance));
+#ifndef MBOSS_DONE
   TEH_plugin->free_reserve_history (TEH_plugin->cls,
                                     rsc.rh);
+#endif
   return mhd_ret;
 }
 
diff --git a/src/exchange/taler-exchange-httpd_reserves_status.c 
b/src/exchange/taler-exchange-httpd_reserves_status.c
new file mode 100644
index 00000000..0b6ee2d3
--- /dev/null
+++ b/src/exchange/taler-exchange-httpd_reserves_status.c
@@ -0,0 +1,199 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2022 Taler Systems SA
+
+  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
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more 
details.
+
+  You should have received a copy of the GNU Affero General Public License 
along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-exchange-httpd_reserves_status.c
+ * @brief Handle /reserves/$RESERVE_PUB STATUS requests
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <jansson.h>
+#include "taler_mhd_lib.h"
+#include "taler_json_lib.h"
+#include "taler_dbevents.h"
+#include "taler-exchange-httpd_keys.h"
+#include "taler-exchange-httpd_reserves_status.h"
+#include "taler-exchange-httpd_responses.h"
+
+
+/**
+ * Closure for #reserve_status_transaction.
+ */
+struct ReserveStatusContext
+{
+  /**
+   * Public key of the reserve the inquiry is about.
+   */
+  const struct TALER_ReservePublicKeyP *reserve_pub;
+
+  /**
+   * History of the reserve, set in the callback.
+   */
+  struct TALER_EXCHANGEDB_ReserveHistory *rh;
+
+  /**
+   * Current reserve balance.
+   */
+  struct TALER_Amount balance;
+};
+
+
+/**
+ * Send reserve status to client.
+ *
+ * @param connection connection to the client
+ * @param rh reserve history to return
+ * @return MHD result code
+ */
+static MHD_RESULT
+reply_reserve_status_success (struct MHD_Connection *connection,
+                              const struct ReserveStatusContext *rhc)
+{
+  const struct TALER_EXCHANGEDB_ReserveHistory *rh = rhc->rh;
+  json_t *json_history;
+
+  json_history = TEH_RESPONSE_compile_reserve_history (rh);
+  if (NULL == json_history)
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       
TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
+                                       NULL);
+  return TALER_MHD_REPLY_JSON_PACK (
+    connection,
+    MHD_HTTP_OK,
+    TALER_JSON_pack_amount ("balance",
+                            &rhc->balance),
+    GNUNET_JSON_pack_array_steal ("history",
+                                  json_history));
+}
+
+
+/**
+ * Function implementing /reserves/ STATUS transaction.
+ * Execute a /reserves/ STATUS.  Given the public key of a reserve,
+ * return the associated transaction history.  Runs the
+ * transaction logic; IF it returns a non-error code, the transaction
+ * logic MUST NOT queue a MHD response.  IF it returns an hard error,
+ * the transaction logic MUST queue a MHD response and set @a mhd_ret.
+ * IF it returns the soft error code, the function MAY be called again
+ * to retry and MUST not queue a MHD response.
+ *
+ * @param cls a `struct ReserveStatusContext *`
+ * @param connection MHD request which triggered the transaction
+ * @param[out] mhd_ret set to MHD response status for @a connection,
+ *             if transaction failed (!); unused
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+reserve_status_transaction (void *cls,
+                            struct MHD_Connection *connection,
+                            MHD_RESULT *mhd_ret)
+{
+  struct ReserveStatusContext *rsc = cls;
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = TEH_plugin->get_reserve_history (TEH_plugin->cls,
+                                        rsc->reserve_pub,
+                                        &rsc->balance,
+                                        &rsc->rh);
+  if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+  {
+    GNUNET_break (0);
+    *mhd_ret
+      = TALER_MHD_reply_with_error (connection,
+                                    MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                    TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                    "get_reserve_status");
+  }
+  return qs;
+}
+
+
+MHD_RESULT
+TEH_handler_reserves_status (struct TEH_RequestContext *rc,
+                             const struct TALER_ReservePublicKeyP *reserve_pub,
+                             const json_t *root)
+{
+  struct ReserveStatusContext rsc;
+  MHD_RESULT mhd_ret;
+  struct GNUNET_TIME_Timestamp timestamp;
+  struct TALER_ReserveSignatureP reserve_sig;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_timestamp ("request_timestamp",
+                                &timestamp),
+    GNUNET_JSON_spec_fixed_auto ("reserve_sig",
+                                 &reserve_sig),
+    GNUNET_JSON_spec_end ()
+  };
+
+  rsc.reserve_pub = reserve_pub;
+  {
+    enum GNUNET_GenericReturnValue res;
+
+    res = TALER_MHD_parse_json_data (rc->connection,
+                                     root,
+                                     spec);
+    if (GNUNET_SYSERR == res)
+    {
+      GNUNET_break (0);
+      return MHD_NO; /* hard failure */
+    }
+    if (GNUNET_NO == res)
+    {
+      GNUNET_break_op (0);
+      return MHD_YES; /* failure */
+    }
+  }
+  if (GNUNET_OK !=
+      TALER_wallet_reserve_status_verify (timestamp,
+                                          reserve_pub,
+                                          &reserve_sig))
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_FORBIDDEN,
+                                       
TALER_EC_EXCHANGE_RESERVES_STATUS_BAD_SIGNATURE,
+                                       NULL);
+  }
+  rsc.rh = NULL;
+  if (GNUNET_OK !=
+      TEH_DB_run_transaction (rc->connection,
+                              "get reserve status",
+                              TEH_MT_REQUEST_OTHER,
+                              &mhd_ret,
+                              &reserve_status_transaction,
+                              &rsc))
+  {
+    return mhd_ret;
+  }
+  if (NULL == rsc.rh)
+  {
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_NOT_FOUND,
+                                       
TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN,
+                                       NULL);
+  }
+  mhd_ret = reply_reserve_status_success (rc->connection,
+                                          &rsc);
+  TEH_plugin->free_reserve_history (TEH_plugin->cls,
+                                    rsc.rh);
+  return mhd_ret;
+}
+
+
+/* end of taler-exchange-httpd_reserves_status.c */
diff --git a/src/exchange/taler-exchange-httpd_mhd.h 
b/src/exchange/taler-exchange-httpd_reserves_status.h
similarity index 52%
copy from src/exchange/taler-exchange-httpd_mhd.h
copy to src/exchange/taler-exchange-httpd_reserves_status.h
index 270b0539..831b270f 100644
--- a/src/exchange/taler-exchange-httpd_mhd.h
+++ b/src/exchange/taler-exchange-httpd_reserves_status.h
@@ -13,45 +13,31 @@
   You should have received a copy of the GNU Affero General Public License 
along with
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
-
 /**
- * @file taler-exchange-httpd_mhd.h
- * @brief helpers for MHD interaction, used to generate simple responses
+ * @file taler-exchange-httpd_reserves_status.h
+ * @brief Handle /reserves/$RESERVE_PUB STATUS requests
  * @author Florian Dold
  * @author Benedikt Mueller
  * @author Christian Grothoff
  */
-#ifndef TALER_EXCHANGE_HTTPD_MHD_H
-#define TALER_EXCHANGE_HTTPD_MHD_H
-#include <gnunet/gnunet_util_lib.h>
+#ifndef TALER_EXCHANGE_HTTPD_RESERVES_STATUS_H
+#define TALER_EXCHANGE_HTTPD_RESERVES_STATUS_H
+
 #include <microhttpd.h>
 #include "taler-exchange-httpd.h"
 
 
 /**
- * Function to call to handle the request by sending
- * back static data from the request handler.
+ * Handle a POST "/reserves/$RID/status" request.
  *
  * @param rc request context
- * @param args array of additional options (must be empty for this function)
+ * @param reserve_pub public key of the reserve
+ * @param root uploaded body from the client
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_static_response (struct TEH_RequestContext *rc,
-                             const char *const args[]);
-
-
-/**
- * Function to call to handle the request by sending
- * back a redirect to the AGPL source code.
- *
- * @param rc request context
- * @param args array of additional options (must be empty for this function)
- * @return MHD result code
- */
-MHD_RESULT
-TEH_handler_agpl_redirect (struct TEH_RequestContext *rc,
-                           const char *const args[]);
-
+TEH_handler_reserves_status (struct TEH_RequestContext *rc,
+                             const struct TALER_ReservePublicKeyP *reserve_pub,
+                             const json_t *root);
 
 #endif
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index f1a219fc..ee8c902d 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2021 Taler Systems SA
+  Copyright (C) 2014-2022 Taler Systems SA
 
   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
@@ -605,31 +605,11 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
 }
 
 
-/**
- * Compile the history of a reserve into a JSON object
- * and calculate the total balance.
- *
- * @param rh reserve history to JSON-ify
- * @param[out] balance set to current reserve balance
- * @return json representation of the @a rh, NULL on error
- */
 json_t *
 TEH_RESPONSE_compile_reserve_history (
-  const struct TALER_EXCHANGEDB_ReserveHistory *rh,
-  struct TALER_Amount *balance)
+  const struct TALER_EXCHANGEDB_ReserveHistory *rh)
 {
-  struct TALER_Amount credit_total;
-  struct TALER_Amount withdraw_total;
   json_t *json_history;
-  enum InitAmounts
-  {
-    /** Nothing initialized */
-    IA_NONE = 0,
-    /** credit_total initialized */
-    IA_CREDIT = 1,
-    /** withdraw_total initialized */
-    IA_WITHDRAW = 2
-  } init = IA_NONE;
 
   json_history = json_array ();
   for (const struct TALER_EXCHANGEDB_ReserveHistory *pos = rh;
@@ -642,20 +622,7 @@ TEH_RESPONSE_compile_reserve_history (
       {
         const struct TALER_EXCHANGEDB_BankTransfer *bank =
           pos->details.bank;
-        if (0 == (IA_CREDIT & init))
-        {
-          credit_total = bank->amount;
-          init |= IA_CREDIT;
-        }
-        else if (0 >
-                 TALER_amount_add (&credit_total,
-                                   &credit_total,
-                                   &bank->amount))
-        {
-          GNUNET_break (0);
-          json_decref (json_history);
-          return NULL;
-        }
+
         if (0 !=
             json_array_append_new (
               json_history,
@@ -681,26 +648,7 @@ TEH_RESPONSE_compile_reserve_history (
       {
         const struct TALER_EXCHANGEDB_CollectableBlindcoin *withdraw
           = pos->details.withdraw;
-        struct TALER_Amount value;
 
-        value = withdraw->amount_with_fee;
-        if (0 == (IA_WITHDRAW & init))
-        {
-          withdraw_total = value;
-          init |= IA_WITHDRAW;
-        }
-        else
-        {
-          if (0 >
-              TALER_amount_add (&withdraw_total,
-                                &withdraw_total,
-                                &value))
-          {
-            GNUNET_break (0);
-            json_decref (json_history);
-            return NULL;
-          }
-        }
         if (0 !=
             json_array_append_new (
               json_history,
@@ -716,7 +664,7 @@ TEH_RESPONSE_compile_reserve_history (
                 TALER_JSON_pack_amount ("withdraw_fee",
                                         &withdraw->withdraw_fee),
                 TALER_JSON_pack_amount ("amount",
-                                        &value))))
+                                        &withdraw->amount_with_fee))))
         {
           GNUNET_break (0);
           json_decref (json_history);
@@ -731,20 +679,6 @@ TEH_RESPONSE_compile_reserve_history (
         struct TALER_ExchangePublicKeyP pub;
         struct TALER_ExchangeSignatureP sig;
 
-        if (0 == (IA_CREDIT & init))
-        {
-          credit_total = recoup->value;
-          init |= IA_CREDIT;
-        }
-        else if (0 >
-                 TALER_amount_add (&credit_total,
-                                   &credit_total,
-                                   &recoup->value))
-        {
-          GNUNET_break (0);
-          json_decref (json_history);
-          return NULL;
-        }
         {
           struct TALER_RecoupConfirmationPS pc = {
             .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
@@ -796,26 +730,7 @@ TEH_RESPONSE_compile_reserve_history (
           pos->details.closing;
         struct TALER_ExchangePublicKeyP pub;
         struct TALER_ExchangeSignatureP sig;
-        struct TALER_Amount value;
 
-        value = closing->amount;
-        if (0 == (IA_WITHDRAW & init))
-        {
-          withdraw_total = value;
-          init |= IA_WITHDRAW;
-        }
-        else
-        {
-          if (0 >
-              TALER_amount_add (&withdraw_total,
-                                &withdraw_total,
-                                &value))
-          {
-            GNUNET_break (0);
-            json_decref (json_history);
-            return NULL;
-          }
-        }
         {
           struct TALER_ReserveCloseConfirmationPS rcc = {
             .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
@@ -826,7 +741,7 @@ TEH_RESPONSE_compile_reserve_history (
           };
 
           TALER_amount_hton (&rcc.closing_amount,
-                             &value);
+                             &closing->amount);
           TALER_amount_hton (&rcc.closing_fee,
                              &closing->closing_fee);
           TALER_payto_hash (closing->receiver_account_details,
@@ -858,7 +773,7 @@ TEH_RESPONSE_compile_reserve_history (
                 GNUNET_JSON_pack_timestamp ("timestamp",
                                             closing->execution_date),
                 TALER_JSON_pack_amount ("amount",
-                                        &value),
+                                        &closing->amount),
                 TALER_JSON_pack_amount ("closing_fee",
                                         &closing->closing_fee))))
         {
@@ -871,31 +786,6 @@ TEH_RESPONSE_compile_reserve_history (
     }
   }
 
-  if (0 == (IA_CREDIT & init))
-  {
-    /* We should not have gotten here, without credits no reserve
-       should exist! */
-    GNUNET_break (0);
-    json_decref (json_history);
-    return NULL;
-  }
-  if (0 == (IA_WITHDRAW & init))
-  {
-    /* did not encounter any withdraw operations, set withdraw_total to zero */
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_set_zero (credit_total.currency,
-                                          &withdraw_total));
-  }
-  if (0 >
-      TALER_amount_subtract (balance,
-                             &credit_total,
-                             &withdraw_total))
-  {
-    GNUNET_break (0);
-    json_decref (json_history);
-    return NULL;
-  }
-
   return json_history;
 }
 
diff --git a/src/exchange/taler-exchange-httpd_responses.h 
b/src/exchange/taler-exchange-httpd_responses.h
index ffd2cc9e..03841e80 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -34,17 +34,14 @@
 
 
 /**
- * Compile the history of a reserve into a JSON object
- * and calculate the total balance.
+ * Compile the history of a reserve into a JSON object.
  *
  * @param rh reserve history to JSON-ify
- * @param[out] balance set to current reserve balance
  * @return json representation of the @a rh, NULL on error
  */
 json_t *
 TEH_RESPONSE_compile_reserve_history (
-  const struct TALER_EXCHANGEDB_ReserveHistory *rh,
-  struct TALER_Amount *balance);
+  const struct TALER_EXCHANGEDB_ReserveHistory *rh);
 
 
 /**
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c 
b/src/exchange/taler-exchange-httpd_withdraw.c
index fcf596e0..5765181b 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -52,32 +52,19 @@ reply_withdraw_insufficient_funds (
   const struct TALER_EXCHANGEDB_ReserveHistory *rh)
 {
   json_t *json_history;
-  struct TALER_Amount balance;
 
-  json_history = TEH_RESPONSE_compile_reserve_history (rh,
-                                                       &balance);
+  json_history = TEH_RESPONSE_compile_reserve_history (rh);
   if (NULL == json_history)
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        
TALER_EC_EXCHANGE_WITHDRAW_HISTORY_ERROR_INSUFFICIENT_FUNDS,
                                        NULL);
-  if (0 !=
-      TALER_amount_cmp (&balance,
-                        ebalance))
-  {
-    GNUNET_break (0);
-    json_decref (json_history);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
-                                       "reserve balance corrupt");
-  }
   return TALER_MHD_REPLY_JSON_PACK (
     connection,
     MHD_HTTP_CONFLICT,
     TALER_JSON_pack_ec (TALER_EC_EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS),
     TALER_JSON_pack_amount ("balance",
-                            &balance),
+                            ebalance),
     TALER_JSON_pack_amount ("requested_amount",
                             withdraw_amount),
     GNUNET_JSON_pack_array_steal ("history",
@@ -105,7 +92,6 @@ struct WithdrawContext
    */
   struct TALER_Amount amount_with_fee;
 
-
   /**
    * Blinded planchet.
    */
@@ -329,8 +315,8 @@ check_request_idempotent (struct TEH_RequestContext *rc,
 
 MHD_RESULT
 TEH_handler_withdraw (struct TEH_RequestContext *rc,
-                      const json_t *root,
-                      const char *const args[2])
+                      const struct TALER_ReservePublicKeyP *reserve_pub,
+                      const json_t *root)
 {
   struct WithdrawContext wc;
   struct GNUNET_JSON_Specification spec[] = {
@@ -348,18 +334,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
   memset (&wc,
           0,
           sizeof (wc));
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_string_to_data (args[0],
-                                     strlen (args[0]),
-                                     &wc.collectable.reserve_pub,
-                                     sizeof (wc.collectable.reserve_pub)))
-  {
-    GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (rc->connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       
TALER_EC_MERCHANT_GENERIC_RESERVE_PUB_MALFORMED,
-                                       args[0]);
-  }
+  wc.collectable.reserve_pub = *reserve_pub;
 
   {
     enum GNUNET_GenericReturnValue res;
diff --git a/src/exchange/taler-exchange-httpd_withdraw.h 
b/src/exchange/taler-exchange-httpd_withdraw.h
index 8d2d8c18..b754e64f 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.h
+++ b/src/exchange/taler-exchange-httpd_withdraw.h
@@ -28,8 +28,7 @@
 
 
 /**
- * Handle a "/reserves/$RESERVE_PUB/withdraw" request.  Parses the
- * "reserve_pub" EdDSA key of the reserve and the requested "denom_pub" which
+ * Handle a "/reserves/$RESERVE_PUB/withdraw" request.  Parses the the 
requested "denom_pub" which
  * specifies the key/value of the coin to be withdrawn, and checks that the
  * signature "reserve_sig" makes this a valid withdrawal request from the
  * specified reserve.  If so, the envelope with the blinded coin "coin_ev" is
@@ -37,13 +36,12 @@
  *
  * @param rc request context
  * @param root uploaded JSON data
- * @param args array of additional options (first must be the
- *         reserve public key, the second one should be "withdraw")
+ * @param reserve_pub public key of the reserve
  * @return MHD result code
   */
 MHD_RESULT
 TEH_handler_withdraw (struct TEH_RequestContext *rc,
-                      const json_t *root,
-                      const char *const args[2]);
+                      const struct TALER_ReservePublicKeyP *reserve_pub,
+                      const json_t *root);
 
 #endif
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index bb6f46f5..2856f300 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -732,6 +732,17 @@ prepare_statements (struct PostgresClosure *pg)
       " WHERE res.reserve_pub=$1;",
       1),
     /* Used in #postgres_select_withdrawals_above_serial_id() */
+
+    GNUNET_PQ_make_prepare (
+      "get_reserve_balance",
+      "SELECT"
+      " current_balance_val"
+      ",current_balance_frac"
+      " FROM reserves"
+      " WHERE reserve_pub=$1;",
+      1),
+    /* Fetch deposits with rowid '\geq' the given parameter */
+
     GNUNET_PQ_make_prepare (
       "audit_get_reserves_out_incr",
       "SELECT"
@@ -5533,6 +5544,37 @@ postgres_get_reserve_history (void *cls,
 }
 
 
+/**
+ * Get the balance of the specified reserve.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param[out] balance set to the reserve balance
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_get_reserve_balance (void *cls,
+                              const struct TALER_ReservePublicKeyP 
*reserve_pub,
+                              struct TALER_Amount *balance)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
+                                 balance),
+    GNUNET_PQ_result_spec_end
+  };
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_reserve_balance",
+                                                   params,
+                                                   rs);
+}
+
+
 /**
  * Check if we have the specified deposit already in the database.
  *
@@ -12503,6 +12545,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   plugin->do_refund = &postgres_do_refund;
   plugin->do_recoup = &postgres_do_recoup;
   plugin->do_recoup_refresh = &postgres_do_recoup_refresh;
+  plugin->get_reserve_balance = &postgres_get_reserve_balance;
   plugin->get_reserve_history = &postgres_get_reserve_history;
   plugin->free_reserve_history = &common_free_reserve_history;
   plugin->count_known_coins = &postgres_count_known_coins;
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index fc909a1b..610f2030 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -2846,6 +2846,20 @@ struct TALER_EXCHANGEDB_Plugin
                          struct TALER_EXCHANGEDB_ReserveHistory **rhp);
 
 
+  /**
+   * The current reserve balance of the specified reserve.
+   *
+   * @param cls the @e cls of this struct with the plugin-specific state
+   * @param reserve_pub public key of the reserve
+   * @param[out] balance set to the reserve balance
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_reserve_balance)(void *cls,
+                         const struct TALER_ReservePublicKeyP *reserve_pub,
+                         struct TALER_Amount *balance);
+
+
   /**
    * Free memory associated with the given reserve history.
    *

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