diff options
Diffstat (limited to 'src/testing/test_exchange_api.c')
-rw-r--r-- | src/testing/test_exchange_api.c | 647 |
1 files changed, 462 insertions, 185 deletions
diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c index 3e1df3841..caeec1e76 100644 --- a/src/testing/test_exchange_api.c +++ b/src/testing/test_exchange_api.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014--2020 Taler Systems SA + Copyright (C) 2014--2022 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 @@ -29,31 +29,38 @@ #include "taler_exchange_service.h" #include "taler_json_lib.h" #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_testing_lib.h> #include <microhttpd.h> #include "taler_bank_service.h" #include "taler_fakebank_lib.h" #include "taler_testing_lib.h" +#include "taler_extensions.h" /** * Configuration file we use. One (big) configuration is used * for the various components for this test. */ -#define CONFIG_FILE "test_exchange_api.conf" - -#define CONFIG_FILE_EXPIRE_RESERVE_NOW \ - "test_exchange_api_expire_reserve_now.conf" - +static char *config_file; /** - * Exchange configuration data. + * Special configuration file to use when we want reserves + * to expire 'immediately'. */ -static struct TALER_TESTING_ExchangeConfiguration ec; +static char *config_file_expire_reserve_now; /** - * Bank configuration data. + * Our credentials. */ -static struct TALER_TESTING_BankConfiguration bc; +static struct TALER_TESTING_Credentials cred; +/** + * Some tests behave differently when using CS as we cannot + * reuse the coin private key for different denominations + * due to the derivation of it with the /csr values. Hence + * some tests behave differently in CS mode, hence this + * flag. + */ +static bool uses_cs; /** * Execute the taler-exchange-wirewatch command with @@ -62,7 +69,7 @@ static struct TALER_TESTING_BankConfiguration bc; * @param label label to use for the command. */ #define CMD_EXEC_WIREWATCH(label) \ - TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE) + TALER_TESTING_cmd_exec_wirewatch2 (label, config_file, "exchange-account-2") /** * Execute the taler-exchange-aggregator, closer and transfer commands with @@ -71,8 +78,9 @@ static struct TALER_TESTING_BankConfiguration bc; * @param label label to use for the command. */ #define CMD_EXEC_AGGREGATOR(label) \ - TALER_TESTING_cmd_exec_aggregator (label "-aggregator", CONFIG_FILE), \ - TALER_TESTING_cmd_exec_transfer (label "-transfer", CONFIG_FILE) + TALER_TESTING_cmd_sleep ("sleep-before-aggregator", 2), \ + TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \ + TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file) /** @@ -84,8 +92,8 @@ static struct TALER_TESTING_BankConfiguration bc; */ #define CMD_TRANSFER_TO_EXCHANGE(label,amount) \ TALER_TESTING_cmd_admin_add_incoming (label, amount, \ - &bc.exchange_auth, \ - bc.user42_payto) + &cred.ba, \ + cred.user42_payto) /** * Main function that will tell the interpreter what commands to @@ -99,21 +107,6 @@ run (void *cls, struct TALER_TESTING_Interpreter *is) { /** - * Checks made against /wire response. - */ - struct TALER_TESTING_Command wire[] = { - /** - * Check if 'x-taler-bank' wire method is offered - * by the exchange. - */ - TALER_TESTING_cmd_wire ("wire-taler-bank-1", - "x-taler-bank", - NULL, - MHD_HTTP_OK), - TALER_TESTING_cmd_end () - }; - - /** * Test withdrawal plus spending. */ struct TALER_TESTING_Command withdraw[] = { @@ -122,30 +115,45 @@ run (void *cls, */ CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1", "EUR:6.02"), + TALER_TESTING_cmd_reserve_poll ("poll-reserve-1", + "create-reserve-1", + "EUR:6.02", + GNUNET_TIME_UNIT_MINUTES, + MHD_HTTP_OK), TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-1", "EUR:6.02", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "create-reserve-1"), /** * Make a reserve exist, according to the previous * transfer. */ CMD_EXEC_WIREWATCH ("wirewatch-1"), + TALER_TESTING_cmd_reserve_poll_finish ("finish-poll-reserve-1", + GNUNET_TIME_UNIT_SECONDS, + "poll-reserve-1"), /** * Withdraw EUR:5. */ TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1", "create-reserve-1", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_OK), /** * Withdraw EUR:1 using the SAME private coin key as for the previous coin * (in violation of the specification, to be detected on spending!). + * However, note that this does NOT work with 'CS', as for a different + * denomination we get different R0/R1 values from the exchange, and + * thus will generate a different coin private key as R0/R1 are hashed + * into the coin priv. So here, we fail to 'reuse' the key due to the + * cryptographic construction! */ TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x", "create-reserve-1", "EUR:1", + 0, /* age restriction off */ "withdraw-coin-1", MHD_HTTP_OK), /** @@ -161,6 +169,7 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2", "create-reserve-1", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_CONFLICT), TALER_TESTING_cmd_end () }; @@ -172,29 +181,43 @@ run (void *cls, TALER_TESTING_cmd_deposit ("deposit-simple", "withdraw-coin-1", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK), - TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay", + TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-1", + "deposit-simple", + MHD_HTTP_OK), + TALER_TESTING_cmd_sleep ("sleep-before-deposit-replay", + 1), + TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-2", "deposit-simple", MHD_HTTP_OK), + /* This creates a conflict, as we have the same coin public key (reuse!), + but different denomination public keys (which is not allowed). + However, note that this does NOT work with 'CS', as for a different + denomination we get different R0/R1 values from the exchange, and + thus will generate a different coin private key as R0/R1 are hashed + into the coin priv. So here, we fail to 'reuse' the key due to the + cryptographic construction! */ TALER_TESTING_cmd_deposit ("deposit-reused-coin-key-failure", "withdraw-coin-1x", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:1", - MHD_HTTP_CONFLICT), + uses_cs + ? MHD_HTTP_OK + : MHD_HTTP_CONFLICT), /** * Try to double spend using different wire details. */ TALER_TESTING_cmd_deposit ("deposit-double-1", "withdraw-coin-1", 0, - bc.user43_payto, + cred.user43_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", @@ -208,7 +231,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("deposit-double-1", "withdraw-coin-1", 0, - bc.user43_payto, + cred.user43_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", @@ -219,7 +242,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("deposit-double-2", "withdraw-coin-1", 0, - bc.user43_payto, + cred.user43_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", @@ -230,7 +253,10 @@ run (void *cls, struct TALER_TESTING_Command refresh[] = { /** * Try to melt the coin that shared the private key with another - * coin (should fail). */ + * coin (should fail). Note that in the CS-case, we fail also + * with MHD_HTTP_CONFLICT, but for a different reason: here it + * is not a denomination conflict, but a double-spending conflict. + */ TALER_TESTING_cmd_melt ("refresh-melt-reused-coin-key-failure", "withdraw-coin-1x", MHD_HTTP_CONFLICT, @@ -241,8 +267,8 @@ run (void *cls, "EUR:5.01"), TALER_TESTING_cmd_check_bank_admin_transfer ("ck-refresh-create-reserve-1", "EUR:5.01", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "refresh-create-reserve-1"), /** * Make previous command effective. @@ -254,14 +280,16 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("refresh-withdraw-coin-1", "refresh-create-reserve-1", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_OK), /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin * (in full) (merchant would receive EUR:0.99 due to 1 ct - * deposit fee) */// + * deposit fee) + */ TALER_TESTING_cmd_deposit ("refresh-deposit-partial", "refresh-withdraw-coin-1", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:1\"}]}", GNUNET_TIME_UNIT_ZERO, "EUR:1", @@ -298,7 +326,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1a", "refresh-reveal-1-idempotency", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", GNUNET_TIME_UNIT_ZERO, "EUR:1", @@ -309,7 +337,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1b", "refresh-reveal-1", 3, - bc.user43_payto, + cred.user43_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", GNUNET_TIME_UNIT_ZERO, "EUR:0.1", @@ -330,11 +358,74 @@ run (void *cls, TALER_TESTING_cmd_end () }; + /** + * Test withdrawal with age restriction. Success is expected, so it MUST be + * called _after_ TALER_TESTING_cmd_exec_offline_sign_extensions is called, + * i. e. age restriction is activated in the exchange! + * + * TODO: create a test that tries to withdraw coins with age restriction but + * (expectedly) fails because the exchange doesn't support age restriction + * yet. + */ + struct TALER_TESTING_Command withdraw_age[] = { + /** + * Move money to the exchange's bank account. + */ + CMD_TRANSFER_TO_EXCHANGE ("create-reserve-age", + "EUR:6.01"), + TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-age", + "EUR:6.01", + cred.user42_payto, + cred.exchange_payto, + "create-reserve-age"), + /** + * Make a reserve exist, according to the previous + * transfer. + */ + CMD_EXEC_WIREWATCH ("wirewatch-age"), + /** + * Withdraw EUR:5. + */ + TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-age-1", + "create-reserve-age", + "EUR:5", + 13, + MHD_HTTP_OK), + + TALER_TESTING_cmd_end () + }; + + struct TALER_TESTING_Command spend_age[] = { + /** + * Spend the coin. + */ + TALER_TESTING_cmd_deposit ("deposit-simple-age", + "withdraw-coin-age-1", + 0, + cred.user42_payto, + "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + GNUNET_TIME_UNIT_ZERO, + "EUR:4.99", + MHD_HTTP_OK), + TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age", + "deposit-simple-age", + MHD_HTTP_OK), + TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age-1", + "deposit-simple-age", + MHD_HTTP_OK), + TALER_TESTING_cmd_sleep ("sleep-before-age-deposit-replay", + 1), + TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age-2", + "deposit-simple-age", + MHD_HTTP_OK), + TALER_TESTING_cmd_end () + }; + struct TALER_TESTING_Command track[] = { /* Try resolving a deposit's WTID, as we never triggered * execution of transactions, the answer should be that * the exchange knows about the deposit, but has no WTID yet. - */// + */ TALER_TESTING_cmd_track_transaction ("deposit-wtid-found", "deposit-simple", 0, @@ -356,37 +447,65 @@ run (void *cls, TALER_TESTING_cmd_track_transfer_empty ("wire-deposit-failing", NULL, MHD_HTTP_NOT_FOUND), - TALER_TESTING_cmd_sleep ("sleep-before-aggregator", - 1), /* Run transfers. Note that _actual_ aggregation will NOT * happen here, as each deposit operation is run with a * fresh merchant public key, so the aggregator will treat * them as "different" merchants and do the wire transfers - * individually. */// + * individually. */ CMD_EXEC_AGGREGATOR ("run-aggregator"), /** * Check all the transfers took place. */ TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-499c", - ec.exchange_url, + cred.exchange_url, "EUR:4.98", - bc.exchange_payto, - bc.user42_payto), + cred.exchange_payto, + cred.user42_payto), + TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-499c2", + cred.exchange_url, + "EUR:4.97", + cred.exchange_payto, + cred.user42_payto), TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c1", - ec.exchange_url, + cred.exchange_url, "EUR:0.98", - bc.exchange_payto, - bc.user42_payto), + cred.exchange_payto, + cred.user42_payto), TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c2", - ec.exchange_url, + cred.exchange_url, + "EUR:0.98", + cred.exchange_payto, + cred.user42_payto), + TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c3", + cred.exchange_url, "EUR:0.98", - bc.exchange_payto, - bc.user42_payto), - TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c", - ec.exchange_url, + cred.exchange_payto, + cred.user42_payto), + TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c4", + cred.exchange_url, + "EUR:0.98", + cred.exchange_payto, + cred.user42_payto), + TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-08c", + cred.exchange_url, + "EUR:0.08", + cred.exchange_payto, + cred.user43_payto), + TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-08c2", + cred.exchange_url, "EUR:0.08", - bc.exchange_payto, - bc.user43_payto), + cred.exchange_payto, + cred.user43_payto), + /* In case of CS, one transaction above succeeded that + failed for RSA, hence we need to check for an extra transfer here */ + uses_cs + ? TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-98c", + cred.exchange_url, + "EUR:0.98", + cred.exchange_payto, + cred.user42_payto) + : TALER_TESTING_cmd_sleep ("dummy", + 0), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty"), TALER_TESTING_cmd_track_transaction ("deposit-wtid-ok", "deposit-simple", @@ -406,7 +525,6 @@ run (void *cls, TALER_TESTING_cmd_end () }; - /** * This block checks whether a wire deadline * very far in the future does NOT get aggregated now. @@ -419,18 +537,19 @@ run (void *cls, TALER_TESTING_cmd_check_bank_admin_transfer ( "check-create-reserve-unaggregated", "EUR:5.01", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "create-reserve-unaggregated"), CMD_EXEC_WIREWATCH ("wirewatch-unaggregated"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-unaggregated", "create-reserve-unaggregated", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_OK), TALER_TESTING_cmd_deposit ("deposit-unaggregated", "withdraw-coin-unaggregated", 0, - bc.user43_payto, + cred.user43_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_relative_multiply ( GNUNET_TIME_UNIT_YEARS, @@ -439,12 +558,108 @@ run (void *cls, MHD_HTTP_OK), CMD_EXEC_AGGREGATOR ("aggregation-attempt"), - TALER_TESTING_cmd_check_bank_empty - ("far-future-aggregation-b"), + TALER_TESTING_cmd_check_bank_empty ( + "far-future-aggregation-b"), TALER_TESTING_cmd_end () }; + struct TALER_TESTING_Command refresh_age[] = { + /* Fill reserve with EUR:5, 1ct is for fees. */ + CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-age-1", + "EUR:6.01"), + TALER_TESTING_cmd_check_bank_admin_transfer ( + "ck-refresh-create-reserve-age-1", + "EUR:6.01", + cred.user42_payto, + cred.exchange_payto, + "refresh-create-reserve-age-1"), + /** + * Make previous command effective. + */ + CMD_EXEC_WIREWATCH ("wirewatch-age-2"), + /** + * Withdraw EUR:7 with age restriction for age 13. + */ + TALER_TESTING_cmd_withdraw_amount ("refresh-withdraw-coin-age-1", + "refresh-create-reserve-age-1", + "EUR:5", + 13, + MHD_HTTP_OK), + /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin + * (in full) (merchant would receive EUR:0.99 due to 1 ct + * deposit fee) + */ + TALER_TESTING_cmd_deposit ("refresh-deposit-partial-age", + "refresh-withdraw-coin-age-1", + 0, + cred.user42_payto, + "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:1\"}]}", + GNUNET_TIME_UNIT_ZERO, + "EUR:1", + MHD_HTTP_OK), + /** + * Melt the rest of the coin's value + * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */ + TALER_TESTING_cmd_melt_double ("refresh-melt-age-1", + "refresh-withdraw-coin-age-1", + MHD_HTTP_OK, + NULL), + /** + * Complete (successful) melt operation, and + * withdraw the coins + */ + TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-age-1", + "refresh-melt-age-1", + MHD_HTTP_OK), + /** + * Do it again to check idempotency + */ + TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-age-1-idempotency", + "refresh-melt-age-1", + MHD_HTTP_OK), + /** + * Test that /refresh/link works + */ + TALER_TESTING_cmd_refresh_link ("refresh-link-age-1", + "refresh-reveal-age-1", + MHD_HTTP_OK), + /** + * Try to spend a refreshed EUR:1 coin + */ + TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-age-1a", + "refresh-reveal-age-1-idempotency", + 0, + cred.user42_payto, + "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", + GNUNET_TIME_UNIT_ZERO, + "EUR:1", + MHD_HTTP_OK), + /** + * Try to spend a refreshed EUR:0.1 coin + */ + TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-age-1b", + "refresh-reveal-age-1", + 3, + cred.user43_payto, + "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", + GNUNET_TIME_UNIT_ZERO, + "EUR:0.1", + MHD_HTTP_OK), + /* Test running a failing melt operation (same operation + * again must fail) */ + TALER_TESTING_cmd_melt ("refresh-melt-failing-age", + "refresh-withdraw-coin-age-1", + MHD_HTTP_CONFLICT, + NULL), + /* Test running a failing melt operation (on a coin that + was itself revealed and subsequently deposited) */ + TALER_TESTING_cmd_melt ("refresh-melt-failing-age-2", + "refresh-reveal-age-1", + MHD_HTTP_CONFLICT, + NULL), + TALER_TESTING_cmd_end () + }; /** * This block exercises the aggretation logic by making two payments @@ -457,18 +672,19 @@ run (void *cls, TALER_TESTING_cmd_check_bank_admin_transfer ( "check-create-reserve-aggtest", "EUR:5.01", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "create-reserve-aggtest"), CMD_EXEC_WIREWATCH ("wirewatch-aggtest"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-aggtest", "create-reserve-aggtest", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_OK), TALER_TESTING_cmd_deposit ("deposit-aggtest-1", "withdraw-coin-aggtest", 0, - bc.user43_payto, + cred.user43_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:2", @@ -476,7 +692,7 @@ run (void *cls, TALER_TESTING_cmd_deposit_with_ref ("deposit-aggtest-2", "withdraw-coin-aggtest", 0, - bc.user43_payto, + cred.user43_payto, "{\"items\":[{\"name\":\"foo bar\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:2", @@ -484,10 +700,10 @@ run (void *cls, "deposit-aggtest-1"), CMD_EXEC_AGGREGATOR ("aggregation-aggtest"), TALER_TESTING_cmd_check_bank_transfer ("check-bank-transfer-aggtest", - ec.exchange_url, + cred.exchange_url, "EUR:3.97", - bc.exchange_payto, - bc.user43_payto), + cred.exchange_payto, + cred.user43_payto), TALER_TESTING_cmd_check_bank_empty ("check-bank-empty-aggtest"), TALER_TESTING_cmd_end () }; @@ -501,8 +717,8 @@ run (void *cls, "EUR:5.01"), TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-r1", "EUR:5.01", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "create-reserve-r1"), /** * Run wire-watch to trigger the reserve creation. @@ -512,6 +728,7 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-r1", "create-reserve-r1", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_OK), /** * Spend 5 EUR of the 5 EUR coin (in full) (merchant would @@ -520,7 +737,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("deposit-refund-1", "withdraw-coin-r1", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:5\"}]}", GNUNET_TIME_UNIT_MINUTES, "EUR:5", @@ -533,7 +750,7 @@ run (void *cls, * Note, this operation takes two commands: one to "flush" * the preliminary transfer (used to withdraw) from the * fakebank and the second to actually check there are not - * other transfers around. */// + * other transfers around. */ TALER_TESTING_cmd_check_bank_empty ("check_bank_transfer-pre-refund"), TALER_TESTING_cmd_refund_with_id ("refund-ok", MHD_HTTP_OK, @@ -554,7 +771,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("deposit-refund-insufficient-refund", "withdraw-coin-r1", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:4\"}]}", GNUNET_TIME_UNIT_MINUTES, "EUR:4", @@ -571,7 +788,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("deposit-refund-2", "withdraw-coin-r1", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"more ice cream\",\"value\":\"EUR:5\"}]}", GNUNET_TIME_UNIT_ZERO, "EUR:4.99", @@ -585,10 +802,10 @@ run (void *cls, * Check that deposit did run. */ TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-pre-refund", - ec.exchange_url, + cred.exchange_url, "EUR:4.97", - bc.exchange_payto, - bc.user42_payto), + cred.exchange_payto, + cred.user42_payto), /** * Run failing refund, as past deadline & aggregation. */ @@ -605,18 +822,19 @@ run (void *cls, "EUR:5.01"), TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-rb", "EUR:5.01", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "create-reserve-rb"), CMD_EXEC_WIREWATCH ("wirewatch-rb"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-rb", "create-reserve-rb", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_OK), TALER_TESTING_cmd_deposit ("deposit-refund-1b", "withdraw-coin-rb", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:5\"}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", @@ -633,7 +851,7 @@ run (void *cls, * Run transfers. This will do the transfer as refund deadline * was 0, except of course because the refund succeeded, the * transfer should no longer be done. - */// + */ CMD_EXEC_AGGREGATOR ("run-aggregator-3b"), /* check that aggregator didn't do anything, as expected */ TALER_TESTING_cmd_check_bank_empty ("check-refund-fast-not-run"), @@ -650,8 +868,8 @@ run (void *cls, TALER_TESTING_cmd_check_bank_admin_transfer ( "recoup-create-reserve-1-check", "EUR:15.02", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "recoup-create-reserve-1"), /** * Run wire-watch to trigger the reserve creation. @@ -661,11 +879,13 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-1", "recoup-create-reserve-1", "EUR:5", + 0, /* age restriction off */ MHD_HTTP_OK), /* Withdraw a 10 EUR coin, at fee of 1 ct */ TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-1b", "recoup-create-reserve-1", "EUR:10", + 0, /* age restriction off */ MHD_HTTP_OK), /* melt 10 EUR coin to get 5 EUR refreshed coin */ TALER_TESTING_cmd_melt ("recoup-melt-coin-1b", @@ -680,12 +900,11 @@ run (void *cls, TALER_TESTING_cmd_revoke ("revoke-0-EUR:5", MHD_HTTP_OK, "recoup-withdraw-coin-1", - CONFIG_FILE), + config_file), /* Recoup coin to reserve */ TALER_TESTING_cmd_recoup ("recoup-1", MHD_HTTP_OK, "recoup-withdraw-coin-1", - NULL, "EUR:5"), /* Check the money is back with the reserve */ TALER_TESTING_cmd_status ("recoup-reserve-status-1", @@ -693,11 +912,11 @@ run (void *cls, "EUR:5.0", MHD_HTTP_OK), /* Recoup-refresh coin to 10 EUR coin */ - TALER_TESTING_cmd_recoup ("recoup-1b", - MHD_HTTP_OK, - "recoup-reveal-coin-1b", - "recoup-melt-coin-1b", - "EUR:5"), + TALER_TESTING_cmd_recoup_refresh ("recoup-1b", + MHD_HTTP_OK, + "recoup-reveal-coin-1b", + "recoup-melt-coin-1b", + "EUR:5"), /* melt 10 EUR coin *again* to get 1 EUR refreshed coin */ TALER_TESTING_cmd_melt ("recoup-remelt-coin-1a", "recoup-withdraw-coin-1b", @@ -757,6 +976,7 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2", "recoup-create-reserve-1", "EUR:1", + 0, /* age restriction off */ MHD_HTTP_OK), /** * This withdrawal will test the logic to create a "recoup" @@ -765,6 +985,7 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2-over", "recoup-create-reserve-1", "EUR:10", + 0, /* age restriction off */ MHD_HTTP_CONFLICT), TALER_TESTING_cmd_status ("recoup-reserve-status-2", "recoup-create-reserve-1", @@ -777,18 +998,19 @@ run (void *cls, "EUR:5.01"), TALER_TESTING_cmd_check_bank_admin_transfer ("check-short-lived-reserve", "EUR:5.01", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "short-lived-reserve"), - TALER_TESTING_cmd_exec_wirewatch ("short-lived-aggregation", - CONFIG_FILE_EXPIRE_RESERVE_NOW), + TALER_TESTING_cmd_exec_wirewatch2 ("short-lived-aggregation", + config_file_expire_reserve_now, + "exchange-account-2"), TALER_TESTING_cmd_exec_closer ("close-reserves", - CONFIG_FILE_EXPIRE_RESERVE_NOW, + config_file_expire_reserve_now, "EUR:5", "EUR:0.01", "short-lived-reserve"), TALER_TESTING_cmd_exec_transfer ("close-reserves-transfer", - CONFIG_FILE_EXPIRE_RESERVE_NOW), + config_file_expire_reserve_now), TALER_TESTING_cmd_status ("short-lived-status", "short-lived-reserve", @@ -797,23 +1019,24 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("expired-withdraw", "short-lived-reserve", "EUR:1", + 0, /* age restriction off */ MHD_HTTP_CONFLICT), TALER_TESTING_cmd_check_bank_transfer ("check_bank_short-lived_reimburse", - ec.exchange_url, + cred.exchange_url, "EUR:5", - bc.exchange_payto, - bc.user42_payto), + cred.exchange_payto, + cred.user42_payto), /* Fill reserve with EUR:2.02, as withdraw fee is 1 ct per * config, then withdraw two coin, partially spend one, and * then have the rest paid back. Check deposit of other coin * fails. Do not use EUR:5 here as the EUR:5 coin was - * revoked and we did not bother to create a new one... */// + * revoked and we did not bother to create a new one... */ CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-2", "EUR:2.02"), TALER_TESTING_cmd_check_bank_admin_transfer ("ck-recoup-create-reserve-2", "EUR:2.02", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "recoup-create-reserve-2"), /* Make previous command effective. */ CMD_EXEC_WIREWATCH ("wirewatch-5"), @@ -821,16 +1044,18 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2a", "recoup-create-reserve-2", "EUR:1", + 0, /* age restriction off */ MHD_HTTP_OK), /* Withdraw a 1 EUR coin, at fee of 1 ct */ TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2b", "recoup-create-reserve-2", "EUR:1", + 0, /* age restriction off */ MHD_HTTP_OK), TALER_TESTING_cmd_deposit ("recoup-deposit-partial", "recoup-withdraw-coin-2a", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:0.5", @@ -838,28 +1063,27 @@ run (void *cls, TALER_TESTING_cmd_revoke ("revoke-1-EUR:1", MHD_HTTP_OK, "recoup-withdraw-coin-2a", - CONFIG_FILE), - /* Check recoup is failing for the coin with the reused coin key */ + config_file), + /* Check recoup is failing for the coin with the reused coin key + (fails either because of denomination conflict (RSA) or + double-spending (CS))*/ TALER_TESTING_cmd_recoup ("recoup-2x", MHD_HTTP_CONFLICT, "withdraw-coin-1x", - NULL, "EUR:1"), TALER_TESTING_cmd_recoup ("recoup-2", MHD_HTTP_OK, "recoup-withdraw-coin-2a", - NULL, "EUR:0.5"), /* Idempotency of recoup (withdrawal variant) */ TALER_TESTING_cmd_recoup ("recoup-2b", MHD_HTTP_OK, "recoup-withdraw-coin-2a", - NULL, - NULL), + "EUR:0.5"), TALER_TESTING_cmd_deposit ("recoup-deposit-revoked", "recoup-withdraw-coin-2b", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:1", @@ -871,7 +1095,7 @@ run (void *cls, TALER_TESTING_cmd_deposit ("recoup-deposit-partial-after-recoup", "recoup-withdraw-coin-2a", 0, - bc.user42_payto, + cred.user42_payto, "{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:0.5", @@ -882,13 +1106,14 @@ run (void *cls, TALER_TESTING_cmd_check_bank_admin_transfer ( "check-recoup-create-reserve-3", "EUR:1.01", - bc.user42_payto, - bc.exchange_payto, + cred.user42_payto, + cred.exchange_payto, "recoup-create-reserve-3"), CMD_EXEC_WIREWATCH ("wirewatch-6"), TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-3-revoked", "recoup-create-reserve-3", "EUR:1", + 0, /* age restriction off */ MHD_HTTP_GONE), /* check that we are empty before the rejection test */ TALER_TESTING_cmd_check_bank_empty ("check-empty-again"), @@ -896,6 +1121,75 @@ run (void *cls, TALER_TESTING_cmd_end () }; + /** + * Test batch withdrawal plus spending. + */ + struct TALER_TESTING_Command batch_withdraw[] = { + /** + * Move money to the exchange's bank account. + */ + CMD_TRANSFER_TO_EXCHANGE ("create-batch-reserve-1", + "EUR:6.03"), + TALER_TESTING_cmd_reserve_poll ("poll-batch-reserve-1", + "create-batch-reserve-1", + "EUR:6.03", + GNUNET_TIME_UNIT_MINUTES, + MHD_HTTP_OK), + TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-batch-reserve-1", + "EUR:6.03", + cred.user42_payto, + cred.exchange_payto, + "create-batch-reserve-1"), + /* + * Make a reserve exist, according to the previous + * transfer. + */ + CMD_EXEC_WIREWATCH ("wirewatch-batch-1"), + TALER_TESTING_cmd_reserve_poll_finish ("finish-poll-batch-reserve-1", + GNUNET_TIME_UNIT_SECONDS, + "poll-batch-reserve-1"), + /** + * Withdraw EUR:5 AND EUR:1. + */ + TALER_TESTING_cmd_batch_withdraw ("batch-withdraw-coin-1", + "create-batch-reserve-1", + 0, /* age restriction off */ + MHD_HTTP_OK, + "EUR:5", + "EUR:1", + NULL), + /** + * Check the reserve is (almost) depleted. + */ + TALER_TESTING_cmd_status ("status-batch-1", + "create-batch-reserve-1", + "EUR:0.01", + MHD_HTTP_OK), + TALER_TESTING_cmd_reserve_history ("history-batch-1", + "create-batch-reserve-1", + "EUR:0.01", + MHD_HTTP_OK), + /** + * Spend the coins. + */ + TALER_TESTING_cmd_batch_deposit ("batch-deposit-1", + cred.user42_payto, + "{\"items\":[{\"name\":\"ice cream\",\"value\":5}]}", + GNUNET_TIME_UNIT_ZERO, + MHD_HTTP_OK, + "batch-withdraw-coin-1#0", + "EUR:5", + "batch-withdraw-coin-1#1", + "EUR:1", + NULL), + TALER_TESTING_cmd_coin_history ("coin-history-batch-1", + "batch-withdraw-coin-1#0", + "EUR:0.0", + MHD_HTTP_OK), + TALER_TESTING_cmd_end () + }; + + #define RESERVE_OPEN_CLOSE_CHUNK 4 #define RESERVE_OPEN_CLOSE_ITERATIONS 3 @@ -912,11 +1206,12 @@ run (void *cls, = CMD_TRANSFER_TO_EXCHANGE ("reserve-open-close-key", "EUR:20"); reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 1] - = TALER_TESTING_cmd_exec_wirewatch ("reserve-open-close-wirewatch", - CONFIG_FILE_EXPIRE_RESERVE_NOW); + = TALER_TESTING_cmd_exec_wirewatch2 ("reserve-open-close-wirewatch", + config_file_expire_reserve_now, + "exchange-account-2"); reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 2] = TALER_TESTING_cmd_exec_closer ("reserve-open-close-aggregation", - CONFIG_FILE_EXPIRE_RESERVE_NOW, + config_file_expire_reserve_now, "EUR:19.99", "EUR:0.01", "reserve-open-close-key"); @@ -931,30 +1226,30 @@ run (void *cls, { struct TALER_TESTING_Command commands[] = { - /* setup exchange */ - TALER_TESTING_cmd_auditor_add ("add-auditor-OK", - MHD_HTTP_NO_CONTENT, - false), - TALER_TESTING_cmd_wire_add ("add-wire-account", - "payto://x-taler-bank/localhost/2", - MHD_HTTP_NO_CONTENT, - false), - TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys", - CONFIG_FILE), - TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", - CONFIG_FILE, - "EUR:0.01", - "EUR:0.01"), - TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys", - 1), - TALER_TESTING_cmd_batch ("wire", - wire), + TALER_TESTING_cmd_run_fakebank ("run-fakebank", + cred.cfg, + "exchange-account-2"), + TALER_TESTING_cmd_system_start ("start-taler", + config_file, + "-e", + NULL), + TALER_TESTING_cmd_get_exchange ("get-exchange", + cred.cfg, + NULL, + true, + true), TALER_TESTING_cmd_batch ("withdraw", withdraw), TALER_TESTING_cmd_batch ("spend", spend), TALER_TESTING_cmd_batch ("refresh", refresh), + TALER_TESTING_cmd_batch ("withdraw-age", + withdraw_age), + TALER_TESTING_cmd_batch ("spend-age", + spend_age), + TALER_TESTING_cmd_batch ("refresh-age", + refresh_age), TALER_TESTING_cmd_batch ("track", track), TALER_TESTING_cmd_batch ("unaggregation", @@ -963,6 +1258,8 @@ run (void *cls, aggregation), TALER_TESTING_cmd_batch ("refund", refund), + TALER_TESTING_cmd_batch ("batch-withdraw", + batch_withdraw), TALER_TESTING_cmd_batch ("recoup", recoup), TALER_TESTING_cmd_batch ("reserve-open-close", @@ -971,9 +1268,8 @@ run (void *cls, TALER_TESTING_cmd_end () }; - TALER_TESTING_run_with_fakebank (is, - commands, - bc.exchange_auth.wire_gateway_url); + TALER_TESTING_run (is, + commands); } } @@ -983,48 +1279,29 @@ main (int argc, char *const *argv) { (void) argc; - (void) argv; - /* These environment variables get in the way... */ - unsetenv ("XDG_DATA_HOME"); - unsetenv ("XDG_CONFIG_HOME"); - GNUNET_log_setup ("test-exchange-api", - "INFO", - NULL); - /* Check fakebank port is available and get config */ - if (GNUNET_OK != - TALER_TESTING_prepare_fakebank (CONFIG_FILE, - "exchange-account-2", - &bc)) - return 77; - TALER_TESTING_cleanup_files (CONFIG_FILE); - /* @helpers. Run keyup, create tables, ... Note: it - * fetches the port number from config in order to see - * if it's available. */ - switch (TALER_TESTING_prepare_exchange (CONFIG_FILE, - GNUNET_YES, - &ec)) { - case GNUNET_SYSERR: - GNUNET_break (0); - return 1; - case GNUNET_NO: - return 77; - case GNUNET_OK: - if (GNUNET_OK != - /* Set up event loop and reschedule context, plus - * start/stop the exchange. It calls TALER_TESTING_setup - * which creates the 'is' object. - */ - TALER_TESTING_setup_with_exchange (&run, - NULL, - CONFIG_FILE)) - return 1; - break; - default: - GNUNET_break (0); - return 1; + char *cipher; + + cipher = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]); + GNUNET_assert (NULL != cipher); + uses_cs = (0 == strcmp (cipher, + "cs")); + GNUNET_asprintf (&config_file, + "test_exchange_api-%s.conf", + cipher); + GNUNET_asprintf (&config_file_expire_reserve_now, + "test_exchange_api_expire_reserve_now-%s.conf", + cipher); + GNUNET_free (cipher); } - return 0; + return TALER_TESTING_main (argv, + "INFO", + config_file, + "exchange-account-2", + TALER_TESTING_BS_FAKEBANK, + &cred, + &run, + NULL); } |