diff options
| author | Christian Grothoff <christian@grothoff.org> | 2017-03-03 19:23:34 +0100 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2017-03-03 19:24:08 +0100 | 
| commit | 4d2faa5ec92213efc4ee40f707ab0ad3615e5433 (patch) | |
| tree | 4bb94dba0c77cca9d0ba6b7fb223bc9476edc08e /src/exchangedb | |
| parent | d06dac625072cad6888c9d0a77f6bd19faa5f2d9 (diff) | |
changing wire plugin specification from [exchange]WIREFORMAT to [exchange-wire-PLUGIN]enable=YES/NO
Diffstat (limited to 'src/exchangedb')
| -rw-r--r-- | src/exchangedb/exchangedb.conf | 7 | ||||
| -rw-r--r-- | src/exchangedb/exchangedb_fees.c | 243 | ||||
| -rw-r--r-- | src/exchangedb/test_exchangedb_fees.c | 46 | 
3 files changed, 296 insertions, 0 deletions
| diff --git a/src/exchangedb/exchangedb.conf b/src/exchangedb/exchangedb.conf index 19277ed2..4640507d 100644 --- a/src/exchangedb/exchangedb.conf +++ b/src/exchangedb/exchangedb.conf @@ -5,3 +5,10 @@  [exchangedb]  # Where do we expect to find information about auditors?  AUDITOR_BASE_DIR = ${TALER_DATA_HOME}/auditors/ + +# Where do we expect to find information about wire transfer fees +# for aggregate payments?  These are the amounts we charge (subtract) +# the merchant per wire transfer.  The directory is expected to +# contain files "$METHOD.fee" with the cost structure, where +# $METHOD corresponds to a wire transfer method. +WIREFEE_BASE_DIR = ${TALER_DATA_HOME}/wirefees/ diff --git a/src/exchangedb/exchangedb_fees.c b/src/exchangedb/exchangedb_fees.c new file mode 100644 index 00000000..938b61c1 --- /dev/null +++ b/src/exchangedb/exchangedb_fees.c @@ -0,0 +1,243 @@ +/* +  This file is part of TALER +  Copyright (C) 2017 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 exchangedb/exchangedb_fees.c + * @brief Logic to read/write/convert aggregation wire fees (not other fees!) + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_exchangedb_lib.h" + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Structure for wire fees on disk. + */ +struct TALER_WireFeeDiskP +{ + +  /** +   * Wire fee details. +   */ +  struct TALER_MasterWireFeePS wf; + + +  /** +   * Signature affirming the above fee structure. +   */ +  struct TALER_MasterSignatureP master_sig; + +}; + +GNUNET_NETWORK_STRUCT_END + + +/** + * Convert @a wd disk format to host format. + * + * @param wd aggregate fees, disk format + * @return fees in host format + */ +static struct TALER_EXCHANGEDB_AggregateFees * +wd2af (const struct TALER_WireFeeDiskP *wd) +{ +  struct TALER_EXCHANGEDB_AggregateFees *af; + +  af = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees); +  af->start_date = GNUNET_TIME_absolute_ntoh (wd->wf.start_date); +  af->end_date = GNUNET_TIME_absolute_ntoh (wd->wf.end_date); +  TALER_amount_ntoh (&af->wire_fee, +                     &wd->wf.wire_fee); +  af->master_sig = wd->master_sig; +  return af; +} + + +/** + * Read the current fee structure from disk. + * + * @param cfg configuration to use + * @param wireplugin name of the wire plugin to read fees for + * @return sorted list of aggregation fees, NULL on error + */ +struct TALER_EXCHANGEDB_AggregateFees * +TALER_EXCHANGEDB_fees_read (const struct GNUNET_CONFIGURATION_Handle *cfg, +                            const char *wireplugin) +{ +  char *wirefee_base_dir; +  char *fn; +  struct GNUNET_DISK_FileHandle *fh; +  struct TALER_WireFeeDiskP wd; +  struct TALER_EXCHANGEDB_AggregateFees *af; +  struct TALER_EXCHANGEDB_AggregateFees *endp; + +  if (GNUNET_OK != +      GNUNET_CONFIGURATION_get_value_filename (cfg, +                                               "exchangedb", +                                               "WIREFEE_BASE_DIR", +                                               &wirefee_base_dir)) +    return NULL; +  GNUNET_asprintf (&fn, +                   "%s" DIR_SEPARATOR_STR "%s.fee", +                   wirefee_base_dir, +                   wireplugin); +  GNUNET_free (wirefee_base_dir); +  fh = GNUNET_DISK_file_open (fn, +                              GNUNET_DISK_OPEN_READ, +                              GNUNET_DISK_PERM_NONE); +  GNUNET_free (fn); +  if (NULL == fh) +    return NULL; + +  af = NULL; +  endp = NULL; +  while (sizeof (wd) == +         GNUNET_DISK_file_read (fh, +                                &wd, +                                sizeof (wd))) +  { +    struct TALER_EXCHANGEDB_AggregateFees *n; + +    n = wd2af (&wd); +    if ( ( (NULL == af) || +           (endp->end_date.abs_value_us == n->start_date.abs_value_us) ) && +         (n->start_date.abs_value_us < n->end_date.abs_value_us) ) +    { +      /* append to list */ +      if (NULL != endp) +        endp->next = n; +      else +        af = n; +      endp = n; +    } +    else +    { +      /* We expect file to be in chronological order! */ +      GNUNET_break (0); +      GNUNET_DISK_file_close (fh); +      GNUNET_free (n); +      TALER_EXCHANGEDB_fees_free (af); +      return NULL; +    } +  } +  GNUNET_DISK_file_close (fh); +  return af; +} + + +/** + * Convert @a af to @a wf. + * + * @param[in,out] af aggregate fees, host format (updated to round time) + * @param[out] wf aggregate fees, disk / signature format + */ +void +TALER_EXCHANGEDB_fees_2_wf (struct TALER_EXCHANGEDB_AggregateFees *af, +                            struct TALER_MasterWireFeePS *wf) +{ +  (void) GNUNET_TIME_round_abs (&af->start_date); +  (void) GNUNET_TIME_round_abs (&af->end_date); +  wf->purpose.size = htonl (sizeof (*wf)); +  wf->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES); +  wf->start_date = GNUNET_TIME_absolute_hton (af->start_date); +  wf->end_date = GNUNET_TIME_absolute_hton (af->end_date); +  TALER_amount_hton (&wf->wire_fee, +                     &af->wire_fee); +} + + +/** + * Write given fee structure to disk. + * + * @param filename where to write the fees + * @param af fee structure to write + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +TALER_EXCHANGEDB_fees_write (const char *filename, +                             struct TALER_EXCHANGEDB_AggregateFees *af) +{ +  struct GNUNET_DISK_FileHandle *fh; +  struct TALER_WireFeeDiskP wd; +  struct TALER_EXCHANGEDB_AggregateFees *last; + +  if (GNUNET_OK != +      GNUNET_DISK_directory_create_for_file (filename)) +    return GNUNET_SYSERR; + +  fh = GNUNET_DISK_file_open (filename, +                              GNUNET_DISK_OPEN_WRITE | +                              GNUNET_DISK_OPEN_TRUNCATE | +                              GNUNET_DISK_OPEN_CREATE, +                              GNUNET_DISK_PERM_USER_READ | +                              GNUNET_DISK_PERM_USER_WRITE); +  if (NULL == fh) +    return GNUNET_SYSERR; + +  last = NULL; +  while (NULL != af) +  { +    if ( ( (NULL != last) && +           (last->end_date.abs_value_us != af->start_date.abs_value_us) ) || +         (af->start_date.abs_value_us >= af->end_date.abs_value_us) ) +    { +      /* @a af malformed, refusing to write file that will be rejected */ +      GNUNET_break (0); +      GNUNET_assert (GNUNET_OK == +                     GNUNET_DISK_file_close (fh)); +      return GNUNET_SYSERR; +    } +    TALER_EXCHANGEDB_fees_2_wf (af, +                                &wd.wf); +    wd.master_sig = af->master_sig; +    af = af->next; +    if (sizeof (wd) != +        GNUNET_DISK_file_write (fh, +                                &wd, +                                sizeof (wd))) +    { +      GNUNET_assert (GNUNET_OK == +                     GNUNET_DISK_file_close (fh)); +      return GNUNET_SYSERR; +    } +  } +  GNUNET_assert (GNUNET_OK == +                 GNUNET_DISK_file_close (fh)); +  return GNUNET_OK; +} + + +/** + * Free @a af data structure + * + * @param af list to free + */ +void +TALER_EXCHANGEDB_fees_free (struct TALER_EXCHANGEDB_AggregateFees *af) +{ +  struct TALER_EXCHANGEDB_AggregateFees *next; + +  while (NULL != af) +  { +    next = af->next; +    GNUNET_free (af); +    af = next; +  } +} + + +/* end of exchangedb_fees.c */ diff --git a/src/exchangedb/test_exchangedb_fees.c b/src/exchangedb/test_exchangedb_fees.c new file mode 100644 index 00000000..e23879ea --- /dev/null +++ b/src/exchangedb/test_exchangedb_fees.c @@ -0,0 +1,46 @@ +/* +  This file is part of TALER +  Copyright (C) 2017 Inria & 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 exchangedb/test_exchangedb_fees.c + * @brief test cases for functions in exchangedb/exchangedb_fees.c + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet/gnunet_util_lib.h" +#include "taler_signatures.h" +#include "taler_exchangedb_lib.h" + + +int +main (int argc, +      const char *const argv[]) +{ +  struct GNUNET_CONFIGURATION_Handle *cfg; +  int ret; + +  ret = 1; +  GNUNET_log_setup ("test-exchangedb-fees", +                    "WARNING", +                    NULL); +  cfg = GNUNET_CONFIGURATION_create (); + +  GNUNET_CONFIGURATION_set_value_string (cfg, +                                         "exchangedb", +                                         "AUDITOR_BASE_DIR", +                                         tmpdir); +  ret = 0; +  return ret; +} | 
