gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated (6b6417b1 -> 602093e


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated (6b6417b1 -> 602093e9)
Date: Mon, 08 Apr 2019 02:44:32 +0200

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

marcello pushed a change to branch master
in repository exchange.

    from 6b6417b1 doc/taler-exchange.texi: Fix build with older Texinfo 
versions.
     new eca27d9d Finish abstract history builder.
     new 3c66bb30 Gather /history implementation(s) in one point.
     new ddb8cdfa Finishing /history-range implementation, untested.
     new 704e0913 Fix compilation warnings, + enable polymorphic /history 
handler.
     new e24e845b debug message
     new 9fc380f7 Set range pointer.
     new e13a8902 Put /history[-range] logic in a dedicate file.
     new 602093e9 notes

The 8 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:
 .gitignore                                |   1 +
 src/bank-lib/Makefile.am                  |   1 +
 src/bank-lib/fakebank.c                   | 867 ++----------------------------
 src/bank-lib/fakebank.h                   | 322 +++++++++++
 src/bank-lib/fakebank_history.c           | 427 +++++++++++++++
 src/exchange-tools/taler-exchange-keyup.c |   7 +-
 6 files changed, 803 insertions(+), 822 deletions(-)
 create mode 100644 src/bank-lib/fakebank.h
 create mode 100644 src/bank-lib/fakebank_history.c

diff --git a/.gitignore b/.gitignore
index 8696558d..6f7a0258 100644
--- a/.gitignore
+++ b/.gitignore
@@ -115,3 +115,4 @@ src/bank-lib/test_bank_api_twisted
 src/lib/test_exchange_api_new
 src/lib/test_auditor_api
 src/lib/test_exchange_api_overlapping_keys_bug
+src/lib/test_exchange_api_home/.local/share/taler/exchange/revocations/
diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am
index e6e2e878..ddc4cf4b 100644
--- a/src/bank-lib/Makefile.am
+++ b/src/bank-lib/Makefile.am
@@ -57,6 +57,7 @@ libtalerfakebank_la_LDFLAGS = \
   -no-undefined
 
 libtalerfakebank_la_SOURCES = \
+  fakebank_history.c \
   fakebank.c
 
 libtalerfakebank_la_LIBADD = \
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index 3eea5f8b..37aae042 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -25,6 +25,7 @@
 #include "platform.h"
 #include "taler_fakebank_lib.h"
 #include "taler_bank_service.h"
+#include "fakebank.h"
 
 /**
  * Maximum POST request size (for /admin/add/incoming)
@@ -33,170 +34,6 @@
 
 
 /**
- * Parse URL arguments of a /history[-range] HTTP request.
- *
- * @param connection MHD connection object.
- * @param ha @a HistoryArgs structure.
- */
-#define PARSE_HISTORY_ARGS(connection, ha) \
-  parse_history_args_ (connection, ha, __FUNCTION__)
-
-/**
- * Details about a transcation we (as the simulated bank) received.
- */
-struct Transaction
-{
-
-  /**
-   * We store transactions in a DLL.
-   */
-  struct Transaction *next;
-
-  /**
-   * We store transactions in a DLL.
-   */
-  struct Transaction *prev;
-
-  /**
-   * Amount to be transferred.
-   */
-  struct TALER_Amount amount;
-
-  /**
-   * Account to debit.
-   */
-  uint64_t debit_account;
-
-  /**
-   * Account to credit.
-   */
-  uint64_t credit_account;
-
-  /**
-   * Subject of the transfer.
-   */
-  char *subject;
-
-  /**
-   * Base URL of the exchange.
-   */
-  char *exchange_base_url;
-
-  /**
-   * When did the transaction happen?
-   */
-  struct GNUNET_TIME_Absolute date;
-
-  /**
-   * Number of this transaction.
-   */
-  uint64_t row_id;
-
-  /**
-   * Flag set if the transfer was rejected.
-   */
-  int rejected;
-
-  /**
-   * Has this transaction been subjected to #TALER_FAKEBANK_check()
-   * and should thus no longer be counted in
-   * #TALER_FAKEBANK_check_empty()?
-   */
-  int checked;
-};
-
-
-/**
- * Needed to implement ascending/descending ordering
- * of /history results.
- */
-struct HistoryElement
-{
-
-  /**
-   * History JSON element.
-   */
-  json_t *element;
-
-  /**
-   * Previous element.
-   */
-  struct HistoryElement *prev;
-
-  /**
-   * Next element.
-   */
-  struct HistoryElement *next;
-};
-
-
-/**
- * Values to implement the "/history-range" range.
- */
-struct HistoryRangeDates
-{
-  /**
-   * Oldest row in the results.
-   */
-  struct GNUNET_TIME_Absolute start;
-
-  /**
-   * Youngest row in the results.
-   */
-  struct GNUNET_TIME_Absolute end;
-};
-
-/**
- * Values to implement the "/history" range.
- */
-struct HistoryRangeIds
-{
-
-  /**
-   * (Exclusive) row ID for the result set.
-   */
-  unsigned long long start;
-
-  /**
-   * How many transactions we want in the result set.  If
-   * negative/positive, @a start will be strictly younger/older
-   * of any element in the result set.
-   */
-  long long count;
-};
-
-
-/**
- * This is the "base" structure for both the /history and the
- * /history-range API calls.
- */
-struct HistoryArgs
-{
-
-  /**
-   * Direction asked by the client: CREDIT / DEBIT / BOTH / CANCEL.
-   */
-  enum TALER_BANK_Direction direction;
-
-  /**
-   * Bank account number of the requesting client.
-   */
-  unsigned long long account_number;
-
-  /**
-   * Ordering of the results.
-   */
-  unsigned int ascending;
-
-  /**
-   * Overloaded type that indicates the "range" to be returned
-   * in the results; this can be either a date range, or a
-   * starting row id + the count.
-   */
-  void *range;
-};
-
-/**
  * Handle for the fake bank.
  */
 struct TALER_FAKEBANK_Handle
@@ -239,17 +76,6 @@ struct TALER_FAKEBANK_Handle
 #endif
 };
 
-typedef int (*CheckAdvance)(const struct HistoryArgs *ha,
-                            struct Transaction *pos);
-
-typedef struct Transaction * (*Step)
-  (const struct HistoryArgs *ha,
-   const struct Transaction *pos);
-
-typedef struct Transaction * (*Skip)
-  (const struct HistoryArgs *ha,
-   const struct Transaction *pos);
-
 
 /**
  * Check that the @a want_amount was transferred from
@@ -742,10 +568,11 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
   json_decref (json);
 
   if (GNUNET_OK != found)
-    return create_bank_error (connection,
-                              MHD_HTTP_NOT_FOUND,
-                              TALER_EC_BANK_REJECT_TRANSACTION_NOT_FOUND,
-                              "transaction unknown");
+    return create_bank_error
+      (connection,
+       MHD_HTTP_NOT_FOUND,
+       TALER_EC_BANK_REJECT_TRANSACTION_NOT_FOUND,
+       "transaction unknown");
   /* finally build regular response */
   resp = MHD_create_response_from_buffer (0,
                                           NULL,
@@ -757,128 +584,6 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
   return ret;
 }
 
-
-/**
- * Parse URL history arguments, of _both_ APIs:
- * /history and /history-range.
- *
- * @param connection MHD connection.
- * @param function_name name of the caller.
- * @param ha[out] will contain the parsed values.
- * @return GNUNET_OK only if the parsing succeedes.
- */
-static int
-parse_history_common_args (struct MHD_Connection *connection,
-                           struct HistoryArgs *ha)
-{
-  /**
-   * @variable
-   * Just check if given and == "basic", no need to keep around.
-   */
-  const char *auth;
-
-  /**
-   * All those will go into the structure, after parsing.
-   */
-  const char *direction;
-  const char *cancelled;
-  const char *ordering;
-  const char *account_number;
-
-
-  auth = MHD_lookup_connection_value (connection,
-                                      MHD_GET_ARGUMENT_KIND,
-                                      "auth");
-  direction = MHD_lookup_connection_value (connection,
-                                           MHD_GET_ARGUMENT_KIND,
-                                           "direction");
-  cancelled = MHD_lookup_connection_value (connection,
-                                           MHD_GET_ARGUMENT_KIND,
-                                           "cancelled");
-  ordering = MHD_lookup_connection_value (connection,
-                                          MHD_GET_ARGUMENT_KIND,
-                                          "ordering");
-  account_number = MHD_lookup_connection_value
-    (connection,
-     MHD_GET_ARGUMENT_KIND,
-     "account_number");
-
-  /* Fail if one of the above failed.  */
-  if ( (NULL == direction) ||
-       (NULL == cancelled) ||
-       ( (0 != strcasecmp (cancelled,
-                           "OMIT")) &&
-         (0 != strcasecmp (cancelled,
-                           "SHOW")) ) ||
-       ( (0 != strcasecmp (direction,
-                           "BOTH")) &&
-         (0 != strcasecmp (direction,
-                           "CREDIT")) &&
-         (0 != strcasecmp (direction,
-                           "DEBIT")) ) ||
-         (1 != sscanf (account_number,
-                       "%llu",
-                       &ha->account_number)) ||
-         ( (NULL == auth) || (0 != strcasecmp (auth,
-                                               "basic")) ) )
-  {
-    /* Invalid request, given that this is fakebank we impolitely
-     * just kill the connection instead of returning a nice error.
-     */
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-
-  if (0 == strcasecmp (direction,
-                       "CREDIT"))
-  {
-    ha->direction = TALER_BANK_DIRECTION_CREDIT;
-  }
-  else if (0 == strcasecmp (direction,
-                            "DEBIT"))
-  {
-    ha->direction = TALER_BANK_DIRECTION_DEBIT;
-  }
-  else if (0 == strcasecmp (direction,
-                            "BOTH"))
-  {
-    ha->direction = TALER_BANK_DIRECTION_BOTH;
-  }
-
-  /* Direction is invalid.  */
-  else
-  {
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-
-  if (0 == strcasecmp (cancelled,
-                       "OMIT"))
-  {
-    /* nothing */
-  } else if (0 == strcasecmp (cancelled,
-                              "SHOW"))
-  {
-    ha->direction |= TALER_BANK_DIRECTION_CANCEL;
-  }
-
-  /* Cancel-showing policy is invalid.  */
-  else
-  {
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-
-  if ((NULL != ordering)
-      && 0 == strcmp ("ascending",
-                      ordering))
-    ha->ascending = GNUNET_YES;
-  else
-    ha->ascending = GNUNET_NO;
-
-  return GNUNET_OK;
-}
-
 /**
  * Handle incoming HTTP request for /history
  *
@@ -898,8 +603,8 @@ handle_history_new (struct TALER_FAKEBANK_Handle *h,
   const char *delta;
   struct Transaction *pos;
 
-  if (GNUNET_OK != parse_history_common_args (connection,
-                                              &ha))
+  if (GNUNET_OK != TFH_parse_history_common_args (connection,
+                                                  &ha))
   {
     GNUNET_break (0);
     return MHD_NO;
@@ -921,6 +626,7 @@ handle_history_new (struct TALER_FAKEBANK_Handle *h,
     GNUNET_break (0);
     return MHD_NO;
   }
+  ha.range = &hri;
 
   if (NULL == start)
     pos = 0 > hri.count ?
@@ -952,7 +658,15 @@ handle_history_new (struct TALER_FAKEBANK_Handle *h,
     /* list is empty */
     pos = NULL;
   }
-
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "/history, start row (0 == no transactions exist): %llu\n",
+              NULL != pos ? pos->row_id : 0);
+  return TFH_build_history_response (connection,
+                                     pos,
+                                     &ha,
+                                     &TFH_handle_history_skip,
+                                     &TFH_handle_history_step,
+                                     &TFH_handle_history_advance);
 }
 
 /**
@@ -968,15 +682,15 @@ handle_history_range (struct TALER_FAKEBANK_Handle *h,
                       struct MHD_Connection *connection,
                       void **con_cls)
 {
-
   struct HistoryArgs ha;
   struct HistoryRangeDates hrd;
   const char *start;
   const char *end;
   long long unsigned int start_stamp; 
   long long unsigned int end_stamp; 
+  struct Transaction *pos;
 
-  if (GNUNET_OK != parse_history_common_args (connection,
+  if (GNUNET_OK != TFH_parse_history_common_args (connection,
                                               &ha))
   {
     GNUNET_break (0);
@@ -997,522 +711,30 @@ handle_history_range (struct TALER_FAKEBANK_Handle *h,
                                    &end_stamp)) )
   {
     GNUNET_break (0);
-    return GNUNET_NO;
+    return MHD_NO;
   }
 
   hrd.start.abs_value_us = start_stamp * 1000LL * 1000LL;
   hrd.end.abs_value_us = end_stamp * 1000LL * 1000LL;
+  ha.range = &hrd;
+
+  pos = NULL;
+  /* hunt for 'pos' in the Transaction(s) LL.  */
+  for (pos = h->transactions_head;
+       NULL != pos;
+       pos = pos->next)
+  {
+    if (hrd.start.abs_value_us <= pos->date.abs_value_us)
+      break; 
+  }
+  return TFH_build_history_response (connection,
+                                     pos,
+                                     &ha,
+                                     &TFH_handle_history_range_skip,
+                                     TFH_handle_history_range_step,
+                                     &TFH_handle_history_range_advance);
 }
 
-
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-static int
-handle_history_advance (const struct HistoryArgs *ha,
-                        struct Transaction *pos)
-{
-  const struct HistoryRangeIds *hri = ha->range;
-
-  return (NULL != pos) && (0 != hri->count);
-}
-
-
-/**
- * Iterates on the "next" element to be processed.  To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-static struct Transaction *
-handle_history_skip (const struct HistoryArgs *ha,
-                     const struct Transaction *pos)
-{
-  const struct HistoryRangeIds *hri = ha->range;
-
-  if (hri->count > 0)
-    return pos->next;
-  if (hri->count < 0)
-    return pos->prev;
-}
-
-
-/**
- * Iterates on the "next" element to be processed.  To
- * be used when the current element _gets_ inserted in the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-static struct Transaction *
-handle_history_step (struct HistoryArgs *ha,
-                     const struct Transaction *pos)
-{
-  struct HistoryRangeIds *hri = ha->range;
-
-  if (hri->count > 0)
-  {
-    hri->count--;
-    return pos->next;
-  }
-  if (hri->count < 0)
-  {
-    hri->count++;
-    return pos->prev;
-  }
-}
-
-
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-static int
-handle_history_range_advance (const struct HistoryArgs *ha)
-{
-  const struct HistoryRangeDates *hrd = ha->range;
-}
-
-
-/**
- * Iterates towards the "next" element to be processed.  To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-static struct Transaction *
-handle_history_range_skip (const struct HistoryArgs *ha)
-{
-  const struct HistoryRangeDates *hrd = ha->range;
-}
-
-/**
- * Iterates on the "next" element to be processed.  To
- * be used when the current element _gets_ inserted in the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-static struct Transaction *
-handle_history_range_step (const struct HistoryArgs *ha)
-{
-  const struct HistoryRangeDates *hrd = ha->range;
-}
-
-/**
- * Actual history response builder.
- *
- * @param pos first (included) element in the result set.
- * @param ha history arguments.
- * @param caller_name which function is building the history.
- * @return MHD response object, or NULL if any error occurs.
- */
-static struct MHD_response *
-build_history_response (struct Transaction *pos,
-                        struct HistoryArgs *ha,
-                        Skip skip,
-                        Step step,
-                        CheckAdvance advance)
-{
-
-  struct HistoryElement *history_results_head = NULL;
-  struct HistoryElement *history_results_tail = NULL;
-  struct HistoryElement *history_element = NULL;
-
-  while (GNUNET_YES == advance (ha,
-                                pos))
-  {
-    json_t *trans;
-    char *subject;
-    const char *sign;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Found transaction over %s from %llu to %llu\n",
-                TALER_amount2s (&pos->amount),
-                (unsigned long long) pos->debit_account,
-                (unsigned long long) pos->credit_account);
-
-    if ( (! ( ( (ha->account_number == pos->debit_account) &&
-                (0 != (ha->direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
-              ( (ha->account_number == pos->credit_account) &&
-                (0 != (ha->direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) ) ||
-         ( (0 == (ha->direction & TALER_BANK_DIRECTION_CANCEL)) &&
-           (GNUNET_YES == pos->rejected) ) )
-    {
-      pos = skip (ha,
-                  pos);
-      continue;
-    }
-
-    GNUNET_asprintf (&subject,
-                     "%s %s",
-                     pos->subject,
-                     pos->exchange_base_url);
-    sign =
-      (ha->account_number == pos->debit_account)
-      ? (pos->rejected ? "cancel-" : "-")
-      : (pos->rejected ? "cancel+" : "+");
-    trans = json_pack
-      ("{s:I, s:o, s:o, s:s, s:I, s:s}",
-       "row_id", (json_int_t) pos->row_id,
-       "date", GNUNET_JSON_from_time_abs (pos->date),
-       "amount", TALER_JSON_from_amount (&pos->amount),
-       "sign", sign,
-       "counterpart", (json_int_t)
-         ( (ha->account_number == pos->debit_account)
-            ? pos->credit_account
-            : pos->debit_account),
-       "wt_subject", subject);
-    GNUNET_assert (NULL != trans);
-    GNUNET_free (subject);
-
-    history_element = GNUNET_new (struct HistoryElement);
-    history_element->element = trans;
-
-
-    /* XXX: the ordering feature is missing.  */
-
-    GNUNET_CONTAINER_DLL_insert_tail (history_results_head,
-                                      history_results_tail,
-                                      history_element);
-    pos = step (ha, pos);
-  }
-}
-
-
-/**
- * Handle incoming HTTP request for /history
- *
- * @param h the fakebank handle
- * @param connection the connection
- * @param con_cls place to store state, not used
- * @return MHD result code
- */
-static int
-handle_history (struct TALER_FAKEBANK_Handle *h,
-                struct MHD_Connection *connection,
-                void **con_cls)
-{
-  const char *auth;
-  const char *delta;
-  const char *start;
-  const char *dir;
-  const char *acc;
-  const char *cancelled;
-  const char *ordering;
-  unsigned long long account_number;
-  unsigned long long start_number;
-  long long count;
-  enum TALER_BANK_Direction direction;
-  struct Transaction *pos;
-  json_t *history;
-  json_t *jresponse;
-  int ret;
-  int ascending;
-  struct HistoryElement *history_results_head = NULL;
-  struct HistoryElement *history_results_tail = NULL;
-  struct HistoryElement *history_element = NULL;
-
-  auth = MHD_lookup_connection_value (connection,
-                                      MHD_GET_ARGUMENT_KIND,
-                                      "auth");
-  delta = MHD_lookup_connection_value (connection,
-                                       MHD_GET_ARGUMENT_KIND,
-                                       "delta");
-  dir = MHD_lookup_connection_value (connection,
-                                     MHD_GET_ARGUMENT_KIND,
-                                     "direction");
-  cancelled = MHD_lookup_connection_value (connection,
-                                           MHD_GET_ARGUMENT_KIND,
-                                           "cancelled");
-  start = MHD_lookup_connection_value (connection,
-                                       MHD_GET_ARGUMENT_KIND,
-                                       "start");
-  ordering = MHD_lookup_connection_value (connection,
-                                          MHD_GET_ARGUMENT_KIND,
-                                          "ordering");
-  acc = MHD_lookup_connection_value (connection,
-                                     MHD_GET_ARGUMENT_KIND,
-                                     "account_number");
-  if ( (NULL == auth) ||
-       (0 != strcasecmp (auth,
-                         "basic")) ||
-       (NULL == acc) ||
-       (NULL == delta) )
-  {
-    /* Invalid request, given that this is fakebank we impolitely just
-       kill the connection instead of returning a nice error. */
-    GNUNET_break (0);
-    return MHD_NO;
-  }
-  start_number = 0;
-  if ( (1 != sscanf (delta,
-                     "%lld",
-                     &count)) ||
-       (1 != sscanf (acc,
-                     "%llu",
-                     &account_number)) ||
-       ( (NULL != start) &&
-         (1 != sscanf (start,
-                       "%llu",
-                       &start_number)) ) ||
-       (NULL == dir) ||
-       (NULL == cancelled) ||
-       ( (0 != strcasecmp (cancelled,
-                           "OMIT")) &&
-         (0 != strcasecmp (cancelled,
-                           "SHOW")) ) ||
-       ( (0 != strcasecmp (dir,
-                           "BOTH")) &&
-         (0 != strcasecmp (dir,
-                           "CREDIT")) &&
-         (0 != strcasecmp (dir,
-                           "DEBIT")) ) )
-  {
-    /* Invalid request, given that this is fakebank we impolitely
-     * just kill the connection instead of returning a nice error.
-     */
-    GNUNET_break (0);
-    return MHD_NO;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Client asked for up to %lld results of type %s for account %llu 
starting at %llu\n",
-              count,
-              dir,
-              (unsigned long long) account_number,
-              start_number);
-  if (0 == strcasecmp (dir,
-                       "CREDIT"))
-  {
-    direction = TALER_BANK_DIRECTION_CREDIT;
-  }
-  else if (0 == strcasecmp (dir,
-                            "DEBIT"))
-  {
-    direction = TALER_BANK_DIRECTION_DEBIT;
-  }
-  else if (0 == strcasecmp (dir,
-                            "BOTH"))
-  {
-    direction = TALER_BANK_DIRECTION_BOTH;
-  }
-  else
-  {
-    GNUNET_assert (0);
-    return MHD_NO;
-  }
-  if (0 == strcasecmp (cancelled,
-                       "OMIT"))
-  {
-    /* nothing */
-  } else if (0 == strcasecmp (cancelled,
-                              "SHOW"))
-  {
-    direction |= TALER_BANK_DIRECTION_CANCEL;
-  }
-  else
-  {
-    GNUNET_assert (0);
-    return MHD_NO;
-  }
-
-  if (NULL == start)
-    pos = 0 > count ? h->transactions_tail : h->transactions_head;
-
-  else if (NULL != h->transactions_head)
-  {
-    for (pos = h->transactions_head;
-         NULL != pos;
-         pos = pos->next)
-      if (pos->row_id  == start_number)
-        break;
-    if (NULL == pos)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Invalid range specified, transaction %llu not known!\n",
-                  (unsigned long long) start_number);
-      return MHD_NO;
-    }
-    /* range is exclusive, skip the matching entry */
-    if (count > 0)
-      pos = pos->next;
-    if (count < 0)
-      pos = pos->prev;
-  }
-  else
-  {
-    /* list is empty */
-    pos = NULL;
-  }
-
-  history = json_array ();
-  if ((NULL != ordering)
-      && 0 == strcmp ("ascending",
-                      ordering))
-    ascending = GNUNET_YES;
-  else
-    ascending = GNUNET_NO;
-
-  while ( (NULL != pos) &&
-          (0 != count) )
-  {
-    json_t *trans;
-    char *subject;
-    const char *sign;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Found transaction over %s from %llu to %llu\n",
-                TALER_amount2s (&pos->amount),
-                (unsigned long long) pos->debit_account,
-                (unsigned long long) pos->credit_account);
-
-    if ( (! ( ( (account_number == pos->debit_account) &&
-                (0 != (direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
-              ( (account_number == pos->credit_account) &&
-                (0 != (direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) ) ||
-         ( (0 == (direction & TALER_BANK_DIRECTION_CANCEL)) &&
-           (GNUNET_YES == pos->rejected) ) )
-    {
-      if (count > 0)
-        pos = pos->next;
-      if (count < 0)
-        pos = pos->prev;
-      continue;
-    }
-
-    GNUNET_asprintf (&subject,
-                     "%s %s",
-                     pos->subject,
-                     pos->exchange_base_url);
-    sign =
-      (account_number == pos->debit_account)
-      ? (pos->rejected ? "cancel-" : "-")
-      : (pos->rejected ? "cancel+" : "+");
-    trans = json_pack ("{s:I, s:o, s:o, s:s, s:I, s:s}",
-                       "row_id", (json_int_t) pos->row_id,
-                       "date", GNUNET_JSON_from_time_abs (pos->date),
-                       "amount", TALER_JSON_from_amount (&pos->amount),
-                       "sign", sign,
-                       "counterpart", (json_int_t) ( (account_number == 
pos->debit_account)
-                                                     ? pos->credit_account
-                                                     : pos->debit_account),
-                       "wt_subject", subject);
-    GNUNET_assert (NULL != trans);
-    GNUNET_free (subject);
-
-    history_element = GNUNET_new (struct HistoryElement);
-    history_element->element = trans;
-
-    if (((0 < count) && (GNUNET_YES == ascending))
-      || ((0 > count) && (GNUNET_NO == ascending)))
-    GNUNET_CONTAINER_DLL_insert_tail (history_results_head,
-                                      history_results_tail,
-                                      history_element);
-    else
-      GNUNET_CONTAINER_DLL_insert (history_results_head,
-                                   history_results_tail,
-                                   history_element);
-    if (count > 0)
-    {
-      pos = pos->next;
-      count--;
-    }
-    if (count < 0)
-    {
-      pos = pos->prev;
-      count++;
-    }
-  }
-
-  if (NULL != history_results_head)
-    history_element = history_results_head;
-  while (NULL != history_element)
-  {
-    json_array_append_new (history,
-                           history_element->element);
-    history_element = history_element->next;
-    if (NULL != history_element)
-      GNUNET_free_non_null (history_element->prev);
-  }
-  GNUNET_free_non_null (history_results_tail);
-
-  if (0 == json_array_size (history))
-  {
-    struct MHD_Response *resp;
-
-    json_decref (history);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Returning empty transaction history\n");
-    resp = MHD_create_response_from_buffer (0,
-                                            "",
-                                            MHD_RESPMEM_PERSISTENT);
-    ret = MHD_queue_response (connection,
-                              MHD_HTTP_NO_CONTENT,
-                              resp);
-    MHD_destroy_response (resp);
-    return ret;
-  }
-
-  jresponse = json_pack ("{s:o}",
-                         "data",
-                         history);
-  if (NULL == jresponse)
-  {
-    GNUNET_break (0);
-    return MHD_NO;
-  }
-
-  /* Finally build response object */
-  {
-    struct MHD_Response *resp;
-    void *json_str;
-    size_t json_len;
-
-    json_str = json_dumps (jresponse,
-                           JSON_INDENT(2));
-    json_decref (jresponse);
-    if (NULL == json_str)
-    {
-      GNUNET_break (0);
-      return MHD_NO;
-    }
-    json_len = strlen (json_str);
-    resp = MHD_create_response_from_buffer (json_len,
-                                            json_str,
-                                            MHD_RESPMEM_MUST_FREE);
-    if (NULL == resp)
-    {
-      GNUNET_break (0);
-      free (json_str);
-      return MHD_NO;
-    }
-    (void) MHD_add_response_header (resp,
-                                    MHD_HTTP_HEADER_CONTENT_TYPE,
-                                    "application/json");
-    ret = MHD_queue_response (connection,
-                              MHD_HTTP_OK,
-                              resp);
-    MHD_destroy_response (resp);
-  }
-  return ret;
-}
-
-
 /**
  * Handle incoming HTTP request.
  *
@@ -1557,12 +779,19 @@ handle_mhd_request (void *cls,
                           upload_data_size,
                           con_cls);
   if ( (0 == strcasecmp (url,
+                         "/history-range")) &&
+       (0 == strcasecmp (method,
+                         MHD_HTTP_METHOD_GET)) )
+    return handle_history_range (h,
+                                 connection,
+                                 con_cls);
+  if ( (0 == strcasecmp (url,
                          "/history")) &&
        (0 == strcasecmp (method,
                          MHD_HTTP_METHOD_GET)) )
-    return handle_history (h,
-                           connection,
-                           con_cls);
+    return handle_history_new (h,
+                               connection,
+                               con_cls);
 
   /* Unexpected URL path, just close the connection. */
   /* we're rather impolite here, but it's a testcase. */
diff --git a/src/bank-lib/fakebank.h b/src/bank-lib/fakebank.h
new file mode 100644
index 00000000..4e81b353
--- /dev/null
+++ b/src/bank-lib/fakebank.h
@@ -0,0 +1,322 @@
+/*
+  This file is part of TALER
+  (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+
+  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 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not,
+  see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file bank-lib/fakebank.h
+ * @brief definitions for the "/history[-range]" layer.
+ * @author Marcello Stanisci <address@hidden>
+ */
+
+#ifndef FAKEBANK_H
+#define FAKEBANK_H
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include "taler_bank_service.h"
+
+/**
+ * Details about a transcation we (as the simulated bank) received.
+ */
+struct Transaction
+{
+  /**
+   * We store transactions in a DLL.
+   */
+  struct Transaction *next;
+
+  /**
+   * We store transactions in a DLL.
+   */
+  struct Transaction *prev;
+
+  /**
+   * Amount to be transferred.
+   */
+  struct TALER_Amount amount;
+
+  /**
+   * Account to debit.
+   */
+  uint64_t debit_account;
+
+  /**
+   * Account to credit.
+   */
+  uint64_t credit_account;
+
+  /**
+   * Subject of the transfer.
+   */
+  char *subject;
+
+  /**
+   * Base URL of the exchange.
+   */
+  char *exchange_base_url;
+
+  /**
+   * When did the transaction happen?
+   */
+  struct GNUNET_TIME_Absolute date;
+
+  /**
+   * Number of this transaction.
+   */
+  uint64_t row_id;
+
+  /**
+   * Flag set if the transfer was rejected.
+   */
+  int rejected;
+
+  /**
+   * Has this transaction been subjected to #TALER_FAKEBANK_check()
+   * and should thus no longer be counted in
+   * #TALER_FAKEBANK_check_empty()?
+   */
+  int checked;
+};
+
+
+/******************************************
+ * Definitions for "/history" start here. *
+ ******************************************/
+
+/**
+ * Needed to implement ascending/descending ordering
+ * of /history results.
+ */
+struct HistoryElement
+{
+
+  /**
+   * History JSON element.
+   */
+  json_t *element;
+
+  /**
+   * Previous element.
+   */
+  struct HistoryElement *prev;
+
+  /**
+   * Next element.
+   */
+  struct HistoryElement *next;
+};
+
+
+/**
+ * Values to implement the "/history-range" range.
+ */
+struct HistoryRangeDates
+{
+  /**
+   * Oldest row in the results.
+   */
+  struct GNUNET_TIME_Absolute start;
+
+  /**
+   * Youngest row in the results.
+   */
+  struct GNUNET_TIME_Absolute end;
+};
+
+/**
+ * Values to implement the "/history" range.
+ */
+struct HistoryRangeIds
+{
+
+  /**
+   * (Exclusive) row ID for the result set.
+   */
+  unsigned long long start;
+
+  /**
+   * How many transactions we want in the result set.  If
+   * negative/positive, @a start will be strictly younger/older
+   * of any element in the result set.
+   */
+  long long count;
+};
+
+
+/**
+ * This is the "base" structure for both the /history and the
+ * /history-range API calls.
+ */
+struct HistoryArgs
+{
+
+  /**
+   * Direction asked by the client: CREDIT / DEBIT / BOTH / CANCEL.
+   */
+  enum TALER_BANK_Direction direction;
+
+  /**
+   * Bank account number of the requesting client.
+   */
+  unsigned long long account_number;
+
+  /**
+   * Ordering of the results.
+   */
+  unsigned int ascending;
+
+  /**
+   * Overloaded type that indicates the "range" to be returned
+   * in the results; this can be either a date range, or a
+   * starting row id + the count.
+   */
+  void *range;
+};
+
+
+
+/**
+ * Type for a function that decides whether or not
+ * the history-building loop should iterate once again.
+ * Typically called from inside the 'while' condition.
+ *
+ * @param ha history argument.
+ * @param pos current position.
+ * @return GNUNET_YES if the iteration shuold go on.
+ */
+typedef int (*CheckAdvance)
+  (const struct HistoryArgs *ha,
+   const struct Transaction *pos);
+
+/**
+ * Type for a function that steps over the next element
+ * in the list of all transactions, after the current @a pos
+ * _got_ included in the result.
+ */
+typedef struct Transaction * (*Step)
+  (const struct HistoryArgs *ha,
+   const struct Transaction *pos);
+
+/*
+ * Type for a function that steps over the next element
+ * in the list of all transactions, after the current @a pos
+ * did _not_ get included in the result.
+ */
+typedef struct Transaction * (*Skip)
+  (const struct HistoryArgs *ha,
+   const struct Transaction *pos);
+
+/**
+ * Actual history response builder.
+ *
+ * @param pos first (included) element in the result set.
+ * @param ha history arguments.
+ * @param caller_name which function is building the history.
+ * @return MHD_YES / MHD_NO, after having enqueued the response
+ *         object into MHD.
+ */
+int
+TFH_build_history_response (struct MHD_Connection *connection,
+                            struct Transaction *pos,
+                            struct HistoryArgs *ha,
+                            Skip skip,
+                            Step step,
+                            CheckAdvance advance);
+
+
+/**
+ * Parse URL history arguments, of _both_ APIs:
+ * /history and /history-range.
+ *
+ * @param connection MHD connection.
+ * @param function_name name of the caller.
+ * @param ha[out] will contain the parsed values.
+ * @return GNUNET_OK only if the parsing succeedes.
+ */
+int
+TFH_parse_history_common_args (struct MHD_Connection *connection,
+                               struct HistoryArgs *ha);
+
+
+/**
+ * Decides whether the history builder will advance or not
+ * to the next element.
+ *
+ * @param ha history args
+ * @return GNUNET_YES/NO to advance/not-advance.
+ */
+int
+TFH_handle_history_advance (const struct HistoryArgs *ha,
+                            const struct Transaction *pos);
+
+/**
+ * Iterates on the "next" element to be processed.  To
+ * be used when the current element does not get inserted in
+ * the result.
+ *
+ * @param ha history arguments.
+ * @param pos current element being processed.
+ * @return the next element to be processed.
+ */
+struct Transaction *
+TFH_handle_history_skip (const struct HistoryArgs *ha,
+                         const struct Transaction *pos);
+
+/**
+ * Iterates on the "next" element to be processed.  To
+ * be used when the current element _gets_ inserted in the result.
+ *
+ * @param ha history arguments.
+ * @param pos current element being processed.
+ * @return the next element to be processed.
+ */
+struct Transaction *
+TFH_handle_history_step (const struct HistoryArgs *ha,
+                         const struct Transaction *pos);
+
+/**
+ * Decides whether the history builder will advance or not
+ * to the next element.
+ *
+ * @param ha history args
+ * @return GNUNET_YES/NO to advance/not-advance.
+ */
+int
+TFH_handle_history_range_advance (const struct HistoryArgs *ha,
+                                  const struct Transaction *pos);
+
+/**
+ * Iterates towards the "next" element to be processed.  To
+ * be used when the current element does not get inserted in
+ * the result.
+ *
+ * @param ha history arguments.
+ * @param pos current element being processed.
+ * @return the next element to be processed.
+ */
+struct Transaction *
+TFH_handle_history_range_skip (const struct HistoryArgs *ha,
+                               const struct Transaction *pos);
+
+/**
+ * Iterates on the "next" element to be processed.  To
+ * be used when the current element _gets_ inserted in the result.
+ * Same implementation of the "skip" counterpart, as /history-range
+ * does not have the notion of count/delta.
+ */
+Step TFH_handle_history_range_step;
+#endif
diff --git a/src/bank-lib/fakebank_history.c b/src/bank-lib/fakebank_history.c
new file mode 100644
index 00000000..17960a4e
--- /dev/null
+++ b/src/bank-lib/fakebank_history.c
@@ -0,0 +1,427 @@
+/*
+  This file is part of TALER
+  (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+
+  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 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not,
+  see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file bank-lib/fakebank_history.c
+ * @brief definitions for the "/history[-range]" layer.
+ * @author Marcello Stanisci <address@hidden>
+ */
+
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include "taler_json_lib.h"
+#include "fakebank.h"
+
+/**
+ * Decides whether the history builder will advance or not
+ * to the next element.
+ *
+ * @param ha history args
+ * @return GNUNET_YES/NO to advance/not-advance.
+ */
+int
+TFH_handle_history_advance (const struct HistoryArgs *ha,
+                            const struct Transaction *pos)
+{
+  const struct HistoryRangeIds *hri = ha->range;
+
+  return (NULL != pos) && (0 != hri->count);
+}
+
+
+/**
+ * Iterates on the "next" element to be processed.  To
+ * be used when the current element does not get inserted in
+ * the result.
+ *
+ * @param ha history arguments.
+ * @param pos current element being processed.
+ * @return the next element to be processed.
+ */
+struct Transaction *
+TFH_handle_history_skip (const struct HistoryArgs *ha,
+                         const struct Transaction *pos)
+{
+  const struct HistoryRangeIds *hri = ha->range;
+
+  if (hri->count > 0)
+    return pos->next;
+  if (hri->count < 0)
+    return pos->prev;
+  return NULL;
+}
+
+
+/**
+ * Iterates on the "next" element to be processed.  To
+ * be used when the current element _gets_ inserted in the result.
+ *
+ * @param ha history arguments.
+ * @param pos current element being processed.
+ * @return the next element to be processed.
+ */
+struct Transaction *
+TFH_handle_history_step (const struct HistoryArgs *ha,
+                         const struct Transaction *pos)
+{
+  struct HistoryRangeIds *hri = ha->range;
+
+  if (hri->count > 0)
+  {
+    hri->count--;
+    return pos->next;
+  }
+  if (hri->count < 0)
+  {
+    hri->count++;
+    return pos->prev;
+  }
+  return NULL;
+}
+
+
+/**
+ * Decides whether the history builder will advance or not
+ * to the next element.
+ *
+ * @param ha history args
+ * @return GNUNET_YES/NO to advance/not-advance.
+ */
+int
+TFH_handle_history_range_advance (const struct HistoryArgs *ha,
+                                  const struct Transaction *pos)
+{
+  const struct HistoryRangeDates *hrd = ha->range;
+
+  if ( (NULL != pos) &&
+      (pos->date.abs_value_us <= hrd->end.abs_value_us) )
+    return GNUNET_YES;
+
+  return GNUNET_NO;
+}
+
+
+/**
+ * Iterates towards the "next" element to be processed.  To
+ * be used when the current element does not get inserted in
+ * the result.
+ *
+ * @param ha history arguments.
+ * @param pos current element being processed.
+ * @return the next element to be processed.
+ */
+struct Transaction *
+TFH_handle_history_range_skip (const struct HistoryArgs *ha,
+                               const struct Transaction *pos)
+{
+  /* Transactions
+   * are stored from "head"/older to "tail"/younger.  */
+  return pos->next;
+}
+
+/**
+ * Iterates on the "next" element to be processed.  To
+ * be used when the current element _gets_ inserted in the result.
+ * Same implementation of the "skip" counterpart, as /history-range
+ * does not have the notion of count/delta.
+ */
+Step TFH_handle_history_range_step = &TFH_handle_history_range_skip;
+
+/**
+ * Actual history response builder.
+ *
+ * @param pos first (included) element in the result set.
+ * @param ha history arguments.
+ * @param caller_name which function is building the history.
+ * @return MHD_YES / MHD_NO, after having enqueued the response
+ *         object into MHD.
+ */
+int
+TFH_build_history_response (struct MHD_Connection *connection,
+                            struct Transaction *pos,
+                            struct HistoryArgs *ha,
+                            Skip skip,
+                            Step step,
+                            CheckAdvance advance)
+{
+
+  struct HistoryElement *history_results_head = NULL;
+  struct HistoryElement *history_results_tail = NULL;
+  struct HistoryElement *history_element = NULL;
+  json_t *history;
+  json_t *jresponse;
+  int ret;
+
+  while (advance (ha,
+                  pos))
+  {
+    json_t *trans;
+    char *subject;
+    const char *sign;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Found transaction over %s from %llu to %llu\n",
+                TALER_amount2s (&pos->amount),
+                (unsigned long long) pos->debit_account,
+                (unsigned long long) pos->credit_account);
+
+    if ( (! ( ( (ha->account_number == pos->debit_account) &&
+                (0 != (ha->direction & TALER_BANK_DIRECTION_DEBIT)) ) ||
+              ( (ha->account_number == pos->credit_account) &&
+                (0 != (ha->direction & TALER_BANK_DIRECTION_CREDIT) ) ) ) ) ||
+         ( (0 == (ha->direction & TALER_BANK_DIRECTION_CANCEL)) &&
+           (GNUNET_YES == pos->rejected) ) )
+    {
+      pos = skip (ha,
+                  pos);
+      continue;
+    }
+
+    GNUNET_asprintf (&subject,
+                     "%s %s",
+                     pos->subject,
+                     pos->exchange_base_url);
+    sign =
+      (ha->account_number == pos->debit_account)
+      ? (pos->rejected ? "cancel-" : "-")
+      : (pos->rejected ? "cancel+" : "+");
+    trans = json_pack
+      ("{s:I, s:o, s:o, s:s, s:I, s:s}",
+       "row_id", (json_int_t) pos->row_id,
+       "date", GNUNET_JSON_from_time_abs (pos->date),
+       "amount", TALER_JSON_from_amount (&pos->amount),
+       "sign", sign,
+       "counterpart", (json_int_t)
+         ( (ha->account_number == pos->debit_account)
+            ? pos->credit_account
+            : pos->debit_account),
+       "wt_subject", subject);
+    GNUNET_assert (NULL != trans);
+    GNUNET_free (subject);
+
+    history_element = GNUNET_new (struct HistoryElement);
+    history_element->element = trans;
+
+
+    /* XXX: the ordering feature is missing.  */
+
+    GNUNET_CONTAINER_DLL_insert_tail (history_results_head,
+                                      history_results_tail,
+                                      history_element);
+    pos = step (ha, pos);
+  }
+
+  history = json_array ();
+  if (NULL != history_results_head)
+    history_element = history_results_head;
+
+  while (NULL != history_element)
+  {
+    json_array_append_new (history,
+                           history_element->element);
+    history_element = history_element->next;
+    if (NULL != history_element)
+      GNUNET_free_non_null (history_element->prev);
+  }
+  GNUNET_free_non_null (history_results_tail);
+
+  if (0 == json_array_size (history))
+  {
+    struct MHD_Response *resp;
+
+    json_decref (history);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Returning empty transaction history\n");
+    resp = MHD_create_response_from_buffer
+      (0,
+       "",
+       MHD_RESPMEM_PERSISTENT);
+    ret = MHD_queue_response (connection,
+                              MHD_HTTP_NO_CONTENT,
+                              resp);
+    MHD_destroy_response (resp);
+    return ret;
+  }
+
+  jresponse = json_pack ("{s:o}",
+                         "data",
+                         history);
+  if (NULL == jresponse)
+  {
+    GNUNET_break (0);
+    return MHD_NO;
+  }
+
+  /* Finally build response object */
+  {
+    struct MHD_Response *resp;
+    void *json_str;
+    size_t json_len;
+
+    json_str = json_dumps (jresponse,
+                           JSON_INDENT(2));
+    json_decref (jresponse);
+    if (NULL == json_str)
+    {
+      GNUNET_break (0);
+      return MHD_NO;
+    }
+    json_len = strlen (json_str);
+    resp = MHD_create_response_from_buffer (json_len,
+                                            json_str,
+                                            MHD_RESPMEM_MUST_FREE);
+    if (NULL == resp)
+    {
+      GNUNET_break (0);
+      free (json_str);
+      return MHD_NO;
+    }
+    (void) MHD_add_response_header (resp,
+                                    MHD_HTTP_HEADER_CONTENT_TYPE,
+                                    "application/json");
+    ret = MHD_queue_response (connection,
+                              MHD_HTTP_OK,
+                              resp);
+    MHD_destroy_response (resp);
+  }
+  return ret;
+}
+
+/**
+ * Parse URL history arguments, of _both_ APIs:
+ * /history and /history-range.
+ *
+ * @param connection MHD connection.
+ * @param function_name name of the caller.
+ * @param ha[out] will contain the parsed values.
+ * @return GNUNET_OK only if the parsing succeedes.
+ */
+int
+TFH_parse_history_common_args (struct MHD_Connection *connection,
+                               struct HistoryArgs *ha)
+{
+  /**
+   * @variable
+   * Just check if given and == "basic", no need to keep around.
+   */
+  const char *auth;
+
+  /**
+   * All those will go into the structure, after parsing.
+   */
+  const char *direction;
+  const char *cancelled;
+  const char *ordering;
+  const char *account_number;
+
+
+  auth = MHD_lookup_connection_value (connection,
+                                      MHD_GET_ARGUMENT_KIND,
+                                      "auth");
+  direction = MHD_lookup_connection_value (connection,
+                                           MHD_GET_ARGUMENT_KIND,
+                                           "direction");
+  cancelled = MHD_lookup_connection_value (connection,
+                                           MHD_GET_ARGUMENT_KIND,
+                                           "cancelled");
+  ordering = MHD_lookup_connection_value (connection,
+                                          MHD_GET_ARGUMENT_KIND,
+                                          "ordering");
+  account_number = MHD_lookup_connection_value
+    (connection,
+     MHD_GET_ARGUMENT_KIND,
+     "account_number");
+
+  /* Fail if one of the above failed.  */
+  if ( (NULL == direction) ||
+       (NULL == cancelled) ||
+       ( (0 != strcasecmp (cancelled,
+                           "OMIT")) &&
+         (0 != strcasecmp (cancelled,
+                           "SHOW")) ) ||
+       ( (0 != strcasecmp (direction,
+                           "BOTH")) &&
+         (0 != strcasecmp (direction,
+                           "CREDIT")) &&
+         (0 != strcasecmp (direction,
+                           "DEBIT")) ) ||
+         (1 != sscanf (account_number,
+                       "%llu",
+                       &ha->account_number)) ||
+         ( (NULL == auth) || (0 != strcasecmp (auth,
+                                               "basic")) ) )
+  {
+    /* Invalid request, given that this is fakebank we impolitely
+     * just kill the connection instead of returning a nice error.
+     */
+    GNUNET_break (0);
+    return GNUNET_NO;
+  }
+
+  if (0 == strcasecmp (direction,
+                       "CREDIT"))
+  {
+    ha->direction = TALER_BANK_DIRECTION_CREDIT;
+  }
+  else if (0 == strcasecmp (direction,
+                            "DEBIT"))
+  {
+    ha->direction = TALER_BANK_DIRECTION_DEBIT;
+  }
+  else if (0 == strcasecmp (direction,
+                            "BOTH"))
+  {
+    ha->direction = TALER_BANK_DIRECTION_BOTH;
+  }
+
+  /* Direction is invalid.  */
+  else
+  {
+    GNUNET_break (0);
+    return GNUNET_NO;
+  }
+
+  if (0 == strcasecmp (cancelled,
+                       "OMIT"))
+  {
+    /* nothing */
+  } else if (0 == strcasecmp (cancelled,
+                              "SHOW"))
+  {
+    ha->direction |= TALER_BANK_DIRECTION_CANCEL;
+  }
+
+  /* Cancel-showing policy is invalid.  */
+  else
+  {
+    GNUNET_break (0);
+    return GNUNET_NO;
+  }
+
+  if ((NULL != ordering)
+      && 0 == strcmp ("ascending",
+                      ordering))
+    ha->ascending = GNUNET_YES;
+  else
+    ha->ascending = GNUNET_NO;
+
+  return GNUNET_OK;
+}
+
+
diff --git a/src/exchange-tools/taler-exchange-keyup.c 
b/src/exchange-tools/taler-exchange-keyup.c
index 295eaa27..dcbc83d0 100644
--- a/src/exchange-tools/taler-exchange-keyup.c
+++ b/src/exchange-tools/taler-exchange-keyup.c
@@ -442,16 +442,17 @@ get_anchor (const char *dir,
 
     /**
      * XXX-ANCHOR question: why adding the duration only in this
-     * case, and not _all the times we found a anchor_ ?  Like
-     * for instance out of this block below ?
+     * case, and not _all the times we found a anchor_ ?  Like for
+     * instance, below out of this block?  
+     *
      */
     *anchor = GNUNET_TIME_absolute_add (*anchor,
                                         duration);
     *anchor = GNUNET_TIME_absolute_subtract (*anchor,
                                              overlap);
   }
-  
 
+  /* ==>Missing to add the duration to the anchor here?<== */ 
 
   /* anchor is now the stamp where we need to create a new key */
 }

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



reply via email to

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