implement #4929: add wire transfer fee to /wire (but not yet charged by aggregator)
This commit is contained in:
parent
364abbaea1
commit
f406f96129
2
.gitignore
vendored
2
.gitignore
vendored
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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 (¶ms->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 (§ion,
|
||||
"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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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 = \
|
||||
|
@ -42,10 +42,11 @@ TALER_EXCHANGEDB_denomination_key_read (const char *filename,
|
||||
void *data;
|
||||
struct GNUNET_CRYPTO_RsaPrivateKey *priv;
|
||||
|
||||
if (GNUNET_OK != GNUNET_DISK_file_size (filename,
|
||||
&size,
|
||||
GNUNET_YES,
|
||||
GNUNET_YES))
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_file_size (filename,
|
||||
&size,
|
||||
GNUNET_YES,
|
||||
GNUNET_YES))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Skipping inaccessable denomination key file `%s'\n",
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user