gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated (7045d3df -> 9ae46f36)


From: gnunet
Subject: [taler-exchange] branch master updated (7045d3df -> 9ae46f36)
Date: Sun, 17 Sep 2023 11:27:38 +0200

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

grothoff pushed a change to branch master
in repository exchange.

    from 7045d3df add triggers to populate reserve history table
     new 535c57b2 bump gana
     new 9ae46f36 first cut for API to get coin history

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 contrib/gana                                       |   2 +-
 src/auditor/taler-helper-auditor-aggregation.c     |   5 +
 src/auditor/taler-helper-auditor-coins.c           |   5 +
 src/exchange/Makefile.am                           |   5 +-
 src/exchange/taler-exchange-httpd.c                |  53 +++++++-
 src/exchange/taler-exchange-httpd_coins_get.c      | 150 +++++++++++++++++++++
 ...rves_get.h => taler-exchange-httpd_coins_get.h} |  22 +--
 src/exchange/taler-exchange-httpd_keys.c           |  55 ++------
 src/exchange/taler-exchange-httpd_link.c           |  25 +---
 src/exchange/taler-exchange-httpd_link.h           |   4 +-
 src/exchange/taler-exchange-httpd_responses.c      |  30 +++++
 src/exchange/taler-exchange-httpd_responses.h      |  31 ++++-
 src/exchangedb/pg_get_coin_transactions.c          |   2 +
 src/exchangedb/pg_get_coin_transactions.h          |   9 +-
 src/exchangedb/test_exchangedb.c                   |  13 +-
 src/include/taler_exchangedb_plugin.h              |   6 +
 16 files changed, 334 insertions(+), 83 deletions(-)
 create mode 100644 src/exchange/taler-exchange-httpd_coins_get.c
 copy src/exchange/{taler-exchange-httpd_reserves_get.h => 
taler-exchange-httpd_coins_get.h} (67%)

diff --git a/contrib/gana b/contrib/gana
index c9bda218..45da8072 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit c9bda21875ea1775f88b71de735d527132e45922
+Subproject commit 45da8072036c16d1f7cd39f85d8e293069ab6482
diff --git a/src/auditor/taler-helper-auditor-aggregation.c 
b/src/auditor/taler-helper-auditor-aggregation.c
index 72498ee0..81892c16 100644
--- a/src/auditor/taler-helper-auditor-aggregation.c
+++ b/src/auditor/taler-helper-auditor-aggregation.c
@@ -767,6 +767,7 @@ wire_transfer_information_cb (
   struct TALER_CoinPublicInfo coin;
   enum GNUNET_DB_QueryStatus qs;
   struct TALER_PaytoHashP hpt;
+  uint64_t etag = 0;
 
   TALER_payto_hash (account_pay_uri,
                     &hpt);
@@ -779,8 +780,12 @@ wire_transfer_information_cb (
                               "h-payto does not match payto URI");
   }
   /* Obtain coin's transaction history */
+  /* TODO: could use 'etag' mechanism to only fetch transactions
+     we did not yet process, instead of going over them
+     again and again.*/
   qs = TALER_ARL_edb->get_coin_transactions (TALER_ARL_edb->cls,
                                              coin_pub,
+                                             &etag,
                                              &tl);
   if ( (qs < 0) ||
        (NULL == tl) )
diff --git a/src/auditor/taler-helper-auditor-coins.c 
b/src/auditor/taler-helper-auditor-coins.c
index bfdc11c7..8c3d66b9 100644
--- a/src/auditor/taler-helper-auditor-coins.c
+++ b/src/auditor/taler-helper-auditor-coins.c
@@ -435,9 +435,14 @@ check_coin_history (const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
   struct TALER_Amount refunded;
   struct TALER_Amount deposit_fee;
   bool have_refund;
+  uint64_t etag = 0;
 
+  /* TODO: could use 'etag' mechanism to only fetch transactions
+     we did not yet process, instead of going over them
+     again and again. */
   qs = TALER_ARL_edb->get_coin_transactions (TALER_ARL_edb->cls,
                                              coin_pub,
+                                             &etag,
                                              &tl);
   if (0 >= qs)
     return qs;
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index 607ea919..dded2b1f 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -124,14 +124,15 @@ taler_exchange_wirewatch_LDADD = \
 
 taler_exchange_httpd_SOURCES = \
   taler-exchange-httpd.c taler-exchange-httpd.h \
+  taler-exchange-httpd_age-withdraw.c taler-exchange-httpd_age-withdraw.h \
+  taler-exchange-httpd_age-withdraw_reveal.c 
taler-exchange-httpd_age-withdraw_reveal.h \
   taler-exchange-httpd_auditors.c taler-exchange-httpd_auditors.h \
   taler-exchange-httpd_aml-decision.c taler-exchange-httpd_aml-decision.h \
   taler-exchange-httpd_aml-decision-get.c \
   taler-exchange-httpd_aml-decisions-get.c \
   taler-exchange-httpd_batch-deposit.c taler-exchange-httpd_batch-deposit.h \
   taler-exchange-httpd_batch-withdraw.c taler-exchange-httpd_batch-withdraw.h \
-  taler-exchange-httpd_age-withdraw.c taler-exchange-httpd_age-withdraw.h \
-  taler-exchange-httpd_age-withdraw_reveal.c 
taler-exchange-httpd_age-withdraw_reveal.h \
+  taler-exchange-httpd_coins_get.c taler-exchange-httpd_coins_get.h \
   taler-exchange-httpd_common_deposit.c taler-exchange-httpd_common_deposit.h \
   taler-exchange-httpd_common_kyc.c taler-exchange-httpd_common_kyc.h \
   taler-exchange-httpd_config.c taler-exchange-httpd_config.h \
diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index 149c60ca..ad4b50d2 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -36,6 +36,7 @@
 #include "taler-exchange-httpd_auditors.h"
 #include "taler-exchange-httpd_batch-deposit.h"
 #include "taler-exchange-httpd_batch-withdraw.h"
+#include "taler-exchange-httpd_coins_get.h"
 #include "taler-exchange-httpd_config.h"
 #include "taler-exchange-httpd_contract.h"
 #include "taler-exchange-httpd_csr.h"
@@ -368,6 +369,55 @@ handle_post_coins (struct TEH_RequestContext *rc,
 }
 
 
+/**
+ * Handle a GET "/coins/$COIN_PUB[/$OP]" request.  Parses the "coin_pub"
+ * EdDSA key of the coin 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_get_coins (struct TEH_RequestContext *rc,
+                  const char *const args[2])
+{
+  struct TALER_CoinSpendPublicKeyP coin_pub;
+
+  if (NULL == args[0])
+  {
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_NOT_FOUND,
+                                       TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+                                       rc->url);
+  }
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (args[0],
+                                     strlen (args[0]),
+                                     &coin_pub,
+                                     sizeof (coin_pub)))
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       
TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB,
+                                       args[0]);
+  }
+
+  if (NULL == args[1])
+    return TEH_handler_coins_get (rc,
+                                  &coin_pub);
+  if (0 == strcmp (args[1],
+                   "link"))
+    return TEH_handler_link (rc,
+                             &coin_pub);
+  return TALER_MHD_reply_with_error (rc->connection,
+                                     MHD_HTTP_NOT_FOUND,
+                                     TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+                                     rc->url);
+}
+
+
 /**
  * Signature of functions that handle operations
  * authorized by AML officers.
@@ -1537,8 +1587,9 @@ handle_mhd_request (void *cls,
     {
       .url = "coins",
       .method = MHD_HTTP_METHOD_GET,
-      .handler.get = TEH_handler_link,
+      .handler.get = &handle_get_coins,
       .nargs = 2,
+      .nargs_is_upper_bound = true
     },
     /* refreshes/$RCH/reveal */
     {
diff --git a/src/exchange/taler-exchange-httpd_coins_get.c 
b/src/exchange/taler-exchange-httpd_coins_get.c
new file mode 100644
index 00000000..f7f0409c
--- /dev/null
+++ b/src/exchange/taler-exchange-httpd_coins_get.c
@@ -0,0 +1,150 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2023 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_coins_get.c
+ * @brief Handle GET /coins/$COIN_PUB requests
+ * @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_coins_get.h"
+#include "taler-exchange-httpd_responses.h"
+
+
+/**
+ * Add the headers we want to set for every /keys response.
+ *
+ * @param cls the key state to use
+ * @param[in,out] response the response to modify
+ */
+static void
+add_response_headers (void *cls,
+                      struct MHD_Response *response)
+{
+  (void) cls;
+  TALER_MHD_add_global_headers (response);
+}
+
+
+MHD_RESULT
+TEH_handler_coins_get (struct TEH_RequestContext *rc,
+                       const struct TALER_CoinSpendPublicKeyP *coin_pub)
+{
+  enum GNUNET_DB_QueryStatus qs;
+  struct TALER_EXCHANGEDB_TransactionList *tl;
+  const char *etags;
+  uint64_t etag = 0;
+
+  etags = MHD_lookup_connection_value (rc->connection,
+                                       MHD_HEADER_KIND,
+                                       MHD_HTTP_HEADER_IF_NONE_MATCH);
+  if (NULL != etags)
+  {
+    char dummy;
+    unsigned long long ev;
+
+    if (1 != sscanf (etags,
+                     "%llu%c",
+                     &ev,
+                     &dummy))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Client send malformed `If-None-Match' header `%s'\n",
+                  etags);
+    }
+    else
+    {
+      etag = (uint64_t) ev;
+    }
+  }
+  qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
+                                          coin_pub,
+                                          &etag,
+                                          &tl);
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    GNUNET_break (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                       "get_coin_history");
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    GNUNET_break (0);   /* single-shot query should never have soft-errors */
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       TALER_EC_GENERIC_DB_SOFT_FAILURE,
+                                       "get_coin_history");
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    if (0 == etag)
+      return TALER_MHD_reply_with_error (rc->connection,
+                                         MHD_HTTP_NOT_FOUND,
+                                         
TALER_EC_EXCHANGE_GENERIC_COIN_UNKNOWN,
+                                         NULL);
+    return TEH_RESPONSE_reply_not_modified (rc->connection,
+                                            etags,
+                                            &add_response_headers,
+                                            NULL);
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    {
+      json_t *history;
+      char etagp[24];
+      MHD_RESULT ret;
+      struct MHD_Response *resp;
+
+      GNUNET_snprintf (etagp,
+                       sizeof (etagp),
+                       "%llu",
+                       (unsigned long long) etag);
+      history = TEH_RESPONSE_compile_transaction_history (coin_pub,
+                                                          tl);
+      TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
+                                              tl);
+      tl = NULL;
+      if (NULL == history)
+      {
+        GNUNET_break (0);
+        return TALER_MHD_reply_with_error (rc->connection,
+                                           MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                           
TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
+                                           "Failed to compile coin history");
+      }
+      resp = TALER_MHD_MAKE_JSON_PACK (
+        GNUNET_JSON_pack_array_steal ("history",
+                                      history));
+      GNUNET_break (MHD_YES ==
+                    MHD_add_response_header (resp,
+                                             MHD_HTTP_HEADER_ETAG,
+                                             etagp));
+      ret = MHD_queue_response (rc->connection,
+                                MHD_HTTP_OK,
+                                resp);
+      GNUNET_break (MHD_YES == ret);
+      MHD_destroy_response (resp);
+      return ret;
+    }
+  }
+  GNUNET_break (0);
+  return MHD_NO;
+}
+
+
+/* end of taler-exchange-httpd_coins_get.c */
diff --git a/src/exchange/taler-exchange-httpd_reserves_get.h 
b/src/exchange/taler-exchange-httpd_coins_get.h
similarity index 67%
copy from src/exchange/taler-exchange-httpd_reserves_get.h
copy to src/exchange/taler-exchange-httpd_coins_get.h
index 30c6559f..712269c3 100644
--- a/src/exchange/taler-exchange-httpd_reserves_get.h
+++ b/src/exchange/taler-exchange-httpd_coins_get.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2020 Taler Systems SA
+  Copyright (C) 2023 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
@@ -14,14 +14,14 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file taler-exchange-httpd_reserves_get.h
- * @brief Handle /reserves/$RESERVE_PUB GET requests
+ * @file taler-exchange-httpd_coins_get.h
+ * @brief Handle GET /coins/$COIN_PUB requests
  * @author Florian Dold
  * @author Benedikt Mueller
  * @author Christian Grothoff
  */
-#ifndef TALER_EXCHANGE_HTTPD_RESERVES_GET_H
-#define TALER_EXCHANGE_HTTPD_RESERVES_GET_H
+#ifndef TALER_EXCHANGE_HTTPD_COINS_GET_H
+#define TALER_EXCHANGE_HTTPD_COINS_GET_H
 
 #include <microhttpd.h>
 #include "taler-exchange-httpd.h"
@@ -37,17 +37,17 @@ TEH_reserves_get_cleanup (void);
 
 
 /**
- * Handle a GET "/reserves/" request.  Parses the
- * given "reserve_pub" in @a args (which should contain the
+ * Handle a GET "/coins/$COIN_PUB" request.  Parses the
+ * given "coins_pub" in @a args (which should contain the
  * EdDSA public key of a reserve) and then respond with the
- * status of the reserve.
+ * transaction history of the coin.
  *
  * @param rc request context
- * @param args array of additional options (length: 1, just the reserve_pub)
+ * @param coin_pub public key of the coin
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_reserves_get (struct TEH_RequestContext *rc,
-                          const char *const args[1]);
+TEH_handler_coins_get (struct TEH_RequestContext *rc,
+                       const struct TALER_CoinSpendPublicKeyP *coin_pub);
 
 #endif
diff --git a/src/exchange/taler-exchange-httpd_keys.c 
b/src/exchange/taler-exchange-httpd_keys.c
index 2389a21d..b9194d89 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -2317,16 +2317,14 @@ add_denom_key_cb (void *cls,
 /**
  * Add the headers we want to set for every /keys response.
  *
- * @param ksh the key state to use
- * @param wsh wire state to use
+ * @param cls the key state to use
  * @param[in,out] response the response to modify
- * @return #GNUNET_OK on success
  */
-static enum GNUNET_GenericReturnValue
-setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
-                                struct WireStateHandle *wsh,
+static void
+setup_general_response_headers (void *cls,
                                 struct MHD_Response *response)
 {
+  struct TEH_KeyStateHandle *ksh = cls;
   char dat[128];
 
   TALER_MHD_add_global_headers (response);
@@ -2352,7 +2350,7 @@ setup_general_response_headers (struct TEH_KeyStateHandle 
*ksh,
                                   ksh->rekey_frequency);
     a = GNUNET_TIME_relative_to_absolute (r);
     km = GNUNET_TIME_absolute_to_timestamp (a);
-    we = GNUNET_TIME_absolute_to_timestamp (wsh->cache_expiration);
+    we = GNUNET_TIME_absolute_to_timestamp (wire_state->cache_expiration);
     m = GNUNET_TIME_timestamp_min (we,
                                    km);
     TALER_MHD_get_date_string (m.abs_time,
@@ -2380,7 +2378,6 @@ setup_general_response_headers (struct TEH_KeyStateHandle 
*ksh,
                 MHD_add_response_header (response,
                                          MHD_HTTP_HEADER_CACHE_CONTROL,
                                          "public,max-age=3600"));
-  return GNUNET_OK;
 }
 
 
@@ -2688,10 +2685,8 @@ create_krd (struct TEH_KeyStateHandle *ksh,
                                          keys_json,
                                          MHD_RESPMEM_MUST_FREE);
     GNUNET_assert (NULL != krd.response_uncompressed);
-    GNUNET_assert (GNUNET_OK ==
-                   setup_general_response_headers (ksh,
-                                                   wsh,
-                                                   krd.response_uncompressed));
+    setup_general_response_headers (ksh,
+                                    krd.response_uncompressed);
     GNUNET_break (MHD_YES ==
                   MHD_add_response_header (krd.response_uncompressed,
                                            MHD_HTTP_HEADER_ETAG,
@@ -2711,10 +2706,8 @@ create_krd (struct TEH_KeyStateHandle *ksh,
                      MHD_add_response_header (krd.response_compressed,
                                               MHD_HTTP_HEADER_CONTENT_ENCODING,
                                               "deflate")) );
-    GNUNET_assert (GNUNET_OK ==
-                   setup_general_response_headers (ksh,
-                                                   wsh,
-                                                   krd.response_compressed));
+    setup_general_response_headers (ksh,
+                                    krd.response_compressed);
     /* Set cache control headers: our response varies depending on these 
headers */
     GNUNET_break (MHD_YES ==
                   MHD_add_response_header (wsh->wire_reply,
@@ -3877,9 +3870,7 @@ TEH_keys_get_handler (struct TEH_RequestContext *rc,
 {
   struct GNUNET_TIME_Timestamp last_issue_date;
   const char *etag;
-  struct WireStateHandle *wsh;
 
-  wsh = get_wire_state ();
   etag = MHD_lookup_connection_value (rc->connection,
                                       MHD_HEADER_KIND,
                                       MHD_HTTP_HEADER_IF_NONE_MATCH);
@@ -3967,29 +3958,11 @@ TEH_keys_get_handler (struct TEH_RequestContext *rc,
     if ( (NULL != etag) &&
          (0 == strcmp (etag,
                        krd->etag)) )
-    {
-      MHD_RESULT ret;
-      struct MHD_Response *resp;
-
-      resp = MHD_create_response_from_buffer (0,
-                                              NULL,
-                                              MHD_RESPMEM_PERSISTENT);
-      TALER_MHD_add_global_headers (resp);
-      GNUNET_break (GNUNET_OK ==
-                    setup_general_response_headers (ksh,
-                                                    wsh,
-                                                    resp));
-      GNUNET_break (MHD_YES ==
-                    MHD_add_response_header (resp,
-                                             MHD_HTTP_HEADER_ETAG,
-                                             krd->etag));
-      ret = MHD_queue_response (rc->connection,
-                                MHD_HTTP_NOT_MODIFIED,
-                                resp);
-      GNUNET_break (MHD_YES == ret);
-      MHD_destroy_response (resp);
-      return ret;
-    }
+      return TEH_RESPONSE_reply_not_modified (rc->connection,
+                                              krd->etag,
+                                              &setup_general_response_headers,
+                                              ksh);
+
     return MHD_queue_response (rc->connection,
                                MHD_HTTP_OK,
                                (MHD_YES ==
diff --git a/src/exchange/taler-exchange-httpd_link.c 
b/src/exchange/taler-exchange-httpd_link.c
index 9b7e297b..3d92a11a 100644
--- a/src/exchange/taler-exchange-httpd_link.c
+++ b/src/exchange/taler-exchange-httpd_link.c
@@ -39,7 +39,7 @@ struct HTD_Context
   /**
    * Public key of the coin for which we are running link.
    */
-  struct TALER_CoinSpendPublicKeyP coin_pub;
+  const struct TALER_CoinSpendPublicKeyP *coin_pub;
 
   /**
    * Json array with transfer data we collect.
@@ -153,7 +153,7 @@ link_transaction (void *cls,
   enum GNUNET_DB_QueryStatus qs;
 
   qs = TEH_plugin->get_link_data (TEH_plugin->cls,
-                                  &ctx->coin_pub,
+                                  ctx->coin_pub,
                                   &handle_link_data,
                                   ctx);
   if (NULL == ctx->mlist)
@@ -178,26 +178,13 @@ link_transaction (void *cls,
 
 MHD_RESULT
 TEH_handler_link (struct TEH_RequestContext *rc,
-                  const char *const args[2])
+                  const struct TALER_CoinSpendPublicKeyP *coin_pub)
 {
-  struct HTD_Context ctx;
+  struct HTD_Context ctx = {
+    .coin_pub = coin_pub
+  };
   MHD_RESULT mhd_ret;
 
-  memset (&ctx,
-          0,
-          sizeof (ctx));
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_string_to_data (args[0],
-                                     strlen (args[0]),
-                                     &ctx.coin_pub,
-                                     sizeof (ctx.coin_pub)))
-  {
-    GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (rc->connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       
TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB,
-                                       args[0]);
-  }
   ctx.mlist = json_array ();
   GNUNET_assert (NULL != ctx.mlist);
   if (GNUNET_OK !=
diff --git a/src/exchange/taler-exchange-httpd_link.h 
b/src/exchange/taler-exchange-httpd_link.h
index 01679e87..255c0ca5 100644
--- a/src/exchange/taler-exchange-httpd_link.h
+++ b/src/exchange/taler-exchange-httpd_link.h
@@ -32,12 +32,12 @@
  * Handle a "/coins/$COIN_PUB/link" request.
  *
  * @param rc request context
- * @param args array of additional options (length: 2, first is the coin_pub, 
second must be "link")
+ * @param coin_pub the coin public key
  * @return MHD result code
   */
 MHD_RESULT
 TEH_handler_link (struct TEH_RequestContext *rc,
-                  const char *const args[2]);
+                  const struct TALER_CoinSpendPublicKeyP *coin_pub);
 
 
 #endif
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 7d2d7a9b..5ae232c3 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -653,6 +653,7 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
   struct TALER_EXCHANGEDB_TransactionList *tl;
   enum GNUNET_DB_QueryStatus qs;
   json_t *history;
+  uint64_t etag = 0;
 
   TEH_plugin->rollback (TEH_plugin->cls);
   if (GNUNET_OK !=
@@ -667,6 +668,7 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
   }
   qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
                                           coin_pub,
+                                          &etag,
                                           &tl);
   TEH_plugin->rollback (TEH_plugin->cls);
   if (0 > qs)
@@ -1187,4 +1189,32 @@ TEH_RESPONSE_reply_aml_blocked (struct MHD_Connection 
*connection,
 }
 
 
+MHD_RESULT
+TEH_RESPONSE_reply_not_modified (
+  struct MHD_Connection *connection,
+  const char *etags,
+  TEH_RESPONSE_SetHeaders cb,
+  void *cb_cls)
+{
+  MHD_RESULT ret;
+  struct MHD_Response *resp;
+
+  resp = MHD_create_response_from_buffer (0,
+                                          NULL,
+                                          MHD_RESPMEM_PERSISTENT);
+  cb (cb_cls,
+      resp);
+  GNUNET_break (MHD_YES ==
+                MHD_add_response_header (resp,
+                                         MHD_HTTP_HEADER_ETAG,
+                                         etags));
+  ret = MHD_queue_response (connection,
+                            MHD_HTTP_NOT_MODIFIED,
+                            resp);
+  GNUNET_break (MHD_YES == ret);
+  MHD_destroy_response (resp);
+  return ret;
+}
+
+
 /* end of taler-exchange-httpd_responses.c */
diff --git a/src/exchange/taler-exchange-httpd_responses.h 
b/src/exchange/taler-exchange-httpd_responses.h
index a57fa495..9b525929 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
+  Copyright (C) 2014-2023 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
@@ -226,4 +226,33 @@ TEH_RESPONSE_compile_transaction_history (
   const struct TALER_EXCHANGEDB_TransactionList *tl);
 
 
+/**
+ * Callback used to set headers in a response.
+ *
+ * @param cls closure
+ * @param[in,out] resp response to modify
+ */
+typedef void
+(*TEH_RESPONSE_SetHeaders)(void *cls,
+                           struct MHD_Response *resp);
+
+
+/**
+ * Generate a HTTP "Not modified" response with the
+ * given @a etags.
+ *
+ * @param connection connection to queue response on
+ * @param etags ETag header to set
+ * @param cb callback to modify response headers
+ * @param cb_cls closure for @a cb
+ * @return MHD result code
+ */
+MHD_RESULT
+TEH_RESPONSE_reply_not_modified (
+  struct MHD_Connection *connection,
+  const char *etags,
+  TEH_RESPONSE_SetHeaders cb,
+  void *cb_cls);
+
+
 #endif
diff --git a/src/exchangedb/pg_get_coin_transactions.c 
b/src/exchangedb/pg_get_coin_transactions.c
index 4f431792..704e7c5c 100644
--- a/src/exchangedb/pg_get_coin_transactions.c
+++ b/src/exchangedb/pg_get_coin_transactions.c
@@ -684,6 +684,7 @@ enum GNUNET_DB_QueryStatus
 TEH_PG_get_coin_transactions (
   void *cls,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t *etag,
   struct TALER_EXCHANGEDB_TransactionList **tlp)
 {
   struct PostgresClosure *pg = cls;
@@ -729,6 +730,7 @@ TEH_PG_get_coin_transactions (
     .db_cls = cls
   };
 
+  *etag = 0;  // FIXME: etag not yet implemented!
   PREPARE (pg, // done!
            "get_deposit_with_coin_pub",
            "SELECT"
diff --git a/src/exchangedb/pg_get_coin_transactions.h 
b/src/exchangedb/pg_get_coin_transactions.h
index c95fd094..d49b97bc 100644
--- a/src/exchangedb/pg_get_coin_transactions.h
+++ b/src/exchangedb/pg_get_coin_transactions.h
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
+   Copyright (C) 2022, 2023 Taler Systems SA
 
    TALER is free software; you can redistribute it and/or modify it under the
    terms of the GNU General Public License as published by the Free Software
@@ -29,16 +29,21 @@
 /**
  * Compile a list of all (historic) transactions performed with the given coin
  * (/refresh/melt, /deposit, /refund and /recoup operations).
+ * Should return 0 if @a etag is already current, otherwise
+ * return the full history and update @a etag. @a etag
+ * should be set to the last row ID of the given coin
+ * in the coin history table.
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @param coin_pub coin to investigate
- * @param[out] tlp set to list of transactions, NULL if coin is fresh
+ * @param[in,out] etag known etag, updated to current etag * @param[out] tlp 
set to list of transactions, NULL if coin is fresh
  * @return database transaction status
  */
 enum GNUNET_DB_QueryStatus
 TEH_PG_get_coin_transactions (
   void *cls,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t *etag,
   struct TALER_EXCHANGEDB_TransactionList **tlp);
 
 #endif
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 56925acf..217df2bb 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -1723,9 +1723,11 @@ run (void *cls)
       /* Just to test fetching a coin with melt history */
       struct TALER_EXCHANGEDB_TransactionList *tl;
       enum GNUNET_DB_QueryStatus qs;
+      uint64_t etag = 0;
 
       qs = plugin->get_coin_transactions (plugin->cls,
                                           &refresh.coin.coin_pub,
+                                          &etag,
                                           &tl);
       FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs);
       plugin->free_coin_transaction_list (plugin->cls,
@@ -1972,9 +1974,14 @@ run (void *cls)
                                                   &audit_refund_cb,
                                                   NULL));
   FAILIF (1 != auditor_row_cnt);
-  qs = plugin->get_coin_transactions (plugin->cls,
-                                      &refund.coin.coin_pub,
-                                      &tl);
+  {
+    uint64_t etag = 0;
+
+    qs = plugin->get_coin_transactions (plugin->cls,
+                                        &refund.coin.coin_pub,
+                                        &etag,
+                                        &tl);
+  }
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs);
   GNUNET_assert (NULL != tl);
   matched = 0;
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index ee382ebe..8fd9ce19 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -4696,15 +4696,21 @@ struct TALER_EXCHANGEDB_Plugin
   /**
    * Compile a list of all (historic) transactions performed
    * with the given coin (melt, refund, recoup and deposit operations).
+   * Should return 0 if @a etag is already current, otherwise
+   * return the full history and update @a etag. @a etag
+   * should be set to the last row ID of the given coin
+   * in the coin history table.
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param coin_pub coin to investigate
+   * @param[in,out] etag known etag, updated to current etag
    * @param[out] tlp set to list of transactions, NULL if coin is fresh
    * @return database transaction status
    */
   enum GNUNET_DB_QueryStatus
   (*get_coin_transactions)(void *cls,
                            const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                           uint64_t *etag,
                            struct TALER_EXCHANGEDB_TransactionList **tlp);
 
 

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