implement #4929: add wire transfer fee to /wire (but not yet charged by aggregator)

This commit is contained in:
Christian Grothoff 2017-03-03 20:31:29 +01:00
parent 364abbaea1
commit f406f96129
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
13 changed files with 578 additions and 27 deletions

2
.gitignore vendored
View File

@ -35,9 +35,11 @@ src/bank-lib/test_bank_api
src/bank-lib/test_bank_api_with_fakebank
src/exchange-lib/test_exchange_api
src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/live-keys/
src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/wirefees/
src/exchange/taler-exchange-aggregator
src/exchange/test_taler_exchange_aggregator-postgres
src/exchange/test_taler_exchange_httpd_home/.local/share/taler/exchange/live-keys/
src/exchange/test_taler_exchange_httpd_home/.local/share/taler/exchange/wirefees/
src/exchange-tools/taler-auditor-sign
src/exchange-tools/taler-exchange-dbinit
src/exchange-tools/taler-exchange-keycheck

View File

@ -30,6 +30,19 @@ DB_CONN_STR = "postgres:///talercheck"
# Enable 'sepa' to test SEPA-specific routines.
ENABLE = YES
# Fees for the forseeable future...
# If you see this after 2017, update to match the next 10 years...
WIRE-FEE-2017 = EUR:0.01
WIRE-FEE-2018 = EUR:0.01
WIRE-FEE-2019 = EUR:0.01
WIRE-FEE-2020 = EUR:0.01
WIRE-FEE-2021 = EUR:0.01
WIRE-FEE-2022 = EUR:0.01
WIRE-FEE-2023 = EUR:0.01
WIRE-FEE-2024 = EUR:0.01
WIRE-FEE-2025 = EUR:0.01
WIRE-FEE-2026 = EUR:0.01
[exchange-wire-incoming-sepa]
# This is the response we give out for the /wire request. It provides
# wallets with the bank information for transfers to the exchange.
@ -39,6 +52,20 @@ SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/sepa.json
# Enable 'test' for testing of the actual coin operations.
ENABLE = YES
# Fees for the forseeable future...
# If you see this after 2017, update to match the next 10 years...
WIRE-FEE-2017 = EUR:0.01
WIRE-FEE-2018 = EUR:0.01
WIRE-FEE-2019 = EUR:0.01
WIRE-FEE-2020 = EUR:0.01
WIRE-FEE-2021 = EUR:0.01
WIRE-FEE-2022 = EUR:0.01
WIRE-FEE-2023 = EUR:0.01
WIRE-FEE-2024 = EUR:0.01
WIRE-FEE-2025 = EUR:0.01
WIRE-FEE-2026 = EUR:0.01
[exchange-wire-incoming-test]
# This is the response we give out for the /wire request. It provides
# wallets with the bank information for transfers to the exchange.

View File

@ -25,6 +25,7 @@ taler_exchange_keyup_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/pq/libtalerpq.la \
$(top_builddir)/src/wire/libtalerwire.la \
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
-lgnunetutil $(XLIB)
taler_exchange_keyup_LDFLAGS = $(POSTGRESQL_LDFLAGS)

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014, 2015, 2016 GNUnet e.V.
Copyright (C) 2014-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
@ -23,6 +23,7 @@
*/
#include <platform.h>
#include "taler_exchangedb_lib.h"
#include "taler_wire_lib.h"
/**
* When generating filenames from a cryptographic hash, we do not use
@ -188,6 +189,11 @@ static char *exchange_directory;
*/
static char *pretend_time_str;
/**
* Directory where we should write the wire transfer fee structure.
*/
static char *feedir;
/**
* Handle to the exchange's configuration
*/
@ -214,6 +220,11 @@ static struct TALER_MasterPublicKeyP master_public_key;
*/
static struct GNUNET_TIME_Absolute lookahead_sign_stamp;
/**
* Largest duration for spending of any key.
*/
static struct GNUNET_TIME_Relative max_duration_spend;
/**
* Return value from main().
*/
@ -598,6 +609,8 @@ get_cointype_params (const char *ct,
return GNUNET_SYSERR;
}
GNUNET_TIME_round_rel (&params->duration_spend);
max_duration_spend = GNUNET_TIME_relative_max (max_duration_spend,
params->duration_spend);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg,
ct,
@ -861,6 +874,151 @@ exchange_keys_update_denomkeys ()
}
/**
* Sign @a af with @a priv
*
* @param[in|out] af fee structure to sign
* @param priv private key to use for signing
*/
static void
sign_af (struct TALER_EXCHANGEDB_AggregateFees *af,
const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
{
struct TALER_MasterWireFeePS wf;
TALER_EXCHANGEDB_fees_2_wf (af,
&wf);
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_eddsa_sign (priv,
&wf.purpose,
&af->master_sig.eddsa_signature));
}
/**
* Output the wire fee structure. Must be run after #max_duration_spend
* was initialized.
*
* @param cls pointer to `int`, set to #GNUNET_SYSERR on error
* @param wiremethod method to write fees for
*/
static void
create_wire_fee_for_method (void *cls,
const char *wiremethod)
{
int *ret = cls;
struct TALER_EXCHANGEDB_AggregateFees *af_head;
struct TALER_EXCHANGEDB_AggregateFees *af_tail;
unsigned int year;
struct GNUNET_TIME_Absolute last_date;
struct GNUNET_TIME_Absolute start_date;
struct GNUNET_TIME_Absolute end_date;
char yearstr[12];
char *fn;
char *section;
if (GNUNET_OK != *ret)
return;
last_date = GNUNET_TIME_absolute_max (last_date,
GNUNET_TIME_absolute_add (lookahead_sign_stamp,
max_duration_spend));
GNUNET_asprintf (&section,
"exchange-wire-%s",
wiremethod);
GNUNET_asprintf (&fn,
"%s%s.fee",
feedir,
wiremethod);
af_head = NULL;
af_tail = NULL;
year = GNUNET_TIME_get_current_year ();
start_date = GNUNET_TIME_year_to_time (year);
while (start_date.abs_value_us < last_date.abs_value_us)
{
struct TALER_EXCHANGEDB_AggregateFees *af;
char *opt;
char *amounts;
GNUNET_snprintf (yearstr,
sizeof (yearstr),
"%u",
year);
end_date = GNUNET_TIME_year_to_time (year + 1);
af = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
af->start_date = start_date;
af->end_date = end_date;
GNUNET_asprintf (&opt,
"wire-fee-%u",
year);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (kcfg,
section,
opt,
&amounts))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
section,
opt);
*ret = GNUNET_SYSERR;
GNUNET_free (opt);
break;
}
if (GNUNET_OK !=
TALER_string_to_amount (amounts,
&af->wire_fee))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid amount `%s' specified in `%s' under `%s'\n",
amounts,
wiremethod,
opt);
*ret = GNUNET_SYSERR;
GNUNET_free (amounts);
GNUNET_free (opt);
break;
}
GNUNET_free (amounts);
GNUNET_free (opt);
sign_af (af,
&master_priv.eddsa_priv);
if (NULL == af_tail)
af_head = af;
else
af_tail->next = af;
af_tail = af;
start_date = end_date;
year++;
}
if ( (GNUNET_OK == *ret) &&
(GNUNET_OK !=
TALER_EXCHANGEDB_fees_write (fn,
af_head)) )
*ret = GNUNET_SYSERR;
GNUNET_free (section);
GNUNET_free (fn);
TALER_EXCHANGEDB_fees_free (af_head);
}
/**
* Output the wire fee structure. Must be run after #max_duration_spend
* was initialized.
*
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static int
create_wire_fees ()
{
int ret;
ret = GNUNET_OK;
TALER_WIRE_find_enabled (kcfg,
&create_wire_fee_for_method,
&ret);
return ret;
}
/**
* Main function that will be run.
*
@ -896,6 +1054,29 @@ run (void *cls,
{
now = GNUNET_TIME_absolute_get ();
}
if (NULL == feedir)
{
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (kcfg,
"exchangedb",
"WIREFEE_BASE_DIR",
&feedir))
{
fprintf (stderr,
"Wire fee directory not given in neither configuration nor command-line\n");
global_ret = 1;
return;
}
}
if (GNUNET_OK !=
GNUNET_DISK_directory_create (feedir))
{
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
"mkdir",
feedir);
global_ret = 1;
return;
}
GNUNET_TIME_round_abs (&now);
if ( (NULL == masterkeyfile) &&
(GNUNET_OK !=
@ -1022,10 +1203,10 @@ run (void *cls,
global_ret = 1;
return;
}
if (NULL != auditor_output_file)
if (GNUNET_OK != create_wire_fees ())
{
FCLOSE (auditor_output_file);
auditor_output_file = NULL;
global_ret = 1;
return;
}
}
@ -1051,6 +1232,9 @@ main (int argc,
{'m', "master-key", "FILE",
"master key file (private key)", 1,
&GNUNET_GETOPT_set_filename, &masterkeyfile},
{'f', "feedir", "DIRNAME",
"directory where to write wire transfer fee structure", 1,
&GNUNET_GETOPT_set_filename, &feedir},
{'o', "output", "FILE",
"auditor denomination key signing request file to create", 1,
&GNUNET_GETOPT_set_filename, &auditorrequestfile},
@ -1072,6 +1256,11 @@ main (int argc,
options,
&run, NULL))
return 1;
if (NULL != auditor_output_file)
{
FCLOSE (auditor_output_file);
auditor_output_file = NULL;
}
return global_ret;
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2016 GNUnet e.V.
Copyright (C) 2016, 2017 GNUnet e.V.
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
@ -23,6 +23,7 @@
#include <gnunet/gnunet_util_lib.h>
#include "taler-exchange-httpd.h"
#include "taler-exchange-httpd_validation.h"
#include "taler-exchange-httpd_wire.h"
#include "taler_wire_lib.h"
@ -77,6 +78,7 @@ load_plugin (void *cls,
{
int *ret = cls;
struct Plugin *p;
json_t *fees;
p = GNUNET_new (struct Plugin);
p->type = GNUNET_strdup (name);
@ -84,13 +86,26 @@ load_plugin (void *cls,
name);
if (NULL == p->plugin)
{
GNUNET_free (p);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to load plugin %s\n",
name);
GNUNET_free (p->type);
GNUNET_free (p);
*ret = GNUNET_SYSERR;
return;
}
fees = TEH_WIRE_get_fees (name);
if (NULL == fees)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Disabling method `%s' as wire transfer fees are not given correctly\n",
name);
GNUNET_free (p->type);
GNUNET_free (p);
*ret = GNUNET_SYSERR;
return;
}
json_decref (fees);
GNUNET_CONTAINER_DLL_insert (wire_head,
wire_tail,
p);
@ -114,9 +129,8 @@ TEH_VALIDATION_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
&ret);
if (NULL == wire_head)
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"wireformat");
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to find properly configured wire transfer method\n");
ret = GNUNET_SYSERR;
}
if (GNUNET_OK != ret)
@ -201,17 +215,17 @@ json_t *
TEH_VALIDATION_get_wire_methods (const char *prefix)
{
json_t *methods;
json_t *method;
struct Plugin *p;
struct TALER_WIRE_Plugin *plugin;
char *account_name;
char *emsg;
enum TALER_ErrorCode ec;
methods = json_object ();
for (p=wire_head;NULL != p;p = p->next)
for (struct Plugin *p=wire_head;NULL != p;p = p->next)
{
plugin = p->plugin;
struct TALER_WIRE_Plugin *plugin = p->plugin;
json_t *method;
json_t *fees;
GNUNET_asprintf (&account_name,
"%s-%s",
prefix,
@ -233,6 +247,22 @@ TEH_VALIDATION_get_wire_methods (const char *prefix)
json_decref (method);
method = NULL;
}
fees = TEH_WIRE_get_fees (p->type);
if (NULL == fees)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Disabling method `%s' as wire transfer fees are not given correctly\n",
p->type);
json_decref (method);
method = NULL;
}
else
{
json_object_set_new (method,
"fees",
fees);
}
if (NULL != method)
json_object_set_new (methods,
p->type,

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2015, 2016 GNUnet e.V. and INRIA
Copyright (C) 2015-2017 GNUnet e.V. and INRIA
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
@ -24,6 +24,7 @@
#include "taler-exchange-httpd_responses.h"
#include "taler-exchange-httpd_validation.h"
#include "taler-exchange-httpd_wire.h"
#include "taler_json_lib.h"
#include <jansson.h>
/**
@ -32,6 +33,76 @@
static json_t *wire_methods;
/**
* Convert fee structure to JSON result to be returned
* as part of a /wire response.
*
* @param af fee structure to convert
* @return NULL on error, otherwise json data structure for /wire.
*/
static json_t *
fees_to_json (struct TALER_EXCHANGEDB_AggregateFees *af)
{
json_t *a;
a = json_array ();
while (NULL != af)
{
if ( (GNUNET_NO == GNUNET_TIME_round_abs (&af->start_date)) ||
(GNUNET_NO == GNUNET_TIME_round_abs (&af->end_date)) )
{
json_decref (a);
return NULL;
}
json_array_append_new (a,
json_pack ("{s:o, s:o, s:o, s:o}",
"wire_fee", TALER_JSON_from_amount (&af->wire_fee),
"start_date", GNUNET_JSON_from_time_abs (af->start_date),
"end_date", GNUNET_JSON_from_time_abs (af->end_date),
"sig", GNUNET_JSON_from_data_auto (&af->master_sig)));
af = af->next;
}
return a;
}
/**
* Obtain fee structure for @a wire_plugin_name wire transfers.
*
* @param wire_plugin_name name of the plugin to load fees for
* @return JSON object (to be freed by caller) with fee structure
*/
json_t *
TEH_WIRE_get_fees (const char *wire_plugin_name)
{
struct TALER_EXCHANGEDB_AggregateFees *af;
json_t *j;
struct GNUNET_TIME_Absolute now;
af = TALER_EXCHANGEDB_fees_read (cfg,
wire_plugin_name);
now = GNUNET_TIME_absolute_get ();
while ( (NULL != af) &&
(af->end_date.abs_value_us < now.abs_value_us) )
{
struct TALER_EXCHANGEDB_AggregateFees *n = af->next;
GNUNET_free (af);
af = n;
}
if (NULL == af)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to find current wire transfer fees for `%s'\n",
wire_plugin_name);
return NULL;
}
j = fees_to_json (af);
TALER_EXCHANGEDB_fees_free (af);
return j;
}
/**
* Handle a "/wire" request.
*

View File

@ -26,6 +26,16 @@
#include "taler-exchange-httpd.h"
/**
* Obtain fee structure for @a wire_plugin_name wire transfers.
*
* @param wire_plugin_name name of the plugin to load fees for
* @return JSON object (to be freed by caller) with fee structure
*/
json_t *
TEH_WIRE_get_fees (const char *wire_plugin_name);
/**
* Handle a "/wire" request.
*

View File

@ -44,6 +44,7 @@ lib_LTLIBRARIES = \
libtalerexchangedb_la_SOURCES = \
exchangedb_auditorkeys.c \
exchangedb_denomkeys.c \
exchangedb_fees.c \
exchangedb_signkeys.c \
exchangedb_plugin.c
@ -60,6 +61,7 @@ libtalerexchangedb_la_LDFLAGS = \
check_PROGRAMS = \
test-exchangedb-auditors \
test-exchangedb-denomkeys \
test-exchangedb-fees \
test-exchangedb-signkeys \
test-exchangedb-postgres \
test-perf-taler-exchangedb \
@ -68,10 +70,11 @@ check_PROGRAMS = \
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
TESTS = \
test-exchangedb-auditors \
test-exchangedb-denomkeys \
test-exchangedb-fees \
test-exchangedb-postgres \
test-exchangedb-signkeys \
test-perf-taler-exchangedb \
test-exchangedb-denomkeys
test-perf-taler-exchangedb
test_exchangedb_auditors_SOURCES = \
test_exchangedb_auditors.c
@ -87,6 +90,13 @@ test_exchangedb_denomkeys_LDADD = \
$(top_srcdir)/src/util/libtalerutil.la \
-lgnunetutil
test_exchangedb_fees_SOURCES = \
test_exchangedb_fees.c
test_exchangedb_fees_LDADD = \
libtalerexchangedb.la \
$(top_srcdir)/src/util/libtalerutil.la \
-lgnunetutil
test_exchangedb_signkeys_SOURCES = \
test_exchangedb_signkeys.c
test_exchangedb_signkeys_LDADD = \

View File

@ -42,7 +42,8 @@ TALER_EXCHANGEDB_denomination_key_read (const char *filename,
void *data;
struct GNUNET_CRYPTO_RsaPrivateKey *priv;
if (GNUNET_OK != GNUNET_DISK_file_size (filename,
if (GNUNET_OK !=
GNUNET_DISK_file_size (filename,
&size,
GNUNET_YES,
GNUNET_YES))

View File

@ -92,7 +92,7 @@ TALER_EXCHANGEDB_fees_read (const struct GNUNET_CONFIGURATION_Handle *cfg,
&wirefee_base_dir))
return NULL;
GNUNET_asprintf (&fn,
"%s" DIR_SEPARATOR_STR "%s.fee",
"%s/%s.fee",
wirefee_base_dir,
wireplugin);
GNUNET_free (wirefee_base_dir);

View File

@ -24,23 +24,121 @@
#include "taler_exchangedb_lib.h"
/**
* Sign @a af with @a priv
*
* @param[in|out] af fee structure to sign
* @param priv private key to use for signing
*/
static void
sign_af (struct TALER_EXCHANGEDB_AggregateFees *af,
const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
{
struct TALER_MasterWireFeePS wf;
TALER_EXCHANGEDB_fees_2_wf (af,
&wf);
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_eddsa_sign (priv,
&wf.purpose,
&af->master_sig.eddsa_signature));
}
int
main (int argc,
const char *const argv[])
{
struct GNUNET_CONFIGURATION_Handle *cfg;
struct TALER_EXCHANGEDB_AggregateFees *af;
struct TALER_EXCHANGEDB_AggregateFees *n;
struct TALER_MasterPublicKeyP master_pub;
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
char *tmpdir;
char *tmpfile = NULL;
int ret;
unsigned int year;
ret = 1;
GNUNET_log_setup ("test-exchangedb-fees",
"WARNING",
NULL);
tmpdir = GNUNET_DISK_mkdtemp ("test_exchangedb_fees");
if (NULL == tmpdir)
return 77; /* skip test */
priv = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_CRYPTO_eddsa_key_get_public (priv,
&master_pub.eddsa_pub);
cfg = GNUNET_CONFIGURATION_create ();
GNUNET_CONFIGURATION_set_value_string (cfg,
"exchangedb",
"AUDITOR_BASE_DIR",
"WIREFEE_BASE_DIR",
tmpdir);
GNUNET_asprintf (&tmpfile,
"%s/%s.fee",
tmpdir,
"test");
ret = 0;
af = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
year = GNUNET_TIME_get_current_year ();
af->start_date = GNUNET_TIME_year_to_time (year);
af->end_date = GNUNET_TIME_year_to_time (year + 1);
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:1.0",
&af->wire_fee));
sign_af (af,
priv);
n = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
n->start_date = GNUNET_TIME_year_to_time (year + 1);
n->end_date = GNUNET_TIME_year_to_time (year + 2);
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:0.1",
&n->wire_fee));
sign_af (n,
priv);
af->next = n;
if (GNUNET_OK !=
TALER_EXCHANGEDB_fees_write (tmpfile,
af))
{
GNUNET_break (0);
ret = 1;
}
TALER_EXCHANGEDB_fees_free (af);
GNUNET_free (tmpfile);
af = TALER_EXCHANGEDB_fees_read (cfg,
"test");
if (NULL == af)
{
GNUNET_break (0);
ret = 1;
}
else
{
for (struct TALER_EXCHANGEDB_AggregateFees *p = af;
NULL != p;
p = p->next)
{
struct TALER_MasterWireFeePS wf;
TALER_EXCHANGEDB_fees_2_wf (p,
&wf);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
&wf.purpose,
&p->master_sig.eddsa_signature,
&master_pub.eddsa_pub))
{
GNUNET_break (0);
ret = 1;
}
}
TALER_EXCHANGEDB_fees_free (af);
}
(void) GNUNET_DISK_directory_remove (tmpdir);
GNUNET_free (tmpdir);
GNUNET_free (priv);
GNUNET_CONFIGURATION_destroy (cfg);
return ret;
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014, 2015, 2016 Inria & GNUnet e.V.
Copyright (C) 2014-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
@ -25,6 +25,7 @@
#include "taler_signatures.h"
/**
* Subdirectroy under the exchange's base directory which contains
* the exchange's signing keys.
@ -297,4 +298,79 @@ void
TALER_EXCHANGEDB_plugin_unload (struct TALER_EXCHANGEDB_Plugin *plugin);
/**
* Sorted list of fees to be paid for aggregate wire transfers.
*/
struct TALER_EXCHANGEDB_AggregateFees
{
/**
* This is a linked list.
*/
struct TALER_EXCHANGEDB_AggregateFees *next;
/**
* Fee to be paid.
*/
struct TALER_Amount wire_fee;
/**
* Time when this fee goes into effect (inclusive)
*/
struct GNUNET_TIME_Absolute start_date;
/**
* Time when this fee stops being in effect (exclusive).
*/
struct GNUNET_TIME_Absolute end_date;
/**
* Signature affirming the above fee structure.
*/
struct TALER_MasterSignatureP master_sig;
};
/**
* 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);
/**
* 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);
/**
* 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);
/**
* Free @a af data structure
*
* @param af list to free
*/
void
TALER_EXCHANGEDB_fees_free (struct TALER_EXCHANGEDB_AggregateFees *af);
#endif

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014, 2015, 2016 GNUnet e.V.
Copyright (C) 2014-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
@ -78,6 +78,11 @@
*/
#define TALER_SIGNATURE_MASTER_TEST_DETAILS 1027
/**
* Fees charged per (aggregate) wire transfer to the merchant.
*/
#define TALER_SIGNATURE_MASTER_WIRE_FEES 1028
/*********************************************/
/* Exchange online signatures (with signing key) */
@ -879,6 +884,37 @@ struct TALER_MasterWireDetailsPS
};
/**
* @brief Information signed by the exchange's master
* key stating the wire fee to be paid per wire transfer.
*/
struct TALER_MasterWireFeePS
{
/**
* Purpose is #TALER_SIGNATURE_MASTER_WIRE_FEES.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Start date when the fee goes into effect.
*/
struct GNUNET_TIME_AbsoluteNBO start_date;
/**
* End date when the fee stops being in effect (exclusive)
*/
struct GNUNET_TIME_AbsoluteNBO end_date;
/**
* Fee charged to the merchant per wire transfer.
*/
struct TALER_AmountNBO wire_fee;
};
/**
* @brief Format used to generate the signature on a request to obtain
* the wire transfer identifier associated with a deposit.