From 4a519078e803c8ff042833a2200c5b6a0297fbe7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 14 Dec 2020 18:27:16 +0100 Subject: update generator scripts to use new -offline tools (WiP) --- src/auditor/generate-auditor-basedb.conf | 2 + src/auditor/generate-auditor-basedb.sh | 66 +- src/auditor/generate-revoke-basedb.sh | 81 +- src/exchange-tools/.gitignore | 3 - src/exchange-tools/Makefile.am | 36 - src/exchange-tools/key-helper.c | 130 -- src/exchange-tools/taler-auditor-offline.c | 6 +- src/exchange-tools/taler-exchange-keyup.c | 1505 -------------------- src/exchange-tools/taler-exchange-wire.c | 225 --- src/exchange-tools/test_taler_exchange_httpd.conf | 130 -- .../.config/taler/test.json | 8 - .../share/taler/exchange/offline-keys/master.priv | 1 - 12 files changed, 110 insertions(+), 2083 deletions(-) delete mode 100644 src/exchange-tools/key-helper.c delete mode 100644 src/exchange-tools/taler-exchange-keyup.c delete mode 100644 src/exchange-tools/taler-exchange-wire.c delete mode 100644 src/exchange-tools/test_taler_exchange_httpd.conf delete mode 100644 src/exchange-tools/test_taler_exchange_httpd_home/.config/taler/test.json delete mode 100644 src/exchange-tools/test_taler_exchange_httpd_home/.local/share/taler/exchange/offline-keys/master.priv (limited to 'src') diff --git a/src/auditor/generate-auditor-basedb.conf b/src/auditor/generate-auditor-basedb.conf index a130aebec..a7a4e7c35 100644 --- a/src/auditor/generate-auditor-basedb.conf +++ b/src/auditor/generate-auditor-basedb.conf @@ -10,6 +10,7 @@ UNIXPATH_MODE = 660 PORT = 8081 BASE_URL = http://localhost:8081/ SIGNKEY_DURATION = 4 weeks +SIGNKEY_LEGAL_DURATION = 4 weeks LEGAL_DURATION = 2 years LOOKAHEAD_SIGN = 32 weeks 1 day LOOKAHEAD_PROVIDE = 4 weeks 1 day @@ -45,6 +46,7 @@ UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http UNIXPATH_MODE = 660 PORT = 8083 AUDITOR_URL = http://localhost:8083/ +BASE_URL = http://localhost:8083/ TINY_AMOUNT = TESTKUDOS:0.01 [PATHS] diff --git a/src/auditor/generate-auditor-basedb.sh b/src/auditor/generate-auditor-basedb.sh index c41d4a982..b934785f5 100755 --- a/src/auditor/generate-auditor-basedb.sh +++ b/src/auditor/generate-auditor-basedb.sh @@ -98,27 +98,18 @@ taler-config -c $CONF -s bank -o database -V postgres:///$TARGET_DB # setup exchange echo "Setting up exchange" taler-exchange-dbinit -c $CONF -taler-exchange-wire -c $CONF 2> taler-exchange-wire.log -taler-exchange-keyup -L INFO -c $CONF -o e2a.dat 2> taler-exchange-keyup.log # setup auditor echo "Setting up auditor" taler-auditor-dbinit -c $CONF taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL -taler-auditor-sign -c $CONF -u $AUDITOR_URL -r e2a.dat -o a2e.dat -m $MASTER_PUB -rm -f e2a.dat - -# provide auditor's signature to exchange -ABD=`taler-config -c $CONF -s EXCHANGEDB -o AUDITOR_BASE_DIR -f` -mkdir -p $ABD -mv a2e.dat $ABD # Launch services echo "Launching services" -taler-bank-manage-testing $CONF postgres:///$TARGET_DB serve & +taler-bank-manage-testing $CONF postgres:///$TARGET_DB serve &> taler-bank.log & TFN=`which taler-exchange-httpd` TBINPFX=`dirname $TFN` -TLIBEXEC=${BINPFX}/../lib/libexec/taler/ +TLIBEXEC=${TBINPFX}/../lib/taler/libexec/ $TLIBEXEC/taler-helper-crypto-eddsa -c $CONF 2> taler-helper-crypto-eddsa.log & $TLIBEXEC/taler-helper-crypto-rsa -c $CONF 2> taler-helper-crypto-rsa.log & taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log & @@ -126,6 +117,23 @@ taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log & taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log & taler-auditor-httpd -c $CONF 2> taler-auditor-httpd.log & +# Wait for all bank to be available (usually the slowest) +for n in `seq 1 50` +do + echo -n "." + sleep 0.2 + OK=0 + # bank + wget http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch services" +fi + # Wait for all services to be available for n in `seq 1 50` do @@ -133,11 +141,9 @@ do sleep 0.1 OK=0 # exchange - wget http://localhost:8081/ -o /dev/null -O /dev/null >/dev/null || continue + wget http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue # merchant wget http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue - # bank - wget http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue # Auditor wget http://localhost:8083/ -o /dev/null -O /dev/null >/dev/null || continue OK=1 @@ -148,9 +154,41 @@ if [ 1 != $OK ] then exit_skip "Failed to launch services" fi +echo " DONE" + +echo -n "Setting up keys" +taler-exchange-offline -c $CONF \ + download sign \ + enable-account payto://x-taler-bank/localhost/2 \ + wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \ + upload &> taler-exchange-offline.log + +echo -n "." + +for n in `seq 1 2` +do + echo -n "." + OK=0 + # bank + wget --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to setup keys" +fi + +taler-auditor-offline -c $CONF \ + download sign upload &> taler-auditor-offline.log + +echo " DONE" # Setup merchant +echo -n "Setting up merchant" + curl -H "Content-Type: application/json" -X POST -d '{"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_ms" : 3600000},"default_pay_delay":{"d_ms": 3600000}}' http://localhost:9966/private/instances diff --git a/src/auditor/generate-revoke-basedb.sh b/src/auditor/generate-revoke-basedb.sh index 3874e349b..cb48f524d 100755 --- a/src/auditor/generate-revoke-basedb.sh +++ b/src/auditor/generate-revoke-basedb.sh @@ -86,27 +86,17 @@ taler-config -c $CONF -s exchange -o REVOCATION_DIR -V "${TMP_DIR}/revdir/" # setup exchange echo "Setting up exchange" taler-exchange-dbinit -c $CONF -taler-exchange-wire -c $CONF 2> taler-exchange-wire.log -taler-exchange-keyup -L INFO -c $CONF -o e2a.dat 2> taler-exchange-keyup.log # setup auditor echo "Setting up auditor" taler-auditor-dbinit -c $CONF -taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL -taler-auditor-sign -c $CONF -u $AUDITOR_URL -r e2a.dat -o a2e.dat -m $MASTER_PUB -rm -f e2a.dat - -# provide auditor's signature to exchange -ABD=`taler-config -c $CONF -s EXCHANGEDB -o AUDITOR_BASE_DIR -f` -mkdir -p $ABD -mv a2e.dat $ABD # Launch services echo "Launching services" taler-bank-manage-testing $CONF postgres:///$TARGET_DB serve &> revocation-bank.log & TFN=`which taler-exchange-httpd` TBINPFX=`dirname $TFN` -TLIBEXEC=${BINPFX}/../lib/libexec/taler/ +TLIBEXEC=${TBINPFX}/../lib/taler/libexec/ $TLIBEXEC/taler-helper-crypto-eddsa -c $CONF 2> taler-helper-crypto-eddsa.log & $TLIBEXEC/taler-helper-crypto-rsa -c $CONF 2> taler-helper-crypto-rsa.log & taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log & @@ -127,6 +117,12 @@ do OK=1 break done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch services" +fi + # Wait for all other services to be available for n in `seq 1 50` do @@ -134,7 +130,7 @@ do sleep 0.1 OK=0 # exchange - wget http://localhost:8081/ -o /dev/null -O /dev/null >/dev/null || continue + wget http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue # merchant wget http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue # Auditor @@ -143,7 +139,6 @@ do break done - if [ 1 != $OK ] then cleanup @@ -151,7 +146,39 @@ then fi echo " DONE" +echo -n "Setting up keys" + +taler-exchange-offline -c $CONF \ + download sign \ + enable-account payto://x-taler-bank/localhost/2 \ + wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \ + upload &> taler-exchange-offline.log + +echo -n "." + +for n in `seq 1 2` +do + echo -n "." + OK=0 + # bank + wget --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to setup keys" +fi + + +taler-auditor-offline -c $CONF \ + download sign upload &> taler-auditor-offline.log + +echo " DONE" + # Setup merchant +echo -n "Setting up merchant" curl -H "Content-Type: application/json" -X POST -d '{"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_ms" : 3600000},"default_pay_delay":{"d_ms": 3600000}}' http://localhost:9966/private/instances @@ -186,15 +213,14 @@ echo "Revoking denomination ${rd} (to affect coin ${rc})" export susp=$(echo "$coins" | jq --arg rc "$rc" '[.coins[] | select(.coin_pub != $rc) | .coin_pub]') # Do the revocation -taler-exchange-keyup -o e2a2.dat -c $CONF -r $rd -taler-auditor-sign -c $CONF -u $AUDITOR_URL -r e2a2.dat -o a2e2.dat -m $MASTER_PUB -rm -f e2a2.dat -mv a2e2.dat $ABD +taler-exchange-offline -c $CONF \ + revoke-denomination "${rd}" upload &> taler-exchange-offline-revoke.log + +sleep 1 # Give exchange time to create replacmenent key -# Restart the exchange... -kill -SIGUSR1 $EXCHANGE_PID -sleep 1 # Give exchange time to re-scan data -echo "Restarted the exchange post revocation" +# Re-sign replacment keys +taler-auditor-offline -c $CONF \ + download sign upload &> taler-auditor-offline.log # Now we suspend the other coins, so later we will pay with the recouped coin taler-wallet-cli --wallet-db=$WALLET_DB advanced suspend-coins "$susp" @@ -280,15 +306,14 @@ export susp=$(echo "$coins" | jq --arg freshc "$freshc" '[.coins[] | select(.coi # Do the revocation of freshc echo "Revoking ${fresh_denom} (to affect coin ${freshc})" -taler-exchange-keyup -c $CONF -o e2a3.dat -r $fresh_denom -taler-auditor-sign -c $CONF -u $AUDITOR_URL -r e2a3.dat -o a2e3.dat -m $MASTER_PUB -rm -f e2a3.dat -mv a2e3.dat $ABD +taler-exchange-offline -c $CONF \ + revoke-denomination "${fresh_denom}" upload &> taler-exchange-offline-revoke-2.log -# Restart the exchange... -kill -SIGUSR1 $EXCHANGE_PID -sleep 1 # give exchange time to re-scan data +sleep 1 # Give exchange time to create replacmenent key +# Re-sign replacment keys +taler-auditor-offline -c $CONF \ + download sign upload &> taler-auditor-offline.log # Now we suspend the other coins, so later we will pay with the recouped coin taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB advanced suspend-coins "$susp" diff --git a/src/exchange-tools/.gitignore b/src/exchange-tools/.gitignore index 4d26c9c2c..bf45e9670 100644 --- a/src/exchange-tools/.gitignore +++ b/src/exchange-tools/.gitignore @@ -1,5 +1,2 @@ -test_taler_exchange_httpd_home/.local/share/taler/exchange/live-keys/ -test_taler_exchange_httpd_home/.local/share/taler/exchange/wirefees/ -test_taler_exchange_httpd_home/.config/taler/account-1.json taler-exchange-offline taler-auditor-offline diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am index 43954c446..82f4cbeb9 100644 --- a/src/exchange-tools/Makefile.am +++ b/src/exchange-tools/Makefile.am @@ -14,25 +14,9 @@ endif bin_PROGRAMS = \ taler-auditor-offline \ - taler-exchange-keyup \ taler-exchange-offline \ - taler-exchange-wire \ taler-exchange-dbinit -taler_exchange_keyup_SOURCES = \ - taler-exchange-keyup.c -taler_exchange_keyup_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ - $(top_builddir)/src/bank-lib/libtalerbank.la \ - $(top_builddir)/src/json/libtalerjson.la \ - $(top_builddir)/src/pq/libtalerpq.la \ - $(top_builddir)/src/util/libtalerutil.la \ - -lgnunetutil \ - $(XLIB) -taler_exchange_keyup_LDFLAGS = $(POSTGRESQL_LDFLAGS) - - taler_exchange_offline_SOURCES = \ taler-exchange-offline.c taler_exchange_offline_LDADD = \ @@ -46,7 +30,6 @@ taler_exchange_offline_LDADD = \ -lgnunetutil \ $(XLIB) - taler_auditor_offline_SOURCES = \ taler-auditor-offline.c taler_auditor_offline_LDADD = \ @@ -60,21 +43,6 @@ taler_auditor_offline_LDADD = \ -lgnunetutil \ $(XLIB) - -taler_exchange_wire_SOURCES = \ - taler-exchange-wire.c -taler_exchange_wire_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/json/libtalerjson.la \ - $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ - $(top_builddir)/src/bank-lib/libtalerbank.la \ - $(top_builddir)/src/util/libtalerutil.la \ - -lgnunetjson \ - -lgnunetutil \ - -ljansson \ - $(XLIB) -taler_exchange_wire_LDFLAGS = $(POSTGRESQL_LDFLAGS) - taler_exchange_dbinit_SOURCES = \ taler-exchange-dbinit.c taler_exchange_dbinit_LDADD = \ @@ -99,8 +67,4 @@ AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH= # Distribution EXTRA_DIST = \ - test_taler_exchange_httpd_home/.local/share/taler/exchange/offline-keys/master.priv \ - test_taler_exchange_httpd.conf \ - key-helper.c \ - $(check_SCRIPTS) \ $(pkgcfg_DATA) diff --git a/src/exchange-tools/key-helper.c b/src/exchange-tools/key-helper.c deleted file mode 100644 index 9fd7d50a6..000000000 --- a/src/exchange-tools/key-helper.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2020 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - 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 -*/ -/** - * @file key-helper.c - * @brief shared logic between tools that deal with the master private key - * @author Christian Grothoff - */ - -/** - * Extract the @a master_priv from the @a cfg or @a masterkeyfile and - * verify that it matches the master public key given in @a cfg. - * - * @param cfg configuration to use - * @param masterkeyfile master private key filename, can be NULL to use from @a cfg - * @param[out] master_priv where to store the master private key on success - * @return #GNUNET_OK on success, #GNUNET_SYSERR on failures - */ -static int -get_and_check_master_key (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *masterkeyfile, - struct TALER_MasterPrivateKeyP *master_priv) -{ - struct GNUNET_CRYPTO_EddsaPublicKey mpub; - struct GNUNET_CRYPTO_EddsaPublicKey mpub_cfg; - char *fn; - - if (NULL != masterkeyfile) - { - fn = GNUNET_strdup (masterkeyfile); - } - else - { - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, - "exchange", - "MASTER_PRIV_FILE", - &fn)) - { - fprintf (stderr, - "Master private key file given neither in configuration nor on command-line\n"); - return GNUNET_SYSERR; - } - } - if (GNUNET_YES != - GNUNET_DISK_file_test (fn)) - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Exchange master private key `%s' does not exist yet, creating it!\n", - fn); - { - int ret; - - ret = GNUNET_CRYPTO_eddsa_key_from_file (fn, - GNUNET_YES, - &master_priv->eddsa_priv); - if (GNUNET_SYSERR == ret) - { - fprintf (stderr, - "Failed to initialize master key from file `%s': %s\n", - fn, - "could not create file"); - GNUNET_free (fn); - return GNUNET_SYSERR; - } - GNUNET_CRYPTO_eddsa_key_get_public (&master_priv->eddsa_priv, - &mpub); - } - - /* Check our key matches that in the configuration */ - { - char *masters; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "exchange", - "MASTER_PUBLIC_KEY", - &masters)) - { - /* Help user by telling them precisely what to fix */ - masters = GNUNET_STRINGS_data_to_string_alloc (&mpub, - sizeof (mpub)); - fprintf (stderr, - "You must set MASTER_PUBLIC_KEY to `%s' in the [exchange] section of the configuration before proceeding.\n", - masters); - GNUNET_free (masters); - GNUNET_free (fn); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (masters, - strlen (masters), - &mpub_cfg, - sizeof (mpub_cfg))) - { - fprintf (stderr, - "MASTER_PUBLIC_KEY value `%s' specified in section [exchange] of the configuration is not a valid public key\n", - masters); - GNUNET_free (masters); - GNUNET_free (fn); - return GNUNET_SYSERR; - } - if (0 != GNUNET_memcmp (&mpub, - &mpub_cfg)) - { - fprintf (stderr, - "MASTER_PUBLIC_KEY value `%s' specified in section [exchange] of the configuration does not match our master private key. You can use `gnunet-ecc -p \"%s\"' to determine the correct value.\n", - masters, - fn); - GNUNET_free (masters); - GNUNET_free (fn); - return GNUNET_SYSERR; - } - GNUNET_free (masters); - } - GNUNET_free (fn); - - return GNUNET_OK; -} diff --git a/src/exchange-tools/taler-auditor-offline.c b/src/exchange-tools/taler-auditor-offline.c index 18d7360cc..5e9e68823 100644 --- a/src/exchange-tools/taler-auditor-offline.c +++ b/src/exchange-tools/taler-auditor-offline.c @@ -417,7 +417,7 @@ upload_denomination_add (const char *exchange_url, &err_line)) { fprintf (stderr, - "Invalid input for adding wire account: %s#%u at %u (skipping)\n", + "Invalid input for adding denomination: %s#%u at %u (skipping)\n", err_name, err_line, (unsigned int) idx); @@ -996,8 +996,8 @@ sign_denomkeys (const json_t *denomkeys) &auditor_priv, &auditor_sig); output_operation ("sign-denomination", - json_pack ("{s:o,s:o}", - "h_denomn_pub", + json_pack ("{s:o, s:o}", + "h_denom_pub", GNUNET_JSON_from_data_auto (&h_denom_pub), "auditor_sig", GNUNET_JSON_from_data_auto (&auditor_sig))); diff --git a/src/exchange-tools/taler-exchange-keyup.c b/src/exchange-tools/taler-exchange-keyup.c deleted file mode 100644 index 074499aef..000000000 --- a/src/exchange-tools/taler-exchange-keyup.c +++ /dev/null @@ -1,1505 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - 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 -*/ -/** - * @file taler-exchange-keyup.c - * @brief Update the exchange's keys for coins and online signing keys, - * using the exchange's offline master key. - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#include -#include "taler_exchangedb_lib.h" - - -/** - * When generating filenames from a cryptographic hash, we do not use all 512 - * bits but cut off after this number of characters (in base32-encoding). - * Base32 is 5 bit per character, and given that we have very few coin types, - * at 100 bits the chance of collision (by accident over such a tiny set) is - * negligible. (Also, some file-systems do not support very long file names.) - */ -#define HASH_CUTOFF 20 - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Struct with all of the meta data about a denomination. Hashed - * to generate a unique directory name per coin type. - */ -struct DenominationNBOP -{ - /** - * How long are the signatures legally valid? - */ - struct GNUNET_TIME_RelativeNBO duration_legal; - - /** - * How long can the coins be spend? - */ - struct GNUNET_TIME_RelativeNBO duration_spend; - - /** - * How long can coins be withdrawn (generated)? - */ - struct GNUNET_TIME_RelativeNBO duration_withdraw; - - /** - * What is the value of each coin? - */ - struct TALER_AmountNBO value; - - /** - * What is the fee charged for withdrawal? - */ - struct TALER_AmountNBO fee_withdraw; - - /** - * What is the fee charged for deposits? - */ - struct TALER_AmountNBO fee_deposit; - - /** - * What is the fee charged for melting? - */ - struct TALER_AmountNBO fee_refresh; - - /** - * What is the fee charged for refunds? - */ - struct TALER_AmountNBO fee_refund; - - /** - * Key size (in NBO). - */ - uint32_t rsa_keysize; -}; - -GNUNET_NETWORK_STRUCT_END - -/** - * Set of all of the parameters that characterize a denomination. - */ -struct DenominationParameters -{ - - /** - * How long are the signatures legally valid? Should be - * significantly larger than @e duration_spend (i.e. years). - */ - struct GNUNET_TIME_Relative duration_legal; - - /** - * How long can the coins be spend? Should be significantly - * larger than @e duration_withdraw (i.e. years). - */ - struct GNUNET_TIME_Relative duration_spend; - - /** - * How long can coins be withdrawn (generated)? Should be small - * enough to limit how many coins will be signed into existence with - * the same key, but large enough to still provide a reasonable - * anonymity set. - */ - struct GNUNET_TIME_Relative duration_withdraw; - - /** - * What is the value of each coin? - */ - struct TALER_Amount value; - - /** - * What is the fee charged for withdrawal? - */ - struct TALER_Amount fee_withdraw; - - /** - * What is the fee charged for deposits? - */ - struct TALER_Amount fee_deposit; - - /** - * What is the fee charged for melting? - */ - struct TALER_Amount fee_refresh; - - /** - * What is the fee charged for refunds? - */ - struct TALER_Amount fee_refund; - - /** - * Time at which this coin is supposed to become valid. - */ - struct GNUNET_TIME_Absolute anchor; - - /** - * Length of the RSA key (in bits). - */ - uint32_t rsa_keysize; -}; - - -/** - * How much should coin creation (@e duration_withdraw) duration overlap - * with the next denomination? Basically, the starting time of two - * denominations is always @e duration_withdraw - #duration_overlap apart. - */ -static struct GNUNET_TIME_Relative duration_overlap; - -/** - * The configured currency. - */ -static char *currency; - -/** - * Filename of the master private key. - */ -static char *masterkeyfile; - -/** - * Filename where to write denomination key signing - * requests for the auditor (optional, can be NULL). - */ -static char *auditorrequestfile; - -/** - * Handle for writing the output for the auditor. - */ -static FILE *auditor_output_file; - -/** - * Director of the exchange, containing the keys. - */ -static char *exchange_directory; - -/** - * Directory where we should write the wire transfer fee structure. - */ -static char *feedir; - -/** - * Handle to the exchange's configuration - */ -static const struct GNUNET_CONFIGURATION_Handle *kcfg; - -/** - * Time when the key update is executed. - * Either the actual current time, or a pretended time. - */ -static struct GNUNET_TIME_Absolute now; - -/** - * The time for the key update, as passed by the user - * on the command line. - */ -static struct GNUNET_TIME_Absolute now_tmp; - -/** - * Master private key of the exchange. - */ -static struct TALER_MasterPrivateKeyP master_priv; - -/** - * Master public key of the exchange. - */ -static struct TALER_MasterPublicKeyP master_public_key; - -/** - * Until what time do we provide keys? - */ -static struct GNUNET_TIME_Absolute lookahead_sign_stamp; - -/** - * Largest duration for spending of any key. - */ -static struct GNUNET_TIME_Relative max_duration_spend; - -/** - * Revoke denomination key identified by this hash (if non-zero). - */ -static struct GNUNET_HashCode revoke_dkh; - -/** - * Which RSA key size should we use for replacement keys after revocation? - * (Useful because maybe that's the one option one might usefully want to - * change when replacing a key.) - */ -static unsigned int replacement_key_size = 2048; - -/** - * Return value from main(). - */ -static int global_ret; - - -#include "key-helper.c" - -/** - * Hash the data defining a denomination type. Exclude information that may - * not be the same for all instances of the denomination's type (i.e. the - * anchor, overlap). - * - * @param p denomination parameters to convert to a hash - * @param[out] hash set to the hash matching @a p - */ -static void -hash_denomination_parameters (const struct DenominationParameters *p, - struct GNUNET_HashCode *hash) -{ - struct DenominationNBOP p_nbo; - - memset (&p_nbo, - 0, - sizeof (struct DenominationNBOP)); - p_nbo.duration_spend = GNUNET_TIME_relative_hton (p->duration_spend); - p_nbo.duration_legal = GNUNET_TIME_relative_hton (p->duration_legal); - p_nbo.duration_withdraw = GNUNET_TIME_relative_hton (p->duration_withdraw); - TALER_amount_hton (&p_nbo.value, - &p->value); - TALER_amount_hton (&p_nbo.fee_withdraw, - &p->fee_withdraw); - TALER_amount_hton (&p_nbo.fee_deposit, - &p->fee_deposit); - TALER_amount_hton (&p_nbo.fee_refresh, - &p->fee_refresh); - TALER_amount_hton (&p_nbo.fee_refund, - &p->fee_refund); - p_nbo.rsa_keysize = htonl (p->rsa_keysize); - GNUNET_CRYPTO_hash (&p_nbo, - sizeof (struct DenominationNBOP), - hash); -} - - -/** - * Obtain the name of the directory we should use to store denominations of - * the given type. The directory name has the format - * "$EXCHANGEDIR/$VALUE/$HASH/" where "$VALUE" represents the value of the - * coins and "$HASH" encodes all of the denomination's parameters, generating - * a unique string for each type of denomination. Note that the "$HASH" - * includes neither the absolute creation time nor the key of the - * denomination, thus the files in the subdirectory really just refer to the - * same type of denominations, not the same denomination. - * - * @param p denomination parameters to convert to a directory name - * @return directory name (valid until next call to this function) - */ -static const char * -get_denomination_dir (const struct DenominationParameters *p) -{ - static char dir[4096]; - struct GNUNET_HashCode hash; - char *hash_str; - char *val_str; - - hash_denomination_parameters (p, - &hash); - hash_str = GNUNET_STRINGS_data_to_string_alloc (&hash, - sizeof (struct - GNUNET_HashCode)); - GNUNET_assert (NULL != hash_str); - GNUNET_assert (HASH_CUTOFF <= strlen (hash_str) + 1); - hash_str[HASH_CUTOFF] = 0; - - val_str = TALER_amount_to_string (&p->value); - GNUNET_assert (NULL != val_str); - for (size_t i = 0; i < strlen (val_str); i++) - if ( (':' == val_str[i]) || - ('.' == val_str[i]) ) - val_str[i] = '_'; - - GNUNET_snprintf (dir, - sizeof (dir), - "%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS - DIR_SEPARATOR_STR "%s-%s", - exchange_directory, - val_str, - hash_str); - GNUNET_free (hash_str); - GNUNET_free (val_str); - return dir; -} - - -/** - * Obtain the name of the file we would use to store the key - * information for a denomination of the given type @a p and validity - * start time @a start - * - * @param p parameters for the denomination - * @param start when would the denomination begin to be issued - * @return name of the file to use for this denomination - * (valid until next call to this function) - */ -static const char * -get_denomination_type_file (const struct DenominationParameters *p, - struct GNUNET_TIME_Absolute start) -{ - static char filename[4096]; - const char *dir; - - dir = get_denomination_dir (p); - GNUNET_snprintf (filename, - sizeof (filename), - "%s" DIR_SEPARATOR_STR "%llu", - dir, - (unsigned long long) start.abs_value_us); - return filename; -} - - -/** - * Get the latest key file from a past run of the key generation - * tool. Used to calculate the starting time for the keys we - * generate during this invocation. This function is used to - * handle both signing keys and denomination keys, as in both cases - * the filenames correspond to the timestamps we need. - * - * @param cls closure, a `struct GNUNET_TIME_Absolute *`, updated - * to contain the highest timestamp (below #now) - * that was found - * @param filename complete filename (absolute path) - * @return #GNUNET_OK (to continue to iterate) - */ -static int -get_anchor_iter (void *cls, - const char *filename) -{ - struct GNUNET_TIME_Absolute *anchor = cls; - struct GNUNET_TIME_Absolute stamp; - const char *base; - char *end = NULL; - long long int bval; - - base = GNUNET_STRINGS_get_short_name (filename); - bval = strtoll (base, - &end, - 10); - if ( (NULL == end) || - (0 != *end) || - (0 > bval) ) - { - fprintf (stderr, - "Ignoring unexpected file `%s'.\n", - filename); - return GNUNET_OK; - } - stamp.abs_value_us = (uint64_t) bval; - *anchor = GNUNET_TIME_absolute_max (stamp, - *anchor); - return GNUNET_OK; -} - - -/** - * Get the timestamp where the first new key should be generated. - * Relies on correctly named key files (as we do not parse them, - * but just look at the filenames to "guess" at their contents). - * - * @param dir directory that should contain the existing keys - * @param duration how long is one key valid (for signing)? - * @param overlap what's the overlap between the keys validity period? - * @param[out] anchor the timestamp where the first new key should be generated - */ -static void -get_anchor (const char *dir, - struct GNUNET_TIME_Relative duration, - struct GNUNET_TIME_Relative overlap, - struct GNUNET_TIME_Absolute *anchor) -{ - GNUNET_assert (0 == duration.rel_value_us % 1000000); - GNUNET_assert (0 == overlap.rel_value_us % 1000000); - if (GNUNET_YES != - GNUNET_DISK_directory_test (dir, - GNUNET_YES)) - { - *anchor = now; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "No existing keys found, starting with fresh key set.\n"); - return; - } - *anchor = GNUNET_TIME_UNIT_ZERO_ABS; - if (-1 == - GNUNET_DISK_directory_scan (dir, - &get_anchor_iter, - anchor)) - { - *anchor = now; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "No existing keys found, starting with fresh key set.\n"); - return; - } - - if ((GNUNET_TIME_absolute_add (*anchor, - duration)).abs_value_us < now.abs_value_us) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Existing keys are way too old, starting with fresh key set.\n"); - *anchor = now; - } - else if (anchor->abs_value_us != now.abs_value_us) - { - *anchor = GNUNET_TIME_absolute_add (*anchor, - duration); - *anchor = GNUNET_TIME_absolute_subtract (*anchor, - overlap); - } - - /* anchor is now the stamp where we need to create a new key */ -} - - -/** - * Create a exchange signing key (for signing exchange messages, not for - * signing coins) and assert its correctness by signing it with the master - * key. - * - * @param start start time of the validity period for the key - * @param duration how long should the key be valid - * @param end when do all signatures by this key expire - * @param[out] pi set to the signing key information - */ -static void -create_signkey_issue_priv ( - struct GNUNET_TIME_Absolute start, - struct GNUNET_TIME_Relative duration, - struct GNUNET_TIME_Absolute end, - struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *pi) -{ - struct TALER_ExchangeSigningKeyValidityPS *issue = &pi->issue; - - GNUNET_CRYPTO_eddsa_key_create (&pi->signkey_priv.eddsa_priv); - issue->master_public_key = master_public_key; - issue->start = GNUNET_TIME_absolute_hton (start); - issue->expire = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (start, - duration)); - issue->end = GNUNET_TIME_absolute_hton (end); - GNUNET_CRYPTO_eddsa_key_get_public (&pi->signkey_priv.eddsa_priv, - &issue->signkey_pub.eddsa_pub); - issue->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY); - issue->purpose.size = htonl (sizeof (struct - TALER_ExchangeSigningKeyValidityPS)); - GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv, - issue, - &pi->master_sig.eddsa_signature); -} - - -/** - * Generate signing keys starting from the last key found to - * the lookahead time. - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -exchange_keys_update_signkeys (void) -{ - struct GNUNET_TIME_Relative signkey_duration; - struct GNUNET_TIME_Relative legal_duration; - struct GNUNET_TIME_Absolute anchor; - char *signkey_dir; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - "exchange", - "SIGNKEY_DURATION", - &signkey_duration)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "SIGNKEY_DURATION"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - "exchange", - "LEGAL_DURATION", - &legal_duration)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "LEGAL_DURATION", - "fails to specify valid timeframe"); - return GNUNET_SYSERR; - } - if (signkey_duration.rel_value_us > legal_duration.rel_value_us) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "LEGAL_DURATION", - "Value given for LEGAL_DURATION must be longer than value for SIGNKEY_DURATION"); - return GNUNET_SYSERR; - } - GNUNET_TIME_round_rel (&signkey_duration); - GNUNET_asprintf (&signkey_dir, - "%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_SIGNING_KEYS, - exchange_directory); - /* make sure the directory exists */ - if (GNUNET_OK != - GNUNET_DISK_directory_create (signkey_dir)) - { - fprintf (stderr, - "Failed to create signing key directory\n"); - GNUNET_free (signkey_dir); - return GNUNET_SYSERR; - } - - get_anchor (signkey_dir, - signkey_duration, - GNUNET_TIME_UNIT_ZERO /* no overlap for signing keys */, - &anchor); - GNUNET_free (signkey_dir); - - while (anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) - { - struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP signkey_issue; - struct GNUNET_TIME_Absolute end; - - end = GNUNET_TIME_absolute_add (anchor, - legal_duration); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Generating signing key for %s.\n", - GNUNET_STRINGS_absolute_time_to_string (anchor)); - create_signkey_issue_priv (anchor, - signkey_duration, - end, - &signkey_issue); - if (GNUNET_OK != - TALER_EXCHANGEDB_signing_key_write (exchange_directory, - anchor, - &signkey_issue)) - return GNUNET_SYSERR; - anchor = GNUNET_TIME_absolute_add (anchor, - signkey_duration); - } - return GNUNET_OK; -} - - -/** - * Parse configuration for denomination type parameters. Also determines - * our anchor by looking at the existing denominations of the same type. - * - * @param ct section in the configuration file giving the denomination type parameters - * @param[out] params set to the denomination parameters from the configuration - * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid - */ -static int -get_denomination_type_params (const char *ct, - struct DenominationParameters *params) -{ - const char *dir; - unsigned long long rsa_keysize; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - ct, - "DURATION_WITHDRAW", - ¶ms->duration_withdraw)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "DURATION_WITHDRAW"); - return GNUNET_SYSERR; - } - GNUNET_TIME_round_rel (¶ms->duration_withdraw); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - ct, - "DURATION_SPEND", - ¶ms->duration_spend)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "DURATION_SPEND"); - 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, - "DURATION_LEGAL", - ¶ms->duration_legal)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "DURATION_LEGAL"); - return GNUNET_SYSERR; - } - GNUNET_TIME_round_rel (¶ms->duration_legal); - if (duration_overlap.rel_value_us >= - params->duration_withdraw.rel_value_us) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "exchangedb", - "DURATION_OVERLAP", - "Value given for DURATION_OVERLAP must be smaller than value for DURATION_WITHDRAW!"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (kcfg, - ct, - "rsa_keysize", - &rsa_keysize)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "rsa_keysize"); - return GNUNET_SYSERR; - } - if ( (rsa_keysize > 4 * 2048) || - (rsa_keysize < 1024) ) - { - fprintf (stderr, - "Given RSA keysize %llu outside of permitted range\n", - rsa_keysize); - return GNUNET_SYSERR; - } - params->rsa_keysize = (unsigned int) rsa_keysize; - if (GNUNET_OK != - TALER_config_get_amount (kcfg, - ct, - "VALUE", - ¶ms->value)) - { - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_amount (kcfg, - ct, - "FEE_WITHDRAW", - ¶ms->fee_withdraw)) - { - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_amount (kcfg, - ct, - "FEE_DEPOSIT", - ¶ms->fee_deposit)) - { - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_amount (kcfg, - ct, - "FEE_REFRESH", - ¶ms->fee_refresh)) - { - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_amount (kcfg, - ct, - "fee_refund", - ¶ms->fee_refund)) - { - return GNUNET_SYSERR; - } - - dir = get_denomination_dir (params); - get_anchor (dir, - params->duration_withdraw, - duration_overlap, - ¶ms->anchor); - - /** - * The "anchor" is merely the latest denom key filename - * converted to a GNUnet absolute time. - */ - - return GNUNET_OK; -} - - -/** - * Initialize the private and public key information structure for - * signing coins into existence. Generates the private signing key - * and signes it together with the denomination's meta data using the master - * signing key. - * - * @param params parameters used to initialize the @a dki - * @param[out] dki initialized according to @a params - */ -static void -create_denomkey_issue ( - const struct DenominationParameters *params, - struct TALER_EXCHANGEDB_DenominationKey *dki) -{ - dki->denom_priv.rsa_private_key - = GNUNET_CRYPTO_rsa_private_key_create (params->rsa_keysize); - GNUNET_assert (NULL != dki->denom_priv.rsa_private_key); - dki->denom_pub.rsa_public_key - = GNUNET_CRYPTO_rsa_private_key_get_public ( - dki->denom_priv.rsa_private_key); - GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key, - &dki->issue.properties.denom_hash); - dki->issue.properties.master = master_public_key; - dki->issue.properties.start = GNUNET_TIME_absolute_hton (params->anchor); - dki->issue.properties.expire_withdraw = - GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor, - params-> - duration_withdraw)); - dki->issue.properties.expire_deposit = - GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor, - params->duration_spend)); - dki->issue.properties.expire_legal = - GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor, - params->duration_legal)); - TALER_amount_hton (&dki->issue.properties.value, - ¶ms->value); - TALER_amount_hton (&dki->issue.properties.fee_withdraw, - ¶ms->fee_withdraw); - TALER_amount_hton (&dki->issue.properties.fee_deposit, - ¶ms->fee_deposit); - TALER_amount_hton (&dki->issue.properties.fee_refresh, - ¶ms->fee_refresh); - TALER_amount_hton (&dki->issue.properties.fee_refund, - ¶ms->fee_refund); - dki->issue.properties.purpose.purpose - = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY); - dki->issue.properties.purpose.size - = htonl (sizeof (struct TALER_DenominationKeyValidityPS)); - GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv, - &dki->issue.properties, - &dki->issue.signature.eddsa_signature); -} - - -/** - * Write the @a denomkey_issue to file @a dkf and also (if applicable) - * dump the properties to the #auditor_output_file. - * - * @param dkf where to write the @a denomkey_issue - * @param denomkey_issue data to write - * @return #GNUNET_OK on success - */ -static int -write_denomkey_issue ( - const char *dkf, - const struct TALER_EXCHANGEDB_DenominationKey *denomkey_issue) -{ - if (GNUNET_OK != - TALER_EXCHANGEDB_denomination_key_write (dkf, - denomkey_issue)) - { - fprintf (stderr, - "Failed to write denomination key information to file `%s'.\n", - dkf); - return GNUNET_SYSERR; - } - if ( (NULL != auditor_output_file) && - (1 != - fwrite (&denomkey_issue->issue.properties, - sizeof (struct TALER_DenominationKeyValidityPS), - 1, - auditor_output_file)) ) - { - fprintf (stderr, - "Failed to write denomination key information to %s: %s\n", - auditorrequestfile, - strerror (errno)); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Generate new denomination signing keys for the denomination type of the given @a - * denomination_alias. - * - * @param cls a `int *`, to be set to #GNUNET_SYSERR on failure - * @param denomination_alias name of the denomination's section in the configuration - */ -static void -exchange_keys_update_denominationtype (void *cls, - const char *denomination_alias) -{ - int *ret = cls; - struct DenominationParameters p; - const char *dkf; - struct TALER_EXCHANGEDB_DenominationKey denomkey_issue; - - if (0 != strncasecmp (denomination_alias, - "coin_", - strlen ("coin_"))) - return; /* not a denomination type definition */ - if (GNUNET_OK != - get_denomination_type_params (denomination_alias, - &p)) - { - *ret = GNUNET_SYSERR; - return; - } - /* p has the right anchor now = latest denom filename converted to time. */ - if (GNUNET_OK != - GNUNET_DISK_directory_create (get_denomination_dir (&p))) - { - *ret = GNUNET_SYSERR; - return; - } - - while (p.anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Future time not covered yet for type `%s': %s\n", - denomination_alias, - GNUNET_STRINGS_relative_time_to_string - (GNUNET_TIME_absolute_get_difference (p.anchor, - lookahead_sign_stamp), - GNUNET_NO)); - dkf = get_denomination_type_file (&p, - p.anchor); - GNUNET_break (GNUNET_YES != - GNUNET_DISK_file_test (dkf)); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Generating denomination key for type `%s', start %s at %s\n", - denomination_alias, - GNUNET_STRINGS_absolute_time_to_string (p.anchor), - dkf); - create_denomkey_issue (&p, - &denomkey_issue); - *ret = write_denomkey_issue (dkf, - &denomkey_issue); - GNUNET_CRYPTO_rsa_private_key_free ( - denomkey_issue.denom_priv.rsa_private_key); - GNUNET_CRYPTO_rsa_public_key_free (denomkey_issue.denom_pub.rsa_public_key); - if (GNUNET_OK != *ret) - return; /* stop loop, hard error */ - p.anchor = GNUNET_TIME_absolute_add (p.anchor, - p.duration_withdraw); - p.anchor = GNUNET_TIME_absolute_subtract (p.anchor, - duration_overlap); - } -} - - -/** - * Update all of the denomination keys of the exchange. - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -exchange_keys_update_denomkeys (void) -{ - int ok; - - ok = GNUNET_OK; - GNUNET_CONFIGURATION_iterate_sections (kcfg, - &exchange_keys_update_denominationtype, - &ok); - return ok; -} - - -/** - * Sign @a af with @a priv - * - * @param[in,out] af fee structure to sign - * @param method name of the wire method for which we sign - * @param priv private key to use for signing - */ -static void -sign_af (struct TALER_EXCHANGEDB_AggregateFees *af, - const char *method, - const struct GNUNET_CRYPTO_EddsaPrivateKey *priv) -{ - struct TALER_MasterWireFeePS wf; - - TALER_EXCHANGEDB_fees_2_wf (method, - af, - &wf); - GNUNET_CRYPTO_eddsa_sign (priv, - &wf, - &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; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Setting up wire fees for `%s'\n", - wiremethod); - last_date = GNUNET_TIME_absolute_add (lookahead_sign_stamp, - max_duration_spend); - GNUNET_asprintf (§ion, - "fees-%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; - - 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; - - /* handle wire fee */ - GNUNET_asprintf (&opt, - "wire-fee-%u", - year); - if ( (GNUNET_OK != - TALER_config_get_amount (kcfg, - section, - opt, - &af->wire_fee)) || - (0 != strcasecmp (currency, - af->wire_fee.currency)) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Need amount with currency `%s' for option `%s' in section `%s'\n", - currency, - opt, - section); - *ret = GNUNET_SYSERR; - GNUNET_free (opt); - break; - } - GNUNET_free (opt); - - /* handle closing fee */ - GNUNET_asprintf (&opt, - "closing-fee-%u", - year); - if ( (GNUNET_OK != - TALER_config_get_amount (kcfg, - section, - opt, - &af->closing_fee)) || - (0 != strcasecmp (currency, - af->closing_fee.currency)) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Need amount with currency `%s' for option `%s' in section `%s'\n", - currency, - opt, - section); - *ret = GNUNET_SYSERR; - GNUNET_free (opt); - break; - } - - GNUNET_free (opt); - sign_af (af, - wiremethod, - &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, - wiremethod, - 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. - * - * @param cls pointer to `int`, set to #GNUNET_SYSERR on error - * @param ai information about enabled accounts - */ -static void -create_wire_fee_by_account (void *cls, - const struct TALER_EXCHANGEDB_AccountInfo *ai) -{ - int *ret = cls; - - if (GNUNET_NO == ai->credit_enabled) - return; - /* We may call this function repeatedly for the same method - if there are multiple accounts with plugins using the - same method, but except for some minor performance loss, - this is harmless. */ - create_wire_fee_for_method (ret, - ai->method); -} - - -/** - * 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 (void) -{ - int ret; - - ret = GNUNET_OK; - TALER_EXCHANGEDB_find_accounts (kcfg, - &create_wire_fee_by_account, - &ret); - return ret; -} - - -/** - * Check if the denomination that we just revoked is currently active, - * and if so, generate a replacement key. - * - * @param cls closure with the revoked denomination key hash, a `struct GNUNET_HashCode *` - * @param alias coin alias - * @param dki the denomination key - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -static int -check_revocation_regeneration ( - void *cls, - const char *alias, - const struct TALER_EXCHANGEDB_DenominationKey *dki) -{ - const struct GNUNET_HashCode *denom_hash = cls; - struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Absolute withdraw_end; - - (void) alias; - if (0 != - GNUNET_memcmp (denom_hash, - &dki->issue.properties.denom_hash)) - return GNUNET_OK; /* does not match */ - now = GNUNET_TIME_absolute_get (); - withdraw_end = GNUNET_TIME_absolute_ntoh ( - dki->issue.properties.expire_withdraw); - if (now.abs_value_us >= withdraw_end.abs_value_us) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Revoked denomination key has expired, no need to create a replacement\n"); - return GNUNET_NO; - } - - { - struct GNUNET_TIME_Absolute anchor - = GNUNET_TIME_absolute_ntoh (dki->issue.properties.start); - struct TALER_EXCHANGEDB_DenominationKey dki_new; - const char *dkf; - int ret; - struct DenominationParameters dp = { - .duration_legal - = GNUNET_TIME_absolute_get_difference - (anchor, - GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_legal)), - .duration_spend - = GNUNET_TIME_absolute_get_difference - (anchor, - GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_deposit)), - .duration_withdraw - = GNUNET_TIME_absolute_get_difference - (anchor, - GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_withdraw)), - .anchor = anchor, - .rsa_keysize = replacement_key_size - }; - char *dkfi; - - TALER_amount_ntoh (&dp.value, - &dki->issue.properties.value); - TALER_amount_ntoh (&dp.fee_withdraw, - &dki->issue.properties.fee_withdraw); - TALER_amount_ntoh (&dp.fee_deposit, - &dki->issue.properties.fee_deposit); - TALER_amount_ntoh (&dp.fee_refresh, - &dki->issue.properties.fee_refresh); - TALER_amount_ntoh (&dp.fee_refund, - &dki->issue.properties.fee_refund); - - /* find unused file name for revocation file by appending -%u */ - dkf = get_denomination_type_file (&dp, - dp.anchor); - for (unsigned int i = 1;; i++) - { - GNUNET_asprintf (&dkfi, - "%s-%u", - dkf, - i); - if (GNUNET_YES != GNUNET_DISK_file_test (dkfi)) - break; - GNUNET_free (dkfi); - } - - create_denomkey_issue (&dp, - &dki_new); - ret = write_denomkey_issue (dkfi, - &dki_new); - GNUNET_free (dkfi); - GNUNET_CRYPTO_rsa_private_key_free (dki_new.denom_priv.rsa_private_key); - GNUNET_CRYPTO_rsa_public_key_free (dki_new.denom_pub.rsa_public_key); - if (GNUNET_OK != ret) - return GNUNET_SYSERR; - } - - return GNUNET_NO; -} - - -/** - * Revoke the denomination key matching @a hc and request /recoup to be - * initiated. - * - * @param hc denomination key hash to revoke - * @return #GNUNET_OK on success, - * #GNUNET_NO if @a hc was not found - * #GNUNET_SYSERR on error - */ -static int -revoke_denomination (const struct GNUNET_HashCode *hc) -{ - { - char *basedir; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (kcfg, - "exchange", - "REVOCATION_DIR", - &basedir)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "REVOCATION_DIR"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_EXCHANGEDB_denomination_key_revoke (basedir, - hc, - &master_priv)) - { - GNUNET_free (basedir); - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_free (basedir); - } - - if (GNUNET_SYSERR == - TALER_EXCHANGEDB_denomination_keys_iterate (exchange_directory, - &check_revocation_regeneration, - (void *) hc)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Might have failed to generate replacement for revoked denomination key!\n"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Main function that will be run. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param cfg configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TIME_Relative lookahead_sign; - - (void) cls; - (void) args; - (void) cfgfile; - kcfg = cfg; - if (GNUNET_OK != - TALER_config_get_currency (cfg, - ¤cy)) - { - global_ret = 1; - return; - } - if (now.abs_value_us != now_tmp.abs_value_us) - { - /* The user gave "--now", use it! */ - now = now_tmp; - } - else - { - /* get current time again, we may be timetraveling! */ - now = GNUNET_TIME_absolute_get (); - } - GNUNET_TIME_round_abs (&now); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - "exchangedb", - "DURATION_OVERLAP", - &duration_overlap)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchangedb", - "DURATION_OVERLAP"); - global_ret = 1; - return; - } - GNUNET_TIME_round_rel (&duration_overlap); - - if (NULL == feedir) - { - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (kcfg, - "exchangedb", - "WIREFEE_BASE_DIR", - &feedir)) - { - fprintf (stderr, - "Wire fee directory given neither in configuration nor on 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; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (kcfg, - "exchange", - "KEYDIR", - &exchange_directory)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "KEYDIR"); - global_ret = 1; - return; - } - - if (GNUNET_OK != - get_and_check_master_key (kcfg, - masterkeyfile, - &master_priv)) - { - global_ret = 1; - return; - } - GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv, - &master_public_key.eddsa_pub); - - if (NULL != auditorrequestfile) - { - auditor_output_file = fopen (auditorrequestfile, - "w"); - if (NULL == auditor_output_file) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open (w)", - auditorrequestfile); - global_ret = 1; - return; - } - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - "exchange", - "LOOKAHEAD_SIGN", - &lookahead_sign)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "LOOKAHEAD_SIGN"); - global_ret = 1; - return; - } - if (0 == lookahead_sign.rel_value_us) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "LOOKAHEAD_SIGN", - "must not be zero"); - global_ret = 1; - return; - } - GNUNET_TIME_round_rel (&lookahead_sign); - lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, - lookahead_sign); - - - /* finally, do actual work */ - if (GNUNET_NO == GNUNET_is_zero (&revoke_dkh)) - { - if (GNUNET_OK != revoke_denomination (&revoke_dkh)) - { - global_ret = 1; - return; - } - /* if we were invoked to revoke a key, let's not also generate - new keys, as that might not be desired. */ - return; - } - - if (NULL == auditor_output_file) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Option `-o' missing. Hence, you will NOT be able to use an auditor with the generated keys!\n"); - - if (GNUNET_OK != exchange_keys_update_signkeys ()) - { - global_ret = 1; - return; - } - if (GNUNET_OK != exchange_keys_update_denomkeys ()) - { - global_ret = 1; - return; - } - if (GNUNET_OK != create_wire_fees ()) - { - global_ret = 1; - return; - } -} - - -/** - * The main function of the taler-exchange-keyup tool. This tool is used to - * create the signing and denomination keys for the exchange. It uses the - * long-term offline private key and writes the (additional) key files to the - * respective exchange directory (from where they can then be copied to the - * online server). Note that we need (at least) the most recent generated - * previous keys to align the validity periods. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, - char *const *argv) -{ - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_option_filename ('m', - "master-key", - "FILENAME", - "master key file (private key)", - &masterkeyfile), - GNUNET_GETOPT_option_filename ('f', - "feedir", - "DIRNAME", - "directory where to write wire transfer fee structure", - &feedir), - GNUNET_GETOPT_option_uint ('k', - "replacement-keysize", - "BITS", - "when creating a replacement key in a revocation operation, which key size should be used for the new denomination key", - &replacement_key_size), - GNUNET_GETOPT_option_filename ('o', - "output", - "FILENAME", - "auditor denomination key signing request file to create", - &auditorrequestfile), - GNUNET_GETOPT_option_base32_auto ('r', - "revoke", - "DKH", - "revoke denomination key hash (DKH) and request wallets to initiate recoup", - &revoke_dkh), - GNUNET_GETOPT_option_timetravel ('T', - "timetravel"), - GNUNET_GETOPT_option_absolute_time ('t', - "time", - "TIMESTAMP", - "pretend it is a different time for the update", - &now_tmp), - GNUNET_GETOPT_OPTION_END - }; - - /* force linker to link against libtalerutil; if we do - not do this, the linker may "optimize" libtalerutil - away and skip #TALER_OS_init(), which we do need */ - (void) TALER_project_data_default (); - GNUNET_assert (GNUNET_OK == - GNUNET_log_setup ("taler-exchange-keyup", - "WARNING", - NULL)); - now = now_tmp = GNUNET_TIME_absolute_get (); - if (GNUNET_OK != - GNUNET_PROGRAM_run (argc, argv, - "taler-exchange-keyup", - "Setup signing and denomination keys for a Taler exchange", - options, - &run, NULL)) - return 1; - if (NULL != auditor_output_file) - { - GNUNET_assert (0 == fclose (auditor_output_file)); - auditor_output_file = NULL; - } - return global_ret; -} - - -/* end of taler-exchange-keyup.c */ diff --git a/src/exchange-tools/taler-exchange-wire.c b/src/exchange-tools/taler-exchange-wire.c deleted file mode 100644 index 8aa3f570c..000000000 --- a/src/exchange-tools/taler-exchange-wire.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2018 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - 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 -*/ -/** - * @file taler-exchange-wire.c - * @brief Create signed response for /wire requests. - * @author Christian Grothoff - */ -#include -#include -#include -#include "taler_crypto_lib.h" -#include "taler_util.h" -#include "taler_json_lib.h" -#include "taler_exchangedb_lib.h" -#include "taler_signatures.h" - - -/** - * Filename of the master private key. - */ -static char *masterkeyfile; - -/** - * Private key for signing. - */ -static struct TALER_MasterPrivateKeyP master_priv; - -/** - * Return value from main(). - */ -static int global_ret; - - -#include "key-helper.c" - - -/** - * Function called with information about a wire account. Signs - * the account's wire details and writes out the JSON file to disk. - * - * @param cls closure - * @param ai account information - */ -static void -sign_account_data (void *cls, - const struct TALER_EXCHANGEDB_AccountInfo *ai) -{ - char *json_out; - FILE *out; - int ret; - - (void) cls; - if (GNUNET_NO == ai->credit_enabled) - return; - if (NULL == ai->wire_response_filename) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ai->section_name, - "WIRE_RESPONSE"); - global_ret = 1; - return; - } - - { - json_t *wire; - - wire = TALER_JSON_exchange_wire_signature_make (ai->payto_uri, - &master_priv); - if (NULL == wire) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not sign wire account `%s'. Is the URI well-formed?\n", - ai->payto_uri); - global_ret = 1; - return; - } - GNUNET_assert (NULL != wire); - json_out = json_dumps (wire, - JSON_INDENT (2)); - json_decref (wire); - } - GNUNET_assert (NULL != json_out); - if (GNUNET_OK != - GNUNET_DISK_directory_create_for_file (ai->wire_response_filename)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "mkdir", - ai->wire_response_filename); - global_ret = 1; - free (json_out); - return; - } - - out = fopen (ai->wire_response_filename, - "w+"); /* create, if exists, truncate */ - if (NULL == out) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "fopen(w+)", - ai->wire_response_filename); - global_ret = 1; - free (json_out); - return; - } - ret = fprintf (out, - "%s", - json_out); - if ( (0 != fclose (out)) || - (-1 == ret) ) - { - fprintf (stderr, - "Failure creating wire account file `%s': %s\n", - ai->wire_response_filename, - strerror (errno)); - /* attempt to remove malformed file */ - if (0 != unlink (ai->wire_response_filename)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, - "unlink", - ai->wire_response_filename); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Created wire account file `%s'\n", - ai->wire_response_filename); - } - free (json_out); -} - - -/** - * Main function that will be run. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param cfg configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - (void) cls; - (void) args; - (void) cfgfile; - - if (GNUNET_OK != - get_and_check_master_key (cfg, - masterkeyfile, - &master_priv)) - { - global_ret = 1; - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Signing /wire responses\n"); - if (GNUNET_OK != - TALER_EXCHANGEDB_find_accounts (cfg, - &sign_account_data, - NULL)) - { - global_ret = 1; - return; - } -} - - -/** - * The main function of the taler-exchange-wire tool. This tool is - * used to sign the bank account details using the master key. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, - char *const *argv) -{ - const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_option_timetravel ('T', - "timetravel"), - GNUNET_GETOPT_option_filename ('m', - "master-key", - "FILENAME", - "master key file (private key)", - &masterkeyfile), - GNUNET_GETOPT_OPTION_END - }; - - /* force linker to link against libtalerutil; if we do - not do this, the linker may "optimize" libtalerutil - away and skip #TALER_OS_init(), which we do need */ - (void) TALER_project_data_default (); - GNUNET_assert (GNUNET_OK == - GNUNET_log_setup ("taler-exchange-wire", - "WARNING", - NULL)); - if (GNUNET_OK != - GNUNET_PROGRAM_run (argc, argv, - "taler-exchange-wire", - "Setup /wire response", - options, - &run, NULL)) - return 1; - return global_ret; -} - - -/* end of taler-exchange-wire.c */ diff --git a/src/exchange-tools/test_taler_exchange_httpd.conf b/src/exchange-tools/test_taler_exchange_httpd.conf deleted file mode 100644 index 27fc067a9..000000000 --- a/src/exchange-tools/test_taler_exchange_httpd.conf +++ /dev/null @@ -1,130 +0,0 @@ -[PATHS] -# Persistent data storage for the testcase -TALER_TEST_HOME = test_taler_exchange_httpd_home/ - -[taler] -# Currency supported by the exchange (can only be one) -CURRENCY = EUR -CURRENCY_ROUND_UNIT = EUR:0.01 - -[exchange] - -# Directory with our terms of service. -TERMS_DIR = ../../contrib/tos - -# Etag / filename for the terms of service. -TERMS_ETAG = 0 - - -# Directory with our privacy policy. -PRIVACY_DIR = ../../contrib/pp - -# Etag / filename for the privacy policy. -PRIVACY_ETAG = 0 - -# MAX_REQUESTS = 2 -# how long is one signkey valid? -SIGNKEY_DURATION = 4 weeks - -# how long are the signatures with the signkey valid? -LEGAL_DURATION = 2 years - -# how long do we generate denomination and signing keys -# ahead of time? -LOOKAHEAD_SIGN = 2 weeks 1 day - -# how long do we provide to clients denomination and signing keys -# ahead of time? -LOOKAHEAD_PROVIDE = 1 weeks 1 day - -# HTTP port the exchange listens to -PORT = 8081 - -# Master public key used to sign the exchange's various keys -MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG - -# How to access our database -DB = postgres - - -[exchangedb] -# After how long do we close idle reserves? The exchange -# and the auditor must agree on this value. We currently -# expect it to be globally defined for the whole system, -# as there is no way for wallets to query this value. Thus, -# it is only configurable for testing, and should be treated -# as constant in production. -IDLE_RESERVE_EXPIRATION_TIME = 4 weeks - - -[exchangedb-postgres] -CONFIG = "postgres:///talercheck" - -[exchange-account-1] -PAYTO_URI = "payto://x-taler-bank/localhost:8082/3" -WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json -ENABLE_DEBIT = YES -ENABLE_CREDIT = YES -TALER_BANK_AUTH_METHOD = NONE - - -# Wire fees are specified by wire method -[fees-x-taler-bank] -# Fees for the foreseeable future... -# If you see this after 2018, update to match the next 10 years... -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 -WIRE-FEE-2027 = EUR:0.01 - -CLOSING-FEE-2018 = EUR:0.01 -CLOSING-FEE-2019 = EUR:0.01 -CLOSING-FEE-2020 = EUR:0.01 -CLOSING-FEE-2021 = EUR:0.01 -CLOSING-FEE-2022 = EUR:0.01 -CLOSING-FEE-2023 = EUR:0.01 -CLOSING-FEE-2024 = EUR:0.01 -CLOSING-FEE-2025 = EUR:0.01 -CLOSING-FEE-2026 = EUR:0.01 -CLOSING-FEE-2027 = EUR:0.01 - - -# Coins for the tests. -[coin_eur_ct_1] -value = EUR:0.01 -duration_withdraw = 7 days -duration_spend = 2 years -duration_legal = 3 years -fee_withdraw = EUR:0.00 -fee_deposit = EUR:0.00 -fee_refresh = EUR:0.01 -fee_refund = EUR:0.01 -rsa_keysize = 1024 - -[coin_eur_ct_10] -value = EUR:0.10 -duration_withdraw = 7 days -duration_spend = 2 years -duration_legal = 3 years -fee_withdraw = EUR:0.01 -fee_deposit = EUR:0.01 -fee_refresh = EUR:0.03 -fee_refund = EUR:0.01 -rsa_keysize = 1024 - -[coin_eur_1] -value = EUR:1 -duration_withdraw = 7 days -duration_spend = 2 years -duration_legal = 3 years -fee_withdraw = EUR:0.01 -fee_deposit = EUR:0.01 -fee_refresh = EUR:0.03 -fee_refund = EUR:0.01 -rsa_keysize = 1024 diff --git a/src/exchange-tools/test_taler_exchange_httpd_home/.config/taler/test.json b/src/exchange-tools/test_taler_exchange_httpd_home/.config/taler/test.json deleted file mode 100644 index eca394241..000000000 --- a/src/exchange-tools/test_taler_exchange_httpd_home/.config/taler/test.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "salt": "AZPRFVJ58NM6M7J5CZQPJAH3EW5DYM52AEZ9Y1C1ER3W94QV8D8TQKF6CK8MYQRA9QMSKDQTGZ306ZS9GQ0M6R01CJ20KPP49WFDZK8", - "name": "The exchange", - "account_number": 3, - "bank_url": "http://localhost:8082/", - "type": "test", - "sig": "RPQXP9S4P8PQP7HEZQNRSZCT0ATNEP8GW0P5TPM34V5RX86FCD670V44R9NETSYDDKB8SZV7TKY9PAJYTY51D3VDWY9XXQ5BPFRXR28" -} diff --git a/src/exchange-tools/test_taler_exchange_httpd_home/.local/share/taler/exchange/offline-keys/master.priv b/src/exchange-tools/test_taler_exchange_httpd_home/.local/share/taler/exchange/offline-keys/master.priv deleted file mode 100644 index 394926938..000000000 --- a/src/exchange-tools/test_taler_exchange_httpd_home/.local/share/taler/exchange/offline-keys/master.priv +++ /dev/null @@ -1 +0,0 @@ -p^-33XX!\0qmU_ \ No newline at end of file -- cgit v1.2.3