summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-06-15 16:45:29 +0200
committerChristian Grothoff <christian@grothoff.org>2016-06-15 22:54:58 +0200
commitf59246e763cce70819f3ea8cc9b2f20732506912 (patch)
tree5f46c7238cb2fbfd225c41560a0e8d7ec74fbb21
parent3876b70eb4daeaa04050fdaf5a2f9f625a879ff6 (diff)
downloadexchange-f59246e763cce70819f3ea8cc9b2f20732506912.tar.gz
exchange-f59246e763cce70819f3ea8cc9b2f20732506912.tar.bz2
exchange-f59246e763cce70819f3ea8cc9b2f20732506912.zip
clean up blobs
clean up blobs clean up blobs clean up blobs pass -c option to taler services, ship with reasonable config exclude live-keys from config
-rw-r--r--src/benchmark/Makefile.am5
-rw-r--r--src/benchmark/taler-exchange-benchmark.c245
-rw-r--r--src/benchmark/taler-exchange-benchmark.conf88
-rw-r--r--src/benchmark/test_benchmark_home/.config/taler/sepa.json9
-rw-r--r--src/benchmark/test_benchmark_home/.config/taler/test.json8
-rw-r--r--src/benchmark/test_benchmark_home/.local/share/taler/exchange/offline-keys/master.priv1
-rw-r--r--src/exchange-lib/test_exchange_api.conf2
7 files changed, 307 insertions, 51 deletions
diff --git a/src/benchmark/Makefile.am b/src/benchmark/Makefile.am
index a5aef47e3..f2c299b64 100644
--- a/src/benchmark/Makefile.am
+++ b/src/benchmark/Makefile.am
@@ -24,4 +24,7 @@ taler_exchange_benchmark_LDADD = \
EXTRA_DIST = \
taler-exchange-benchmark.conf \
bank-details.json \
- merchant-details.json
+ merchant-details.json \
+ test_benchmark_home/.local/share/taler/exchange/offline-keys/master.priv \
+ test_benchmark_home/.config/taler/test.json \
+ test_benchmark_home/.config/taler/sepa.json
diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c
index 392504efc..430f44f0f 100644
--- a/src/benchmark/taler-exchange-benchmark.c
+++ b/src/benchmark/taler-exchange-benchmark.c
@@ -20,10 +20,9 @@
* @author Christian Grothoff
*
* TODO:
- * - track state of reserve/coin with its struct
- * - have global work-lists with available slots for
- * admin, deposit and withdraw operations (and stats!)
- * - implement the main loop of the benchmark
+ * - test
+ * - add instrumentation
+ * - add support for automatic termination
*/
#include "platform.h"
#include "taler_util.h"
@@ -35,13 +34,28 @@
#include <microhttpd.h>
#include <jansson.h>
+/**
+ * How much slack do we leave in terms of coins that are invalid (and
+ * thus available for refresh)?
+ */
+#define INVALID_COIN_SLACK 10
/**
* Needed information for a reserve. Other values are the same for all reserves, therefore defined in global variables
*/
struct Reserve
{
- /**
+ /**
+ * DLL of reserves to fill.
+ */
+ struct Reserve *next;
+
+ /**
+ * DLL of reserves to fill.
+ */
+ struct Reserve *prev;
+
+ /**
* Set (by the interpreter) to the reserve's private key
* we used to fill the reserve.
*/
@@ -51,6 +65,11 @@ struct Reserve
* Set to the API's handle during the operation.
*/
struct TALER_EXCHANGE_AdminAddIncomingHandle *aih;
+
+ /**
+ * How much is left in this reserve.
+ */
+ struct TALER_Amount left;
/**
* Index of this reserve in the #reserves array.
@@ -67,6 +86,16 @@ struct Coin
{
/**
+ * DLL of coins to withdraw.
+ */
+ struct Coin *next;
+
+ /**
+ * DLL of coins to withdraw.
+ */
+ struct Coin *prev;
+
+ /**
* Set (by the interpreter) to the exchange's signature over the
* coin's public key.
*/
@@ -101,28 +130,33 @@ struct Coin
* Deposit handle (while operation is running).
*/
struct TALER_EXCHANGE_DepositHandle *dh;
+
+ /**
+ * Array of denominations expected to get from melt
+ */
+ struct TALER_Amount *denoms;
/**
* The result of a #TALER_EXCHANGE_refresh_prepare() call
*/
- const char *blob;
-
+ char *blob;
+
/**
* Size of @e blob
*/
size_t blob_size;
/**
- * Array of denominations expected to get from melt
- */
- struct TALER_Amount *denoms;
-
- /**
* Flag indicating if the coin is going to be refreshed
*/
unsigned int refresh;
/**
+ * #GNUNET_YES if this coin is in the #invalid_coins_head DLL.
+ */
+ int invalid;
+
+ /**
* Index in the reserve's global array indicating which
* reserve this coin is to be retrieved. If the coin comes
* from a refresh, then this value is set to the melted coin's
@@ -145,6 +179,31 @@ struct Coin
/**
+ * DLL of reserves to fill.
+ */
+static struct Reserve *empty_reserve_head;
+
+/**
+ * DLL of reserves to fill.
+ */
+static struct Reserve *empty_reserve_tail;
+
+/**
+ * DLL of coins to withdraw.
+ */
+static struct Coin *invalid_coins_head;
+
+/**
+ * DLL of coins to withdraw.
+ */
+static struct Coin *invalid_coins_tail;
+
+/**
+ * How many coins are in the #invalid_coins_head DLL?
+ */
+static unsigned int num_invalid_coins;
+
+/**
* Should we initialize and start the exchange, if #GNUNET_NO,
* we expect one to be already up and running.
*/
@@ -462,7 +521,7 @@ reveal_cb (void *cls,
keys = TALER_EXCHANGE_get_keys (exchange);
for (i=0; i<num_coins; i++)
{
- struct Coin fresh_coin;
+ struct Coin *fresh_coin;
char *revealed_str;
revealed_str = TALER_amount_to_string (&coin->denoms[i]);
@@ -472,13 +531,22 @@ reveal_cb (void *cls,
ncoins);
GNUNET_free (revealed_str);
- fresh_coin.reserve_index = coin->reserve_index;
- fresh_coin.pk = find_pk (keys, &coin->denoms[i]);
- fresh_coin.sig = sigs[i];
- // FIXME: yuck!
- GNUNET_array_append (coins,
- ncoins,
- fresh_coin);
+ fresh_coin = invalid_coins_head;
+ if (NULL == fresh_coin)
+ {
+ /* #INVALID_COIN_SLACK too low? */
+ GNUNET_break (0);
+ continue;
+ }
+ GNUNET_CONTAINER_DLL_remove (invalid_coins_head,
+ invalid_coins_tail,
+ fresh_coin);
+ num_invalid_coins--;
+ fresh_coin->invalid = GNUNET_NO;
+ fresh_coin->pk = find_pk (keys, &coin->denoms[i]);
+ fresh_coin->sig = sigs[i];
+ fresh_coin->coin_priv = coin_privs[i];
+ fresh_coin->left = coin->denoms[i];
}
continue_master_task ();
}
@@ -519,6 +587,13 @@ melt_cb (void *cls,
noreveal_index,
&reveal_cb,
coin);
+ GNUNET_free (coin->blob);
+ coin->blob = NULL;
+ if (NULL == coin->rrh)
+ {
+ fail ("Failed on reveal during refresh!");
+ return;
+ }
}
@@ -708,6 +783,7 @@ spend_coin (struct Coin *coin,
TALER_amount_subtract (&amount,
&coin->pk->value,
&coin->pk->fee_deposit);
+ coin->refresh = GNUNET_NO;
}
memset (&dr, 0, sizeof (dr));
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
@@ -754,6 +830,11 @@ spend_coin (struct Coin *coin,
fail ("An error occurred while calling deposit API");
return;
}
+ GNUNET_CONTAINER_DLL_insert (invalid_coins_head,
+ invalid_coins_tail,
+ coin);
+ num_invalid_coins++;
+ coin->invalid = GNUNET_YES;
}
@@ -788,6 +869,11 @@ reserve_withdraw_cb (void *cls,
coin->coin_index);
coin->sig.rsa_signature =
GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
+ GNUNET_CONTAINER_DLL_remove (invalid_coins_head,
+ invalid_coins_tail,
+ coin);
+ num_invalid_coins--;
+ coin->invalid = GNUNET_NO;
continue_master_task ();
}
@@ -802,11 +888,14 @@ withdraw_coin (struct Coin *coin)
{
struct GNUNET_CRYPTO_EddsaPrivateKey *coin_priv;
struct TALER_Amount amount;
+ struct TALER_Amount left;
const struct TALER_EXCHANGE_Keys *keys;
struct Reserve *r;
keys = TALER_EXCHANGE_get_keys (exchange);
r = &reserves[coin->reserve_index];
+ GNUNET_assert (-1 != TALER_amount_cmp (&r->left,
+ &amount));
coin_priv = GNUNET_CRYPTO_eddsa_key_create ();
coin->coin_priv.eddsa_priv = *coin_priv;
GNUNET_free (coin_priv);
@@ -822,6 +911,20 @@ withdraw_coin (struct Coin *coin)
&blinding_key,
&reserve_withdraw_cb,
coin);
+ GNUNET_assert (GNUNET_SYSERR !=
+ TALER_amount_subtract (&left,
+ &r->left,
+ &amount));
+ r->left = left;
+ if (-1 == TALER_amount_cmp (&left,
+ &amount))
+ {
+ /* not enough left in the reserve for future withdrawals,
+ create a new reserve! */
+ GNUNET_CONTAINER_DLL_insert (empty_reserve_head,
+ empty_reserve_tail,
+ r);
+ }
}
@@ -851,6 +954,9 @@ add_incoming_cb (void *cls,
fail ("At least one reserve failed in being created");
return;
}
+ GNUNET_CONTAINER_DLL_remove (empty_reserve_head,
+ empty_reserve_tail,
+ r);
continue_master_task ();
}
@@ -883,6 +989,7 @@ fill_reserve (struct Reserve *r)
GNUNET_assert (NULL != transfer_details);
GNUNET_CRYPTO_eddsa_key_get_public (&r->reserve_priv.eddsa_priv,
&reserve_pub.eddsa_pub);
+ r->left = reserve_amount;
r->aih = TALER_EXCHANGE_admin_add_incoming (exchange,
exchange_admin_uri,
&reserve_pub,
@@ -906,39 +1013,40 @@ static void
benchmark_run (void *cls)
{
unsigned int i;
+ int refresh;
+ struct Coin *coin;
benchmark_task = NULL;
- /* FIXME: Note that this function cannot work as-is, it's
- just a placeholder for the final logic we want here. */
- for (i=0;i < nreserves;i++)
+ /* First, always make sure all reserves are full */
+ if (NULL != empty_reserve_head)
{
- struct Reserve *r = &reserves[i];
-
- r->reserve_index = i;
- fill_reserve (r);
-
-
- for (i=0; i < COINS_PER_RESERVE; i++)
- {
- struct Coin *coin;
- unsigned int coin_index;
-
- coin_index = r->reserve_index * COINS_PER_RESERVE + i;
- coin = &coins[coin_index];
- coin->coin_index = coin_index;
- coin->reserve_index = r->reserve_index;
- withdraw_coin (coin);
- }
+ fill_reserve (empty_reserve_head);
+ return;
}
-
- if (GNUNET_OK == eval_probability (SPEND_PROBABILITY))
+ /* Second, withdraw until #num_invalid_coins is less than
+ #INVALID_COIN_SLACK */
+ if (num_invalid_coins > INVALID_COIN_SLACK)
{
- struct Coin *coin;
+ withdraw_coin (invalid_coins_head);
+ return;
+ }
- i = 0; // FIXME...
- coin = &coins[i];
+ /* By default, pick a random valid coin to spend */
+ for (i=0;i<1000;i++)
+ {
+ coin = &coins[GNUNET_CRYPTO_random_u32 (ncoins,
+ GNUNET_CRYPTO_QUALITY_WEAK)];
+ if (GNUNET_YES == coin->invalid)
+ continue; /* unlucky draw, try again */
+ if (1 == coin->left.value)
+ refresh = GNUNET_NO; /* cannot refresh, coin is already at unit */
+ else
+ refresh = eval_probability (REFRESH_PROBABILITY);
spend_coin (coin,
- (GNUNET_YES == eval_probability (REFRESH_PROBABILITY))); }
+ refresh);
+ return;
+ }
+ fail ("Too many invalid coins, is your INVALID_COIN_SLACK too high?");
}
@@ -1097,6 +1205,11 @@ do_shutdown (void *cls)
TALER_EXCHANGE_refresh_reveal_cancel (coin->rrh);
coin->rmh = NULL;
}
+ if (NULL != coin->blob)
+ {
+ GNUNET_free (coin->blob);
+ coin->blob = NULL;
+ }
}
if (NULL != bank_details)
{
@@ -1153,6 +1266,8 @@ run (void *cls)
char *bank_details_filename;
char *merchant_details_filename;
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+ unsigned int i;
+ unsigned int j;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"running run()\n");
@@ -1230,7 +1345,31 @@ run (void *cls)
ncoins = COINS_PER_RESERVE * nreserves;
coins = GNUNET_new_array (ncoins,
struct Coin);
+ for (i=0;i < nreserves;i++)
+ {
+ struct Reserve *r = &reserves[i];
+ r->reserve_index = i;
+ GNUNET_CONTAINER_DLL_insert (empty_reserve_head,
+ empty_reserve_tail,
+ r);
+ for (j=0; j < COINS_PER_RESERVE; j++)
+ {
+ struct Coin *coin;
+ unsigned int coin_index;
+
+ coin_index = i * COINS_PER_RESERVE + j;
+ coin = &coins[coin_index];
+ coin->coin_index = coin_index;
+ coin->reserve_index = i;
+ coin->invalid = GNUNET_YES;
+ GNUNET_CONTAINER_DLL_insert (invalid_coins_head,
+ invalid_coins_tail,
+ coin);
+ num_invalid_coins++;
+ }
+ }
+
ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
&rc);
GNUNET_assert (NULL != ctx);
@@ -1278,8 +1417,12 @@ main (int argc,
GNUNET_assert (GNUNET_SYSERR !=
GNUNET_GETOPT_run ("taler-exchange-benchmark",
options, argc, argv));
- if (NULL == exchange_uri)
+ if ( (NULL == exchange_uri) ||
+ (0 == strlen (exchange_uri) ))
+ {
+ GNUNET_free_non_null (exchange_uri);
exchange_uri = GNUNET_strdup ("http://localhost:8081/");
+ }
if (NULL == exchange_admin_uri)
exchange_admin_uri = GNUNET_strdup ("http://localhost:18080/");
if (run_exchange)
@@ -1291,6 +1434,7 @@ main (int argc,
NULL, NULL, NULL,
"taler-exchange-keyup",
"taler-exchange-keyup",
+ "-c", config_file,
NULL);
if (NULL == proc)
{
@@ -1307,6 +1451,7 @@ main (int argc,
"taler-exchange-dbinit",
"taler-exchange-dbinit",
"-r",
+ "-c", config_file,
NULL);
if (NULL == proc)
{
@@ -1322,6 +1467,7 @@ main (int argc,
NULL, NULL, NULL,
"taler-exchange-httpd",
"taler-exchange-httpd",
+ "-c", config_file,
NULL);
if (NULL == exchanged)
{
@@ -1331,8 +1477,9 @@ main (int argc,
}
GNUNET_asprintf (&wget,
- "wget -q -t 1 -T 1 %s keys -o /dev/null -O /dev/null",
- exchange_uri);
+ "wget -q -t 1 -T 1 %s%skeys -o /dev/null -O /dev/null",
+ exchange_uri,
+ (exchange_uri[strlen (exchange_uri)-1] == '/') ? "" : "/");
cnt = 0;
do {
fprintf (stderr, ".");
diff --git a/src/benchmark/taler-exchange-benchmark.conf b/src/benchmark/taler-exchange-benchmark.conf
index 6197bb3a9..16a26d8ae 100644
--- a/src/benchmark/taler-exchange-benchmark.conf
+++ b/src/benchmark/taler-exchange-benchmark.conf
@@ -1,3 +1,91 @@
[benchmark]
BANK_DETAILS = bank_details.json
MERCHANT_DETAILS = merchant_details.json
+
+[PATHS]
+# Persistant data storage for the testcase
+TALER_TEST_HOME = test_benchmark_home/
+
+[taler]
+CURRENCY = KUDOS
+
+[exchange]
+
+# Wire format supported by the exchange
+# We use 'test' for testing of the actual
+# coin operations, and 'sepa' to test SEPA-specific routines.
+WIREFORMAT = test
+
+# HTTP port the exchange listens to
+PORT = 8081
+# How to access our database
+DB = postgres
+
+# Master public key used to sign the exchange's various keys
+MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
+
+[exchangedb-postgres]
+DB_CONN_STR = "postgres:///talercheck"
+
+
+[exchange-wire-outgoing-test]
+# What is the main website of the bank?
+# (Not used unless the aggregator is run.)
+BANK_URI = "http://localhost:8082/"
+# From which account at the 'bank' should outgoing wire transfers be made?
+BANK_ACCOUNT_NUMBER = 2
+
+[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.
+TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
+
+
+[coin_kudos_1]
+value = KUDOS:1
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = KUDOS:0.00
+fee_deposit = KUDOS:0.00
+fee_refresh = KUDOS:0.00
+fee_refund = KUDOS:0.00
+rsa_keysize = 1024
+
+[coin_kudos_2]
+value = KUDOS:2
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = KUDOS:0.00
+fee_deposit = KUDOS:0.00
+fee_refresh = KUDOS:0.00
+fee_refund = KUDOS:0.00
+rsa_keysize = 1024
+
+[coin_kudos_4]
+value = KUDOS:4
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = KUDOS:0.00
+fee_deposit = KUDOS:0.00
+fee_refresh = KUDOS:0.00
+fee_refund = KUDOS:0.00
+rsa_keysize = 1024
+
+[coin_kudos_8]
+value = KUDOS:8
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = KUDOS:0.00
+fee_deposit = KUDOS:0.00
+fee_refresh = KUDOS:0.00
+fee_refund = KUDOS:0.00
+rsa_keysize = 1024
+
diff --git a/src/benchmark/test_benchmark_home/.config/taler/sepa.json b/src/benchmark/test_benchmark_home/.config/taler/sepa.json
new file mode 100644
index 000000000..b435ce86b
--- /dev/null
+++ b/src/benchmark/test_benchmark_home/.config/taler/sepa.json
@@ -0,0 +1,9 @@
+{
+ "name": "Max Musterman",
+ "bic": "COBADEFF370",
+ "type": "sepa",
+ "sig": "4EVRC2MCJPXQC8MC00831DNWEXMZAP4JQDDE1A7R6KR3MANG24RC1VQ55AX5A2E35S58VW1VSTENFTPHG5MWG9BSN8B8WXSV21KKW20",
+ "address": "Musterstadt",
+ "salt": "3KTM1ZRMWGEQPQ254S4R5R4Q8XM0ZYWTCTE01TZ76MVBSQ6RX7A5DR08WXVH1DCHR1R7ACRB7X0EVC2XDW1CBZM9WFSD9TRMZ90BR98",
+ "iban": "DE89370400440532013000"
+} \ No newline at end of file
diff --git a/src/benchmark/test_benchmark_home/.config/taler/test.json b/src/benchmark/test_benchmark_home/.config/taler/test.json
new file mode 100644
index 000000000..be5e92c11
--- /dev/null
+++ b/src/benchmark/test_benchmark_home/.config/taler/test.json
@@ -0,0 +1,8 @@
+{
+ "salt": "AZPRFVJ58NM6M7J5CZQPJAH3EW5DYM52AEZ9Y1C1ER3W94QV8D8TQKF6CK8MYQRA9QMSKDQTGZ306ZS9GQ0M6R01CJ20KPP49WFDZK8",
+ "name": "The exchange",
+ "account_number": 3,
+ "bank_uri": "http://localhost:8082/",
+ "type": "test",
+ "sig": "RPQXP9S4P8PQP7HEZQNRSZCT0ATNEP8GW0P5TPM34V5RX86FCD670V44R9NETSYDDKB8SZV7TKY9PAJYTY51D3VDWY9XXQ5BPFRXR28"
+} \ No newline at end of file
diff --git a/src/benchmark/test_benchmark_home/.local/share/taler/exchange/offline-keys/master.priv b/src/benchmark/test_benchmark_home/.local/share/taler/exchange/offline-keys/master.priv
new file mode 100644
index 000000000..394926938
--- /dev/null
+++ b/src/benchmark/test_benchmark_home/.local/share/taler/exchange/offline-keys/master.priv
@@ -0,0 +1 @@
+p^-33XX!\0qmU_ \ No newline at end of file
diff --git a/src/exchange-lib/test_exchange_api.conf b/src/exchange-lib/test_exchange_api.conf
index a8c690786..03dd6f992 100644
--- a/src/exchange-lib/test_exchange_api.conf
+++ b/src/exchange-lib/test_exchange_api.conf
@@ -43,7 +43,7 @@ TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
[exchange-wire-outgoing-test]
# What is the main website of the bank?
BANK_URI = "http://localhost:8082/"
-# Into which account at the 'bank' should (incoming) wire transfers be made?
+# From which account at the 'bank' should outgoing wire transfers be made?
BANK_ACCOUNT_NUMBER = 2
[coin_eur_ct_1]