LCOV - code coverage report
Current view: top level - testing - test_exchange_api.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 197 197
Test Date: 2026-04-14 15:39:31 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2014--2022 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify
       6              :   it under the terms of the GNU General Public License as
       7              :   published by the Free Software Foundation; either version 3, or
       8              :   (at your option) any later version.
       9              : 
      10              :   TALER is distributed in the hope that it will be useful, but
      11              :   WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13              :   GNU General Public License for more details.
      14              : 
      15              :   You should have received a copy of the GNU General Public
      16              :   License along with TALER; see the file COPYING.  If not, see
      17              :   <http://www.gnu.org/licenses/>
      18              : */
      19              : /**
      20              :  * @file testing/test_exchange_api.c
      21              :  * @brief testcase to test exchange's HTTP API interface
      22              :  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
      23              :  * @author Christian Grothoff
      24              :  * @author Marcello Stanisci
      25              :  */
      26              : #include "taler/taler_util.h"
      27              : #include "taler/taler_signatures.h"
      28              : #include "taler/taler_json_lib.h"
      29              : #include <gnunet/gnunet_util_lib.h>
      30              : #include <gnunet/gnunet_testing_lib.h>
      31              : #include <microhttpd.h>
      32              : #include "taler/taler_bank_service.h"
      33              : #include "taler/taler_testing_lib.h"
      34              : #include "taler/taler_extensions.h"
      35              : 
      36              : /**
      37              :  * Configuration file we use.  One (big) configuration is used
      38              :  * for the various components for this test.
      39              :  */
      40              : static char *config_file;
      41              : 
      42              : /**
      43              :  * Special configuration file to use when we want reserves
      44              :  * to expire 'immediately'.
      45              :  */
      46              : static char *config_file_expire_reserve_now;
      47              : 
      48              : /**
      49              :  * Our credentials.
      50              :  */
      51              : static struct TALER_TESTING_Credentials cred;
      52              : 
      53              : /**
      54              :  * Some tests behave differently when using CS as we cannot
      55              :  * reuse the coin private key for different denominations
      56              :  * due to the derivation of it with the /csr values. Hence
      57              :  * some tests behave differently in CS mode, hence this
      58              :  * flag.
      59              :  */
      60              : static bool uses_cs;
      61              : 
      62              : /**
      63              :  * Execute the taler-exchange-wirewatch command with
      64              :  * our configuration file.
      65              :  *
      66              :  * @param label label to use for the command.
      67              :  */
      68              : #define CMD_EXEC_WIREWATCH(label) \
      69              :         TALER_TESTING_cmd_exec_wirewatch2 (label, config_file, \
      70              :                                            "exchange-account-2")
      71              : 
      72              : /**
      73              :  * Execute the taler-exchange-aggregator, closer and transfer commands with
      74              :  * our configuration file.
      75              :  *
      76              :  * @param label label to use for the command.
      77              :  */
      78              : #define CMD_EXEC_AGGREGATOR(label) \
      79              :         TALER_TESTING_cmd_sleep ("sleep-before-aggregator", 2), \
      80              :         TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \
      81              :         TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file)
      82              : 
      83              : 
      84              : /**
      85              :  * Run wire transfer of funds from some user's account to the
      86              :  * exchange.
      87              :  *
      88              :  * @param label label to use for the command.
      89              :  * @param amount amount to transfer, i.e. "EUR:1"
      90              :  */
      91              : #define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
      92              :         TALER_TESTING_cmd_admin_add_incoming (label, amount, \
      93              :                                               &cred.ba,                \
      94              :                                               cred.user42_payto)
      95              : 
      96              : /**
      97              :  * Main function that will tell the interpreter what commands to
      98              :  * run.
      99              :  *
     100              :  * @param cls closure
     101              :  * @param is interpreter we use to run commands
     102              :  */
     103              : static void
     104            2 : run (void *cls,
     105              :      struct TALER_TESTING_Interpreter *is)
     106              : {
     107              :   /**
     108              :    * Test withdrawal plus spending.
     109              :    */
     110              :   struct TALER_TESTING_Command withdraw[] = {
     111              :     /**
     112              :      * Move money to the exchange's bank account.
     113              :      */
     114            2 :     CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
     115              :                               "EUR:6.02"),
     116            2 :     TALER_TESTING_cmd_reserve_poll ("poll-reserve-1",
     117              :                                     "create-reserve-1",
     118              :                                     "EUR:6.02",
     119              :                                     GNUNET_TIME_UNIT_MINUTES,
     120              :                                     MHD_HTTP_OK),
     121            2 :     TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-1",
     122              :                                                  "EUR:6.02",
     123              :                                                  cred.user42_payto,
     124              :                                                  cred.exchange_payto,
     125              :                                                  "create-reserve-1"),
     126              :     /**
     127              :      * Make a reserve exist, according to the previous
     128              :      * transfer.
     129              :      */
     130            2 :     CMD_EXEC_WIREWATCH ("wirewatch-1"),
     131            2 :     TALER_TESTING_cmd_reserve_poll_finish ("finish-poll-reserve-1",
     132              :                                            GNUNET_TIME_relative_multiply (
     133              :                                              GNUNET_TIME_UNIT_SECONDS,
     134              :                                              2),
     135              :                                            "poll-reserve-1"),
     136              :     /**
     137              :      * Withdraw EUR:5.
     138              :      */
     139            2 :     TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1",
     140              :                                        "create-reserve-1",
     141              :                                        "EUR:5",
     142              :                                        0, /* age restriction off */
     143              :                                        MHD_HTTP_OK),
     144              :     /**
     145              :      * Idempotent withdrawal.  Note that in the case of CS, this is _not_
     146              :      * idempotent because the blinding nonces still differ, so instead,
     147              :      * it is an overcharging of the reserve.
     148              :      */
     149            2 :     TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1-idem",
     150              :                                                  "create-reserve-1",
     151              :                                                  "EUR:5",
     152              :                                                  0, /* age restriction off */
     153              :                                                  "withdraw-coin-1",
     154              :                                                  (uses_cs)
     155            2 :                                                  ? MHD_HTTP_CONFLICT
     156              :                                                  : MHD_HTTP_OK),
     157              :     /**
     158              :     * Withdraw EUR:1 using the SAME private coin key as for the previous coin
     159              :     * (in violation of the specification, to be detected on spending!).
     160              :     * However, note that this does NOT work with 'CS', as for a different
     161              :     * denomination we get different R0/R1 values from the exchange, and
     162              :     * thus will generate a different coin private key as R0/R1 are hashed
     163              :     * into the coin priv. So here, we fail to 'reuse' the key due to the
     164              :     * cryptographic construction!
     165              :     */
     166            2 :     TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x",
     167              :                                                  "create-reserve-1",
     168              :                                                  "EUR:1",
     169              :                                                  0, /* age restriction off */
     170              :                                                  "withdraw-coin-1",
     171              :                                                  MHD_HTTP_OK),
     172              :     /**
     173              :      * Check the reserve is depleted.
     174              :      */
     175            2 :     TALER_TESTING_cmd_status ("status-1",
     176              :                               "create-reserve-1",
     177              :                               "EUR:0",
     178              :                               MHD_HTTP_OK),
     179              :     /*
     180              :      * Try to overdraw.
     181              :      */
     182            2 :     TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2",
     183              :                                        "create-reserve-1",
     184              :                                        "EUR:5",
     185              :                                        0, /* age restriction off */
     186              :                                        MHD_HTTP_CONFLICT),
     187            2 :     TALER_TESTING_cmd_end ()
     188              :   };
     189              : 
     190              :   struct TALER_TESTING_Command spend[] = {
     191              :     /**
     192              :      * Spend the coin.
     193              :      */
     194            2 :     TALER_TESTING_cmd_set_var (
     195              :       "account-priv",
     196              :       TALER_TESTING_cmd_deposit (
     197              :         "deposit-simple-fail-kyc",
     198              :         "withdraw-coin-1",
     199              :         0,
     200              :         cred.user42_payto,
     201              :         "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
     202            2 :         GNUNET_TIME_UNIT_ZERO,
     203              :         "EUR:5",
     204              :         MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS)),
     205            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     206              :       "kyc-auth-transfer",
     207              :       "EUR:0.01",
     208              :       &cred.ba,
     209              :       cred.user42_payto,
     210              :       "deposit-simple-fail-kyc"),
     211            2 :     CMD_EXEC_WIREWATCH (
     212              :       "import-kyc-account-withdraw"),
     213            2 :     TALER_TESTING_cmd_deposit_replay (
     214              :       "deposit-simple",
     215              :       "deposit-simple-fail-kyc",
     216              :       MHD_HTTP_OK),
     217            2 :     TALER_TESTING_cmd_deposit_replay (
     218              :       "deposit-simple-replay-1",
     219              :       "deposit-simple",
     220              :       MHD_HTTP_OK),
     221            2 :     TALER_TESTING_cmd_sleep (
     222              :       "sleep-before-deposit-replay",
     223              :       1),
     224            2 :     TALER_TESTING_cmd_deposit_replay (
     225              :       "deposit-simple-replay-2",
     226              :       "deposit-simple",
     227              :       MHD_HTTP_OK),
     228              :     /* This creates a conflict, as we have the same coin public key (reuse!),
     229              :        but different denomination public keys (which is not allowed).
     230              :        However, note that this does NOT work with 'CS', as for a different
     231              :        denomination we get different R0/R1 values from the exchange, and
     232              :        thus will generate a different coin private key as R0/R1 are hashed
     233              :        into the coin priv. So here, we fail to 'reuse' the key due to the
     234              :        cryptographic construction! */
     235            2 :     TALER_TESTING_cmd_deposit (
     236              :       "deposit-reused-coin-key-failure",
     237              :       "withdraw-coin-1x",
     238              :       0,
     239              :       cred.user42_payto,
     240              :       "{\"items\":[{\"name\":\"conflicting ice cream\",\"value\":1}]}",
     241            2 :       GNUNET_TIME_UNIT_ZERO,
     242              :       "EUR:1",
     243              :       uses_cs
     244            2 :       ? MHD_HTTP_OK
     245              :       : MHD_HTTP_CONFLICT),
     246              :     /**
     247              :      * Try to double spend using different wire details.
     248              :      */
     249            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     250              :       "kyc-auth-transfer-2",
     251              :       "EUR:0.01",
     252              :       &cred.ba,
     253              :       cred.user43_payto,
     254              :       "deposit-simple-fail-kyc"),
     255            2 :     CMD_EXEC_WIREWATCH (
     256              :       "import-kyc-account-1"),
     257            2 :     TALER_TESTING_cmd_deposit (
     258              :       "deposit-double-1",
     259              :       "withdraw-coin-1",
     260              :       0,
     261              :       cred.user43_payto,
     262              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
     263            2 :       GNUNET_TIME_UNIT_ZERO,
     264              :       "EUR:5",
     265              :       MHD_HTTP_CONFLICT),
     266              :     /* Try to double spend using a different transaction id.
     267              :      * The test needs the contract terms to differ. This
     268              :      * is currently the case because of the "timestamp" field,
     269              :      * which is set automatically by #TALER_TESTING_cmd_deposit().
     270              :      * This could theoretically fail if at some point a deposit
     271              :      * command executes in less than 1 ms. */
     272            2 :     TALER_TESTING_cmd_deposit (
     273              :       "deposit-double-1",
     274              :       "withdraw-coin-1",
     275              :       0,
     276              :       cred.user43_payto,
     277              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
     278            2 :       GNUNET_TIME_UNIT_ZERO,
     279              :       "EUR:5",
     280              :       MHD_HTTP_CONFLICT),
     281              :     /**
     282              :      * Try to double spend with different proposal.
     283              :      */
     284            2 :     TALER_TESTING_cmd_deposit (
     285              :       "deposit-double-2",
     286              :       "withdraw-coin-1",
     287              :       0,
     288              :       cred.user43_payto,
     289              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}",
     290            2 :       GNUNET_TIME_UNIT_ZERO,
     291              :       "EUR:5",
     292              :       MHD_HTTP_CONFLICT),
     293            2 :     TALER_TESTING_cmd_end ()
     294              :   };
     295              : 
     296              :   struct TALER_TESTING_Command refresh[] = {
     297              :     /**
     298              :      * Try to melt the coin that shared the private key with another
     299              :      * coin (should fail). Note that in the CS-case, we fail also
     300              :      * with MHD_HTTP_CONFLICT, but for a different reason: here it
     301              :      * is not a denomination conflict, but a double-spending conflict.
     302              :      */
     303            2 :     TALER_TESTING_cmd_melt (
     304              :       "refresh-melt-reused-coin-key-failure",
     305              :       "withdraw-coin-1x",
     306              :       MHD_HTTP_CONFLICT,
     307              :       NULL),
     308              : 
     309              :     /* Fill reserve with EUR:5, 1ct is for fees. */
     310            2 :     CMD_TRANSFER_TO_EXCHANGE (
     311              :       "refresh-create-reserve-1",
     312              :       "EUR:5.01"),
     313            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     314              :       "ck-refresh-create-reserve-1",
     315              :       "EUR:5.01",
     316              :       cred.user42_payto,
     317              :       cred.exchange_payto,
     318              :       "refresh-create-reserve-1"),
     319              :     /**
     320              :      * Make previous command effective.
     321              :      */
     322            2 :     CMD_EXEC_WIREWATCH ("wirewatch-2"),
     323              :     /**
     324              :      * Withdraw EUR:5.
     325              :      */
     326            2 :     TALER_TESTING_cmd_withdraw_amount (
     327              :       "refresh-withdraw-coin-1",
     328              :       "refresh-create-reserve-1",
     329              :       "EUR:5",
     330              :       0,                                  /* age restriction off */
     331              :       MHD_HTTP_OK),
     332              :     /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin
     333              :      * (in full) (merchant would receive EUR:0.99 due to 1 ct
     334              :      * deposit fee)
     335              :      */
     336            2 :     TALER_TESTING_cmd_deposit (
     337              :       "refresh-deposit-partial",
     338              :       "refresh-withdraw-coin-1",
     339              :       0,
     340              :       cred.user42_payto,
     341              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:1\"}]}",
     342            2 :       GNUNET_TIME_UNIT_ZERO,
     343              :       "EUR:1",
     344              :       MHD_HTTP_OK),
     345              :     /**
     346              :      * Melt the rest of the coin's value
     347              :      * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
     348            2 :     TALER_TESTING_cmd_melt_double (
     349              :       "refresh-melt-1",
     350              :       "refresh-withdraw-coin-1",
     351              :       MHD_HTTP_OK,
     352              :       NULL),
     353              :     /**
     354              :      * Complete (successful) melt operation, and
     355              :      * withdraw the coins
     356              :      */
     357            2 :     TALER_TESTING_cmd_melt_reveal (
     358              :       "refresh-reveal-1",
     359              :       "refresh-melt-1",
     360              :       MHD_HTTP_OK),
     361              :     /**
     362              :      * Do it again to check idempotency
     363              :      */
     364            2 :     TALER_TESTING_cmd_melt_reveal (
     365              :       "refresh-reveal-1-idempotency",
     366              :       "refresh-melt-1",
     367              :       MHD_HTTP_OK),
     368              :     /**
     369              :      * Try to spend a refreshed EUR:1 coin
     370              :      */
     371            2 :     TALER_TESTING_cmd_deposit (
     372              :       "refresh-deposit-refreshed-1a",
     373              :       "refresh-reveal-1-idempotency",
     374              :       0,
     375              :       cred.user42_payto,
     376              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}",
     377            2 :       GNUNET_TIME_UNIT_ZERO,
     378              :       "EUR:1",
     379              :       MHD_HTTP_OK),
     380              :     /**
     381              :      * Try to spend a refreshed EUR:0.1 coin
     382              :      */
     383            2 :     TALER_TESTING_cmd_deposit (
     384              :       "refresh-deposit-refreshed-1b",
     385              :       "refresh-reveal-1",
     386              :       3,
     387              :       cred.user43_payto,
     388              :       "{\"items\":[{\"name\":\"cheap ice cream\",\"value\":3}]}",
     389            2 :       GNUNET_TIME_UNIT_ZERO,
     390              :       "EUR:0.1",
     391              :       MHD_HTTP_OK),
     392              :     /* Test running a failing melt operation (same operation
     393              :      * again must fail) */
     394            2 :     TALER_TESTING_cmd_melt (
     395              :       "refresh-melt-failing",
     396              :       "refresh-withdraw-coin-1",
     397              :       MHD_HTTP_CONFLICT,
     398              :       NULL),
     399              :     /* Test running a failing melt operation (on a coin that
     400              :        was itself revealed and subsequently deposited) */
     401            2 :     TALER_TESTING_cmd_melt (
     402              :       "refresh-melt-failing-2",
     403              :       "refresh-reveal-1",
     404              :       MHD_HTTP_CONFLICT,
     405              :       NULL),
     406              : 
     407            2 :     TALER_TESTING_cmd_end ()
     408              :   };
     409              : 
     410              :   /**
     411              :    * Test withdrawal with age restriction.  Success is expected, so it MUST be
     412              :    * called _after_ TALER_TESTING_cmd_exec_offline_sign_extensions is called,
     413              :    * i. e. age restriction is activated in the exchange!
     414              :    *
     415              :    * FIXME[oec]: create a test that tries to withdraw coins with age restriction but
     416              :    * (expectedly) fails because the exchange doesn't support age restriction
     417              :    * yet.
     418              :    */
     419              :   struct TALER_TESTING_Command withdraw_age[] = {
     420              :     /**
     421              :      * Move money to the exchange's bank account.
     422              :      */
     423            2 :     CMD_TRANSFER_TO_EXCHANGE (
     424              :       "create-reserve-age",
     425              :       "EUR:6.01"),
     426            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     427              :       "check-create-reserve-age",
     428              :       "EUR:6.01",
     429              :       cred.user42_payto,
     430              :       cred.exchange_payto,
     431              :       "create-reserve-age"),
     432              :     /**
     433              :      * Make a reserve exist, according to the previous
     434              :      * transfer.
     435              :      */
     436            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age"),
     437              :     /**
     438              :      * Withdraw EUR:5.
     439              :      */
     440            2 :     TALER_TESTING_cmd_withdraw_amount (
     441              :       "withdraw-coin-age-1",
     442              :       "create-reserve-age",
     443              :       "EUR:5",
     444              :       13,
     445              :       MHD_HTTP_OK),
     446              : 
     447            2 :     TALER_TESTING_cmd_end ()
     448              :   };
     449              : 
     450              :   struct TALER_TESTING_Command spend_age[] = {
     451              :     /**
     452              :      * Spend the coin.
     453              :      */
     454            2 :     TALER_TESTING_cmd_deposit (
     455              :       "deposit-simple-age",
     456              :       "withdraw-coin-age-1",
     457              :       0,
     458              :       cred.user42_payto,
     459              :       "{\"items\":[{\"name\":\"unique ice cream\",\"value\":1}]}",
     460            2 :       GNUNET_TIME_UNIT_ZERO,
     461              :       "EUR:4.99",
     462              :       MHD_HTTP_OK),
     463            2 :     TALER_TESTING_cmd_deposit_replay (
     464              :       "deposit-simple-replay-age",
     465              :       "deposit-simple-age",
     466              :       MHD_HTTP_OK),
     467            2 :     TALER_TESTING_cmd_deposit_replay (
     468              :       "deposit-simple-replay-age-1",
     469              :       "deposit-simple-age",
     470              :       MHD_HTTP_OK),
     471            2 :     TALER_TESTING_cmd_sleep (
     472              :       "sleep-before-age-deposit-replay",
     473              :       1),
     474            2 :     TALER_TESTING_cmd_deposit_replay (
     475              :       "deposit-simple-replay-age-2",
     476              :       "deposit-simple-age",
     477              :       MHD_HTTP_OK),
     478            2 :     TALER_TESTING_cmd_end ()
     479              :   };
     480              : 
     481              :   struct TALER_TESTING_Command track[] = {
     482              :     /* Try resolving a deposit's WTID, as we never triggered
     483              :      * execution of transactions, the answer should be that
     484              :      * the exchange knows about the deposit, but has no WTID yet.
     485              :      */
     486            2 :     TALER_TESTING_cmd_deposits_get (
     487              :       "deposit-wtid-found",
     488              :       "deposit-simple",
     489              :       0,
     490              :       MHD_HTTP_ACCEPTED,
     491              :       NULL),
     492              :     /* Try resolving a deposit's WTID for a failed deposit.
     493              :      * As the deposit failed, the answer should be that the
     494              :      * exchange does NOT know about the deposit.
     495              :      */
     496            2 :     TALER_TESTING_cmd_deposits_get (
     497              :       "deposit-wtid-failing",
     498              :       "deposit-double-2",
     499              :       0,
     500              :       MHD_HTTP_NOT_FOUND,
     501              :       NULL),
     502              :     /* Try resolving an undefined (all zeros) WTID; this
     503              :      * should fail as obviously the exchange didn't use that
     504              :      * WTID value for any transaction.
     505              :      */
     506            2 :     TALER_TESTING_cmd_track_transfer_empty (
     507              :       "wire-deposit-failing",
     508              :       NULL,
     509              :       MHD_HTTP_NOT_FOUND),
     510              :     /* Run transfers. */
     511            2 :     CMD_EXEC_AGGREGATOR ("run-aggregator"),
     512              :     /**
     513              :      * Check all the transfers took place.
     514              :      */
     515            2 :     TALER_TESTING_cmd_check_bank_transfer (
     516              :       "check_bank_transfer-42-aggregate",
     517            2 :       cred.exchange_url,
     518              :       /* In case of CS, one transaction above succeeded that
     519              :          failed for RSA, hence we get a larger amount here */
     520            2 :       uses_cs ? "EUR:14.91" : "EUR:13.92",
     521              :       cred.exchange_payto,
     522              :       cred.user42_payto),
     523            2 :     TALER_TESTING_cmd_check_bank_transfer (
     524              :       "check_bank_transfer-43-aggregate",
     525            2 :       cred.exchange_url,
     526              :       "EUR:0.17",
     527              :       cred.exchange_payto,
     528              :       cred.user43_payto),
     529            2 :     TALER_TESTING_cmd_check_bank_empty ("check_bank_empty"),
     530            2 :     TALER_TESTING_cmd_deposits_get (
     531              :       "deposit-wtid-ok",
     532              :       "deposit-simple",
     533              :       0,
     534              :       MHD_HTTP_OK,
     535              :       "check_bank_transfer-42-aggregate"),
     536            2 :     TALER_TESTING_cmd_track_transfer (
     537              :       "wire-deposit-success-bank",
     538              :       "check_bank_transfer-42-aggregate",
     539              :       MHD_HTTP_OK,
     540            2 :       uses_cs ? "EUR:14.91" : "EUR:13.92",
     541              :       "EUR:0.01"),
     542            2 :     TALER_TESTING_cmd_track_transfer (
     543              :       "wire-deposits-success-wtid",
     544              :       "check_bank_transfer-43-aggregate",
     545              :       MHD_HTTP_OK,
     546              :       "EUR:0.17",
     547              :       "EUR:0.01"),
     548            2 :     TALER_TESTING_cmd_end ()
     549              :   };
     550              : 
     551              :   /**
     552              :    * This block checks whether a wire deadline
     553              :    * very far in the future does NOT get aggregated now.
     554              :    */
     555              :   struct TALER_TESTING_Command unaggregation[] = {
     556            2 :     TALER_TESTING_cmd_check_bank_empty ("far-future-aggregation-a"),
     557            2 :     CMD_TRANSFER_TO_EXCHANGE (
     558              :       "create-reserve-unaggregated",
     559              :       "EUR:5.01"),
     560              :     /* "consume" reserve creation transfer.  */
     561            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     562              :       "check-create-reserve-unaggregated",
     563              :       "EUR:5.01",
     564              :       cred.user42_payto,
     565              :       cred.exchange_payto,
     566              :       "create-reserve-unaggregated"),
     567            2 :     CMD_EXEC_WIREWATCH ("wirewatch-unaggregated"),
     568            2 :     TALER_TESTING_cmd_withdraw_amount (
     569              :       "withdraw-coin-unaggregated",
     570              :       "create-reserve-unaggregated",
     571              :       "EUR:5",
     572              :       0,                                  /* age restriction off */
     573              :       MHD_HTTP_OK),
     574            2 :     TALER_TESTING_cmd_deposit (
     575              :       "deposit-unaggregated",
     576              :       "withdraw-coin-unaggregated",
     577              :       0,
     578              :       cred.user43_payto,
     579              :       "{\"items\":[{\"name\":\"different ice cream\",\"value\":1}]}",
     580              :       GNUNET_TIME_relative_multiply (
     581              :         GNUNET_TIME_UNIT_YEARS,
     582              :         3000),
     583              :       "EUR:5",
     584              :       MHD_HTTP_OK),
     585            2 :     CMD_EXEC_AGGREGATOR ("aggregation-attempt"),
     586              : 
     587            2 :     TALER_TESTING_cmd_check_bank_empty (
     588              :       "far-future-aggregation-b"),
     589              : 
     590            2 :     TALER_TESTING_cmd_end ()
     591              :   };
     592              : 
     593              :   struct TALER_TESTING_Command refresh_age[] = {
     594              :     /* Fill reserve with EUR:5, 1ct is for fees. */
     595            2 :     CMD_TRANSFER_TO_EXCHANGE (
     596              :       "refresh-create-reserve-age-1",
     597              :       "EUR:6.01"),
     598            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     599              :       "ck-refresh-create-reserve-age-1",
     600              :       "EUR:6.01",
     601              :       cred.user42_payto,
     602              :       cred.exchange_payto,
     603              :       "refresh-create-reserve-age-1"),
     604              :     /**
     605              :      * Make previous command effective.
     606              :      */
     607            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age-2"),
     608              :     /**
     609              :      * Withdraw EUR:7 with age restriction for age 13.
     610              :      */
     611            2 :     TALER_TESTING_cmd_withdraw_amount (
     612              :       "refresh-withdraw-coin-age-1",
     613              :       "refresh-create-reserve-age-1",
     614              :       "EUR:5",
     615              :       13,
     616              :       MHD_HTTP_OK),
     617              :     /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin
     618              :      * (in full) (merchant would receive EUR:0.99 due to 1 ct
     619              :      * deposit fee)
     620              :      */
     621            2 :     TALER_TESTING_cmd_deposit (
     622              :       "refresh-deposit-partial-age",
     623              :       "refresh-withdraw-coin-age-1",
     624              :       0,
     625              :       cred.user42_payto,
     626              :       "{\"items\":[{\"name\":\"special ice cream\",\"value\":\"EUR:1\"}]}",
     627            2 :       GNUNET_TIME_UNIT_ZERO,
     628              :       "EUR:1",
     629              :       MHD_HTTP_OK),
     630              :     /**
     631              :      * Melt the rest of the coin's value
     632              :      * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
     633            2 :     TALER_TESTING_cmd_melt_double (
     634              :       "refresh-melt-age-1",
     635              :       "refresh-withdraw-coin-age-1",
     636              :       MHD_HTTP_OK,
     637              :       NULL),
     638              :     /**
     639              :      * Complete (successful) melt operation, and
     640              :      * withdraw the coins
     641              :      */
     642            2 :     TALER_TESTING_cmd_melt_reveal (
     643              :       "refresh-reveal-age-1",
     644              :       "refresh-melt-age-1",
     645              :       MHD_HTTP_OK),
     646              :     /**
     647              :      * Do it again to check idempotency
     648              :      */
     649            2 :     TALER_TESTING_cmd_melt_reveal (
     650              :       "refresh-reveal-age-1-idempotency",
     651              :       "refresh-melt-age-1",
     652              :       MHD_HTTP_OK),
     653              :     /**
     654              :      * Try to spend a refreshed EUR:1 coin
     655              :      */
     656            2 :     TALER_TESTING_cmd_deposit (
     657              :       "refresh-deposit-refreshed-age-1a",
     658              :       "refresh-reveal-age-1-idempotency",
     659              :       0,
     660              :       cred.user42_payto,
     661              :       "{\"items\":[{\"name\":\"garlic ice cream\",\"value\":3}]}",
     662            2 :       GNUNET_TIME_UNIT_ZERO,
     663              :       "EUR:1",
     664              :       MHD_HTTP_OK),
     665              :     /**
     666              :      * Try to spend a refreshed EUR:0.1 coin
     667              :      */
     668            2 :     TALER_TESTING_cmd_deposit (
     669              :       "refresh-deposit-refreshed-age-1b",
     670              :       "refresh-reveal-age-1",
     671              :       3,
     672              :       cred.user43_payto,
     673              :       "{\"items\":[{\"name\":\"spicy ice cream\",\"value\":3}]}",
     674            2 :       GNUNET_TIME_UNIT_ZERO,
     675              :       "EUR:0.1",
     676              :       MHD_HTTP_OK),
     677              :     /* Test running a failing melt operation (same operation
     678              :      * again must fail) */
     679            2 :     TALER_TESTING_cmd_melt (
     680              :       "refresh-melt-failing-age",
     681              :       "refresh-withdraw-coin-age-1",
     682              :       MHD_HTTP_CONFLICT,
     683              :       NULL),
     684              :     /* Test running a failing melt operation (on a coin that
     685              :        was itself revealed and subsequently deposited) */
     686            2 :     TALER_TESTING_cmd_melt (
     687              :       "refresh-melt-failing-age-2",
     688              :       "refresh-reveal-age-1",
     689              :       MHD_HTTP_CONFLICT,
     690              :       NULL),
     691            2 :     TALER_TESTING_cmd_end ()
     692              :   };
     693              : 
     694              :   /**
     695              :    * This block exercises the aggretation logic by making two payments
     696              :    * to the same merchant.
     697              :    */
     698              :   struct TALER_TESTING_Command aggregation[] = {
     699            2 :     CMD_TRANSFER_TO_EXCHANGE ("create-reserve-aggtest",
     700              :                               "EUR:5.01"),
     701              :     /* "consume" reserve creation transfer.  */
     702            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     703              :       "check-create-reserve-aggtest",
     704              :       "EUR:5.01",
     705              :       cred.user42_payto,
     706              :       cred.exchange_payto,
     707              :       "create-reserve-aggtest"),
     708            2 :     CMD_EXEC_WIREWATCH ("wirewatch-aggtest"),
     709            2 :     TALER_TESTING_cmd_withdraw_amount (
     710              :       "withdraw-coin-aggtest",
     711              :       "create-reserve-aggtest",
     712              :       "EUR:5",
     713              :       0,                                  /* age restriction off */
     714              :       MHD_HTTP_OK),
     715            2 :     TALER_TESTING_cmd_deposit (
     716              :       "deposit-aggtest-1",
     717              :       "withdraw-coin-aggtest",
     718              :       0,
     719              :       cred.user43_payto,
     720              :       "{\"items\":[{\"name\":\"cinamon ice cream\",\"value\":1}]}",
     721            2 :       GNUNET_TIME_UNIT_ZERO,
     722              :       "EUR:2",
     723              :       MHD_HTTP_OK),
     724            2 :     TALER_TESTING_cmd_deposit_with_ref (
     725              :       "deposit-aggtest-2",
     726              :       "withdraw-coin-aggtest",
     727              :       0,
     728              :       cred.user43_payto,
     729              :       "{\"items\":[{\"name\":\"foo bar\",\"value\":1}]}",
     730            2 :       GNUNET_TIME_UNIT_ZERO,
     731              :       "EUR:2",
     732              :       MHD_HTTP_OK,
     733              :       "deposit-aggtest-1"),
     734            2 :     CMD_EXEC_AGGREGATOR ("aggregation-aggtest"),
     735            2 :     TALER_TESTING_cmd_check_bank_transfer (
     736              :       "check-bank-transfer-aggtest",
     737            2 :       cred.exchange_url,
     738              :       "EUR:3.97",
     739              :       cred.exchange_payto,
     740              :       cred.user43_payto),
     741            2 :     TALER_TESTING_cmd_check_bank_empty ("check-bank-empty-aggtest"),
     742            2 :     TALER_TESTING_cmd_end ()
     743              :   };
     744              : 
     745              :   struct TALER_TESTING_Command refund[] = {
     746              :     /**
     747              :      * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
     748              :      * config.
     749              :      */
     750            2 :     CMD_TRANSFER_TO_EXCHANGE (
     751              :       "create-reserve-r1",
     752              :       "EUR:5.01"),
     753            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     754              :       "check-create-reserve-r1",
     755              :       "EUR:5.01",
     756              :       cred.user42_payto,
     757              :       cred.exchange_payto,
     758              :       "create-reserve-r1"),
     759              :     /**
     760              :      * Run wire-watch to trigger the reserve creation.
     761              :      */
     762            2 :     CMD_EXEC_WIREWATCH ("wirewatch-3"),
     763              :     /* Withdraw a 5 EUR coin, at fee of 1 ct */
     764            2 :     TALER_TESTING_cmd_withdraw_amount (
     765              :       "withdraw-coin-r1",
     766              :       "create-reserve-r1",
     767              :       "EUR:5",
     768              :       0,                                  /* age restriction off */
     769              :       MHD_HTTP_OK),
     770              :     /**
     771              :      * Spend 5 EUR of the 5 EUR coin (in full) (merchant would
     772              :      * receive EUR:4.99 due to 1 ct deposit fee)
     773              :      */
     774            2 :     TALER_TESTING_cmd_deposit (
     775              :       "deposit-refund-1",
     776              :       "withdraw-coin-r1",
     777              :       0,
     778              :       cred.user42_payto,
     779              :       "{\"items\":[{\"name\":\"blue ice cream\",\"value\":\"EUR:5\"}]}",
     780              :       GNUNET_TIME_UNIT_MINUTES,
     781              :       "EUR:5",
     782              :       MHD_HTTP_OK),
     783              :     /**
     784              :      * Run transfers. Should do nothing as refund deadline blocks it
     785              :      */
     786            2 :     CMD_EXEC_AGGREGATOR ("run-aggregator-refund"),
     787              :     /* Check that aggregator didn't do anything, as expected.
     788              :      * Note, this operation takes two commands: one to "flush"
     789              :      * the preliminary transfer (used to withdraw) from the
     790              :      * fakebank and the second to actually check there are not
     791              :      * other transfers around. */
     792            2 :     TALER_TESTING_cmd_check_bank_empty ("check_bank_transfer-pre-refund"),
     793            2 :     TALER_TESTING_cmd_refund_with_id (
     794              :       "refund-ok",
     795              :       MHD_HTTP_OK,
     796              :       "EUR:3",
     797              :       "deposit-refund-1",
     798              :       3),
     799            2 :     TALER_TESTING_cmd_refund_with_id (
     800              :       "refund-ok-double",
     801              :       MHD_HTTP_OK,
     802              :       "EUR:3",
     803              :       "deposit-refund-1",
     804              :       3),
     805              :     /* Previous /refund(s) had id == 0.  */
     806            2 :     TALER_TESTING_cmd_refund_with_id (
     807              :       "refund-conflicting",
     808              :       MHD_HTTP_CONFLICT,
     809              :       "EUR:5",
     810              :       "deposit-refund-1",
     811              :       1),
     812            2 :     TALER_TESTING_cmd_deposit (
     813              :       "deposit-refund-insufficient-refund",
     814              :       "withdraw-coin-r1",
     815              :       0,
     816              :       cred.user42_payto,
     817              :       "{\"items\":[{\"name\":\"fruit ice cream\",\"value\":\"EUR:4\"}]}",
     818              :       GNUNET_TIME_UNIT_MINUTES,
     819              :       "EUR:4",
     820              :       MHD_HTTP_CONFLICT),
     821            2 :     TALER_TESTING_cmd_refund_with_id (
     822              :       "refund-ok-increase",
     823              :       MHD_HTTP_OK,
     824              :       "EUR:2",
     825              :       "deposit-refund-1",
     826              :       2),
     827              :     /**
     828              :      * Spend 4.99 EUR of the refunded 4.99 EUR coin (1ct gone
     829              :      * due to refund) (merchant would receive EUR:4.98 due to
     830              :      * 1 ct deposit fee) */
     831            2 :     TALER_TESTING_cmd_deposit (
     832              :       "deposit-refund-2",
     833              :       "withdraw-coin-r1",
     834              :       0,
     835              :       cred.user42_payto,
     836              :       "{\"items\":[{\"name\":\"more ice cream\",\"value\":\"EUR:5\"}]}",
     837            2 :       GNUNET_TIME_UNIT_ZERO,
     838              :       "EUR:4.99",
     839              :       MHD_HTTP_OK),
     840              :     /**
     841              :      * Run transfers. This will do the transfer as refund deadline
     842              :      * was 0
     843              :      */
     844            2 :     CMD_EXEC_AGGREGATOR ("run-aggregator-3"),
     845              :     /**
     846              :      * Check that deposit did run.
     847              :      */
     848            2 :     TALER_TESTING_cmd_check_bank_transfer (
     849              :       "check_bank_transfer-pre-refund",
     850            2 :       cred.exchange_url,
     851              :       "EUR:4.97",
     852              :       cred.exchange_payto,
     853              :       cred.user42_payto),
     854              :     /**
     855              :      * Run failing refund, as past deadline & aggregation.
     856              :      */
     857            2 :     TALER_TESTING_cmd_refund (
     858              :       "refund-fail",
     859              :       MHD_HTTP_GONE,
     860              :       "EUR:4.99",
     861              :       "deposit-refund-2"),
     862            2 :     TALER_TESTING_cmd_check_bank_empty ("check-empty-after-refund"),
     863              :     /**
     864              :      * Test refunded coins are never executed, even past
     865              :      * refund deadline
     866              :      */
     867            2 :     CMD_TRANSFER_TO_EXCHANGE (
     868              :       "create-reserve-rb",
     869              :       "EUR:5.01"),
     870            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     871              :       "check-create-reserve-rb",
     872              :       "EUR:5.01",
     873              :       cred.user42_payto,
     874              :       cred.exchange_payto,
     875              :       "create-reserve-rb"),
     876            2 :     CMD_EXEC_WIREWATCH ("wirewatch-rb"),
     877            2 :     TALER_TESTING_cmd_withdraw_amount (
     878              :       "withdraw-coin-rb",
     879              :       "create-reserve-rb",
     880              :       "EUR:5",
     881              :       0,                                  /* age restriction off */
     882              :       MHD_HTTP_OK),
     883            2 :     TALER_TESTING_cmd_deposit (
     884              :       "deposit-refund-1b",
     885              :       "withdraw-coin-rb",
     886              :       0,
     887              :       cred.user42_payto,
     888              :       "{\"items\":[{\"name\":\"purple ice cream\",\"value\":\"EUR:5\"}]}",
     889            2 :       GNUNET_TIME_UNIT_ZERO,
     890              :       "EUR:5",
     891              :       MHD_HTTP_OK),
     892              :     /**
     893              :      * Trigger refund (before aggregator had a chance to execute
     894              :      * deposit, even though refund deadline was zero).
     895              :      */
     896            2 :     TALER_TESTING_cmd_refund (
     897              :       "refund-ok-fast",
     898              :       MHD_HTTP_OK,
     899              :       "EUR:5",
     900              :       "deposit-refund-1b"),
     901              :     /**
     902              :      * Run transfers. This will do the transfer as refund deadline
     903              :      * was 0, except of course because the refund succeeded, the
     904              :      * transfer should no longer be done.
     905              :      */
     906            2 :     CMD_EXEC_AGGREGATOR ("run-aggregator-3b"),
     907              :     /* check that aggregator didn't do anything, as expected */
     908            2 :     TALER_TESTING_cmd_check_bank_empty ("check-refund-fast-not-run"),
     909            2 :     TALER_TESTING_cmd_end ()
     910              :   };
     911              : 
     912              : #if FIXME_9828
     913              :   struct TALER_TESTING_Command recoup[] = {
     914              :     /**
     915              :      * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
     916              :      * config.
     917              :      */
     918              :     CMD_TRANSFER_TO_EXCHANGE (
     919              :       "recoup-create-reserve-1",
     920              :       "EUR:15.02"),
     921              :     TALER_TESTING_cmd_check_bank_admin_transfer (
     922              :       "recoup-create-reserve-1-check",
     923              :       "EUR:15.02",
     924              :       cred.user42_payto,
     925              :       cred.exchange_payto,
     926              :       "recoup-create-reserve-1"),
     927              :     /**
     928              :      * Run wire-watch to trigger the reserve creation.
     929              :      */
     930              :     CMD_EXEC_WIREWATCH ("wirewatch-4"),
     931              :     /* Withdraw a 5 EUR coin, at fee of 1 ct */
     932              :     TALER_TESTING_cmd_withdraw_amount (
     933              :       "recoup-withdraw-coin-1",
     934              :       "recoup-create-reserve-1",
     935              :       "EUR:5",
     936              :       0,                                  /* age restriction off */
     937              :       MHD_HTTP_OK),
     938              :     /* Withdraw a 10 EUR coin, at fee of 1 ct */
     939              :     TALER_TESTING_cmd_withdraw_amount (
     940              :       "recoup-withdraw-coin-1b",
     941              :       "recoup-create-reserve-1",
     942              :       "EUR:10",
     943              :       0,                                  /* age restriction off */
     944              :       MHD_HTTP_OK),
     945              :     /* melt 10 EUR coin to get 5 EUR refreshed coin */
     946              :     TALER_TESTING_cmd_melt (
     947              :       "recoup-melt-coin-1b",
     948              :       "recoup-withdraw-coin-1b",
     949              :       MHD_HTTP_OK,
     950              :       "EUR:5",
     951              :       NULL),
     952              :     TALER_TESTING_cmd_melt_reveal (
     953              :       "recoup-reveal-coin-1b",
     954              :       "recoup-melt-coin-1b",
     955              :       MHD_HTTP_OK),
     956              :     /* Revoke both 5 EUR coins */
     957              :     TALER_TESTING_cmd_revoke (
     958              :       "revoke-0-EUR:5",
     959              :       MHD_HTTP_OK,
     960              :       "recoup-withdraw-coin-1",
     961              :       config_file),
     962              :     /* Recoup coin to reserve */
     963              :     TALER_TESTING_cmd_recoup (
     964              :       "recoup-1",
     965              :       MHD_HTTP_OK,
     966              :       "recoup-withdraw-coin-1",
     967              :       "EUR:5"),
     968              :     /* Check the money is back with the reserve */
     969              :     TALER_TESTING_cmd_status (
     970              :       "recoup-reserve-status-1",
     971              :       "recoup-create-reserve-1",
     972              :       "EUR:5.0",
     973              :       MHD_HTTP_OK),
     974              :     /* Recoup-refresh coin to 10 EUR coin */
     975              :     TALER_TESTING_cmd_recoup_refresh (
     976              :       "recoup-1b",
     977              :       MHD_HTTP_OK,
     978              :       "recoup-reveal-coin-1b",
     979              :       "recoup-melt-coin-1b",
     980              :       "EUR:5"),
     981              :     /* melt 10 EUR coin *again* to get 1 EUR refreshed coin */
     982              :     TALER_TESTING_cmd_melt (
     983              :       "recoup-remelt-coin-1a",
     984              :       "recoup-withdraw-coin-1b",
     985              :       MHD_HTTP_OK,
     986              :       "EUR:1",
     987              :       NULL),
     988              :     TALER_TESTING_cmd_melt_reveal (
     989              :       "recoup-reveal-coin-1a",
     990              :       "recoup-remelt-coin-1a",
     991              :       MHD_HTTP_OK),
     992              :     /* Try melting for more than the residual value to provoke an error */
     993              :     TALER_TESTING_cmd_melt (
     994              :       "recoup-remelt-coin-1b",
     995              :       "recoup-withdraw-coin-1b",
     996              :       MHD_HTTP_OK,
     997              :       "EUR:1",
     998              :       NULL),
     999              :     TALER_TESTING_cmd_melt (
    1000              :       "recoup-remelt-coin-1c",
    1001              :       "recoup-withdraw-coin-1b",
    1002              :       MHD_HTTP_OK,
    1003              :       "EUR:1",
    1004              :       NULL),
    1005              :     TALER_TESTING_cmd_melt (
    1006              :       "recoup-remelt-coin-1d",
    1007              :       "recoup-withdraw-coin-1b",
    1008              :       MHD_HTTP_OK,
    1009              :       "EUR:1",
    1010              :       NULL),
    1011              :     TALER_TESTING_cmd_melt (
    1012              :       "recoup-remelt-coin-1e",
    1013              :       "recoup-withdraw-coin-1b",
    1014              :       MHD_HTTP_OK,
    1015              :       "EUR:1",
    1016              :       NULL),
    1017              :     TALER_TESTING_cmd_melt (
    1018              :       "recoup-remelt-coin-1f",
    1019              :       "recoup-withdraw-coin-1b",
    1020              :       MHD_HTTP_OK,
    1021              :       "EUR:1",
    1022              :       NULL),
    1023              :     TALER_TESTING_cmd_melt (
    1024              :       "recoup-remelt-coin-1g",
    1025              :       "recoup-withdraw-coin-1b",
    1026              :       MHD_HTTP_OK,
    1027              :       "EUR:1",
    1028              :       NULL),
    1029              :     TALER_TESTING_cmd_melt (
    1030              :       "recoup-remelt-coin-1h",
    1031              :       "recoup-withdraw-coin-1b",
    1032              :       MHD_HTTP_OK,
    1033              :       "EUR:1",
    1034              :       NULL),
    1035              :     TALER_TESTING_cmd_melt (
    1036              :       "recoup-remelt-coin-1i",
    1037              :       "recoup-withdraw-coin-1b",
    1038              :       MHD_HTTP_OK,
    1039              :       "EUR:1",
    1040              :       NULL),
    1041              :     TALER_TESTING_cmd_melt (
    1042              :       "recoup-remelt-coin-1b-failing",
    1043              :       "recoup-withdraw-coin-1b",
    1044              :       MHD_HTTP_CONFLICT,
    1045              :       "EUR:1",
    1046              :       NULL),
    1047              :     /* Re-withdraw from this reserve */
    1048              :     TALER_TESTING_cmd_withdraw_amount (
    1049              :       "recoup-withdraw-coin-2",
    1050              :       "recoup-create-reserve-1",
    1051              :       "EUR:1",
    1052              :       0,                                  /* age restriction off */
    1053              :       MHD_HTTP_OK),
    1054              :     /**
    1055              :      * This withdrawal will test the logic to create a "recoup"
    1056              :      * element to insert into the reserve's history.
    1057              :      */
    1058              :     TALER_TESTING_cmd_withdraw_amount (
    1059              :       "recoup-withdraw-coin-2-over",
    1060              :       "recoup-create-reserve-1",
    1061              :       "EUR:10",
    1062              :       0,                                  /* age restriction off */
    1063              :       MHD_HTTP_CONFLICT),
    1064              :     TALER_TESTING_cmd_status (
    1065              :       "recoup-reserve-status-2",
    1066              :       "recoup-create-reserve-1",
    1067              :       "EUR:3.99",
    1068              :       MHD_HTTP_OK),
    1069              :     /* These commands should close the reserve because
    1070              :      * the aggregator is given a config file that overrides
    1071              :      * the reserve expiration time (making it now-ish) */
    1072              :     CMD_TRANSFER_TO_EXCHANGE ("short-lived-reserve",
    1073              :                               "EUR:5.01"),
    1074              :     TALER_TESTING_cmd_check_bank_admin_transfer (
    1075              :       "check-short-lived-reserve",
    1076              :       "EUR:5.01",
    1077              :       cred.user42_payto,
    1078              :       cred.exchange_payto,
    1079              :       "short-lived-reserve"),
    1080              :     TALER_TESTING_cmd_exec_wirewatch2 (
    1081              :       "short-lived-aggregation",
    1082              :       config_file_expire_reserve_now,
    1083              :       "exchange-account-2"),
    1084              :     TALER_TESTING_cmd_exec_closer (
    1085              :       "close-reserves",
    1086              :       config_file_expire_reserve_now,
    1087              :       "EUR:5",
    1088              :       "EUR:0.01",
    1089              :       "short-lived-reserve"),
    1090              :     TALER_TESTING_cmd_exec_transfer (
    1091              :       "close-reserves-transfer",
    1092              :       config_file_expire_reserve_now),
    1093              : 
    1094              :     TALER_TESTING_cmd_status (
    1095              :       "short-lived-status",
    1096              :       "short-lived-reserve",
    1097              :       "EUR:0",
    1098              :       MHD_HTTP_OK),
    1099              :     TALER_TESTING_cmd_withdraw_amount (
    1100              :       "expired-withdraw",
    1101              :       "short-lived-reserve",
    1102              :       "EUR:1",
    1103              :       0,                                  /* age restriction off */
    1104              :       MHD_HTTP_CONFLICT),
    1105              :     TALER_TESTING_cmd_check_bank_transfer (
    1106              :       "check_bank_short-lived_reimburse",
    1107              :       cred.exchange_url,
    1108              :       "EUR:5",
    1109              :       cred.exchange_payto,
    1110              :       cred.user42_payto),
    1111              :     /* Fill reserve with EUR:2.02, as withdraw fee is 1 ct per
    1112              :      * config, then withdraw two coin, partially spend one, and
    1113              :      * then have the rest paid back.  Check deposit of other coin
    1114              :      * fails.  Do not use EUR:5 here as the EUR:5 coin was
    1115              :      * revoked and we did not bother to create a new one... */
    1116              :     CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-2",
    1117              :                               "EUR:2.02"),
    1118              :     TALER_TESTING_cmd_check_bank_admin_transfer (
    1119              :       "ck-recoup-create-reserve-2",
    1120              :       "EUR:2.02",
    1121              :       cred.user42_payto,
    1122              :       cred.exchange_payto,
    1123              :       "recoup-create-reserve-2"),
    1124              :     /* Make previous command effective. */
    1125              :     CMD_EXEC_WIREWATCH ("wirewatch-5"),
    1126              :     /* Withdraw a 1 EUR coin, at fee of 1 ct */
    1127              :     TALER_TESTING_cmd_withdraw_amount (
    1128              :       "recoup-withdraw-coin-2a",
    1129              :       "recoup-create-reserve-2",
    1130              :       "EUR:1",
    1131              :       0,                                  /* age restriction off */
    1132              :       MHD_HTTP_OK),
    1133              :     /* Withdraw a 1 EUR coin, at fee of 1 ct */
    1134              :     TALER_TESTING_cmd_withdraw_amount (
    1135              :       "recoup-withdraw-coin-2b",
    1136              :       "recoup-create-reserve-2",
    1137              :       "EUR:1",
    1138              :       0,                                  /* age restriction off */
    1139              :       MHD_HTTP_OK),
    1140              :     TALER_TESTING_cmd_deposit (
    1141              :       "recoup-deposit-partial",
    1142              :       "recoup-withdraw-coin-2a",
    1143              :       0,
    1144              :       cred.user42_payto,
    1145              :       "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
    1146              :       GNUNET_TIME_UNIT_ZERO,
    1147              :       "EUR:0.5",
    1148              :       MHD_HTTP_OK),
    1149              :     TALER_TESTING_cmd_revoke (
    1150              :       "revoke-1-EUR:1",
    1151              :       MHD_HTTP_OK,
    1152              :       "recoup-withdraw-coin-2a",
    1153              :       config_file),
    1154              :     /* Check recoup is failing for the coin with the reused coin key
    1155              :        (fails either because of denomination conflict (RSA) or
    1156              :        double-spending (CS))*/
    1157              :     TALER_TESTING_cmd_recoup (
    1158              :       "recoup-2x",
    1159              :       MHD_HTTP_CONFLICT,
    1160              :       "withdraw-coin-1x",
    1161              :       "EUR:1"),
    1162              :     TALER_TESTING_cmd_recoup (
    1163              :       "recoup-2",
    1164              :       MHD_HTTP_OK,
    1165              :       "recoup-withdraw-coin-2a",
    1166              :       "EUR:0.5"),
    1167              :     /* Idempotency of recoup (withdrawal variant) */
    1168              :     TALER_TESTING_cmd_recoup (
    1169              :       "recoup-2b",
    1170              :       MHD_HTTP_OK,
    1171              :       "recoup-withdraw-coin-2a",
    1172              :       "EUR:0.5"),
    1173              :     TALER_TESTING_cmd_deposit (
    1174              :       "recoup-deposit-revoked",
    1175              :       "recoup-withdraw-coin-2b",
    1176              :       0,
    1177              :       cred.user42_payto,
    1178              :       "{\"items\":[{\"name\":\"gnu ice cream\",\"value\":1}]}",
    1179              :       GNUNET_TIME_UNIT_ZERO,
    1180              :       "EUR:1",
    1181              :       MHD_HTTP_GONE),
    1182              :     /* Test deposit fails after recoup, with proof in recoup */
    1183              : 
    1184              :     /* Note that, the exchange will never return the coin's transaction
    1185              :      * history with recoup data, as we get a 410 on the DK! */
    1186              :     TALER_TESTING_cmd_deposit (
    1187              :       "recoup-deposit-partial-after-recoup",
    1188              :       "recoup-withdraw-coin-2a",
    1189              :       0,
    1190              :       cred.user42_payto,
    1191              :       "{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}",
    1192              :       GNUNET_TIME_UNIT_ZERO,
    1193              :       "EUR:0.5",
    1194              :       MHD_HTTP_GONE),
    1195              :     /* Test that revoked coins cannot be withdrawn */
    1196              :     CMD_TRANSFER_TO_EXCHANGE (
    1197              :       "recoup-create-reserve-3",
    1198              :       "EUR:1.01"),
    1199              :     TALER_TESTING_cmd_check_bank_admin_transfer (
    1200              :       "check-recoup-create-reserve-3",
    1201              :       "EUR:1.01",
    1202              :       cred.user42_payto,
    1203              :       cred.exchange_payto,
    1204              :       "recoup-create-reserve-3"),
    1205              :     CMD_EXEC_WIREWATCH ("wirewatch-6"),
    1206              :     TALER_TESTING_cmd_withdraw_amount (
    1207              :       "recoup-withdraw-coin-3-revoked",
    1208              :       "recoup-create-reserve-3",
    1209              :       "EUR:1",
    1210              :       0,                                  /* age restriction off */
    1211              :       MHD_HTTP_GONE),
    1212              :     /* check that we are empty before the rejection test */
    1213              :     TALER_TESTING_cmd_check_bank_empty ("check-empty-again"),
    1214              : 
    1215              :     TALER_TESTING_cmd_end ()
    1216              :   };
    1217              : #endif
    1218              : 
    1219              :   /**
    1220              :    * Test batch withdrawal plus spending.
    1221              :    */
    1222              :   struct TALER_TESTING_Command batch_withdraw[] = {
    1223              :     /**
    1224              :      * Move money to the exchange's bank account.
    1225              :      */
    1226            2 :     CMD_TRANSFER_TO_EXCHANGE (
    1227              :       "create-batch-reserve-1",
    1228              :       "EUR:6.03"),
    1229            2 :     TALER_TESTING_cmd_reserve_poll (
    1230              :       "poll-batch-reserve-1",
    1231              :       "create-batch-reserve-1",
    1232              :       "EUR:6.03",
    1233              :       GNUNET_TIME_UNIT_MINUTES,
    1234              :       MHD_HTTP_OK),
    1235            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
    1236              :       "check-create-batch-reserve-1",
    1237              :       "EUR:6.03",
    1238              :       cred.user42_payto,
    1239              :       cred.exchange_payto,
    1240              :       "create-batch-reserve-1"),
    1241              :     /*
    1242              :      * Make a reserve exist, according to the previous
    1243              :      * transfer.
    1244              :      */
    1245            2 :     CMD_EXEC_WIREWATCH ("wirewatch-batch-1"),
    1246            2 :     TALER_TESTING_cmd_reserve_poll_finish (
    1247              :       "finish-poll-batch-reserve-1",
    1248              :       GNUNET_TIME_UNIT_SECONDS,
    1249              :       "poll-batch-reserve-1"),
    1250              :     /**
    1251              :      * Withdraw EUR:5 AND EUR:1.
    1252              :      */
    1253            2 :     TALER_TESTING_cmd_batch_withdraw (
    1254              :       "batch-withdraw-coin-1",
    1255              :       "create-batch-reserve-1",
    1256              :       MHD_HTTP_OK,
    1257              :       "EUR:5",
    1258              :       "EUR:1",
    1259              :       NULL),
    1260              :     /**
    1261              :      * Check the reserve is (almost) depleted.
    1262              :      */
    1263            2 :     TALER_TESTING_cmd_status (
    1264              :       "status-batch-1",
    1265              :       "create-batch-reserve-1",
    1266              :       "EUR:0.01",
    1267              :       MHD_HTTP_OK),
    1268            2 :     TALER_TESTING_cmd_reserve_history (
    1269              :       "history-batch-1",
    1270              :       "create-batch-reserve-1",
    1271              :       "EUR:0.01",
    1272              :       MHD_HTTP_OK),
    1273              :     /**
    1274              :      * Spend the coins.
    1275              :      */
    1276            2 :     TALER_TESTING_cmd_batch_deposit (
    1277              :       "batch-deposit-1",
    1278              :       cred.user42_payto,
    1279              :       "{\"items\":[{\"name\":\"final ice cream\",\"value\":5}]}",
    1280            2 :       GNUNET_TIME_UNIT_ZERO,
    1281              :       MHD_HTTP_OK,
    1282              :       "batch-withdraw-coin-1#0",
    1283              :       "EUR:5",
    1284              :       "batch-withdraw-coin-1#1",
    1285              :       "EUR:1",
    1286              :       NULL),
    1287            2 :     TALER_TESTING_cmd_coin_history (
    1288              :       "coin-history-batch-1",
    1289              :       "batch-withdraw-coin-1#0",
    1290              :       "EUR:0.0",
    1291              :       MHD_HTTP_OK),
    1292            2 :     TALER_TESTING_cmd_end ()
    1293              :   };
    1294              : 
    1295              : 
    1296              : #define RESERVE_OPEN_CLOSE_CHUNK 4
    1297              : #define RESERVE_OPEN_CLOSE_ITERATIONS 3
    1298              : 
    1299              :   struct TALER_TESTING_Command reserve_open_close[(RESERVE_OPEN_CLOSE_ITERATIONS
    1300              :                                                    * RESERVE_OPEN_CLOSE_CHUNK)
    1301              :                                                   + 1];
    1302              : 
    1303              :   (void) cls;
    1304            2 :   for (unsigned int i = 0;
    1305            8 :        i < RESERVE_OPEN_CLOSE_ITERATIONS;
    1306            6 :        i++)
    1307              :   {
    1308            6 :     reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 0]
    1309            6 :       = CMD_TRANSFER_TO_EXCHANGE ("reserve-open-close-key",
    1310              :                                   "EUR:20");
    1311            6 :     reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 1]
    1312            6 :       = TALER_TESTING_cmd_exec_wirewatch2 ("reserve-open-close-wirewatch",
    1313              :                                            config_file_expire_reserve_now,
    1314              :                                            "exchange-account-2");
    1315            6 :     reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 2]
    1316            6 :       = TALER_TESTING_cmd_exec_closer ("reserve-open-close-aggregation",
    1317              :                                        config_file_expire_reserve_now,
    1318              :                                        "EUR:19.99",
    1319              :                                        "EUR:0.01",
    1320              :                                        "reserve-open-close-key");
    1321            6 :     reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 3]
    1322            6 :       = TALER_TESTING_cmd_status ("reserve-open-close-status",
    1323              :                                   "reserve-open-close-key",
    1324              :                                   "EUR:0",
    1325              :                                   MHD_HTTP_OK);
    1326              :   }
    1327              :   reserve_open_close[RESERVE_OPEN_CLOSE_ITERATIONS * RESERVE_OPEN_CLOSE_CHUNK]
    1328            2 :     = TALER_TESTING_cmd_end ();
    1329              : 
    1330              :   {
    1331              :     struct TALER_TESTING_Command commands[] = {
    1332            2 :       TALER_TESTING_cmd_run_fakebank ("run-fakebank",
    1333            2 :                                       cred.cfg,
    1334              :                                       "exchange-account-2"),
    1335            2 :       TALER_TESTING_cmd_system_start ("start-taler",
    1336              :                                       config_file,
    1337              :                                       "-e",
    1338              :                                       NULL),
    1339            2 :       TALER_TESTING_cmd_get_exchange ("get-exchange",
    1340            2 :                                       cred.cfg,
    1341              :                                       NULL,
    1342              :                                       true,
    1343              :                                       true),
    1344            2 :       TALER_TESTING_cmd_batch ("withdraw",
    1345              :                                withdraw),
    1346            2 :       TALER_TESTING_cmd_batch ("spend",
    1347              :                                spend),
    1348            2 :       TALER_TESTING_cmd_batch ("refresh",
    1349              :                                refresh),
    1350            2 :       TALER_TESTING_cmd_batch ("withdraw-age",
    1351              :                                withdraw_age),
    1352            2 :       TALER_TESTING_cmd_batch ("spend-age",
    1353              :                                spend_age),
    1354            2 :       TALER_TESTING_cmd_batch ("refresh-age",
    1355              :                                refresh_age),
    1356            2 :       TALER_TESTING_cmd_batch ("track",
    1357              :                                track),
    1358            2 :       TALER_TESTING_cmd_batch ("unaggregation",
    1359              :                                unaggregation),
    1360            2 :       TALER_TESTING_cmd_batch ("aggregation",
    1361              :                                aggregation),
    1362            2 :       TALER_TESTING_cmd_batch ("refund",
    1363              :                                refund),
    1364            2 :       TALER_TESTING_cmd_batch ("batch-withdraw",
    1365              :                                batch_withdraw),
    1366              : #if FIXME_9828
    1367              :       TALER_TESTING_cmd_batch ("recoup",
    1368              :                                recoup),
    1369              : #endif
    1370            2 :       TALER_TESTING_cmd_batch ("reserve-open-close",
    1371              :                                reserve_open_close),
    1372              :       /* End the suite. */
    1373            2 :       TALER_TESTING_cmd_end ()
    1374              :     };
    1375              : 
    1376            2 :     TALER_TESTING_run (is,
    1377              :                        commands);
    1378              :   }
    1379            2 : }
    1380              : 
    1381              : 
    1382              : int
    1383            2 : main (int argc,
    1384              :       char *const *argv)
    1385              : {
    1386              :   (void) argc;
    1387              :   {
    1388              :     char *cipher;
    1389              : 
    1390            2 :     cipher = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
    1391            2 :     GNUNET_assert (NULL != cipher);
    1392            2 :     uses_cs = (0 == strcmp (cipher,
    1393            2 :                             "cs"));
    1394            2 :     GNUNET_asprintf (&config_file,
    1395              :                      "test_exchange_api-%s.conf",
    1396              :                      cipher);
    1397            2 :     GNUNET_asprintf (&config_file_expire_reserve_now,
    1398              :                      "test_exchange_api_expire_reserve_now-%s.conf",
    1399              :                      cipher);
    1400            2 :     GNUNET_free (cipher);
    1401              :   }
    1402            2 :   return TALER_TESTING_main (argv,
    1403              :                              "INFO",
    1404              :                              config_file,
    1405              :                              "exchange-account-2",
    1406              :                              TALER_TESTING_BS_FAKEBANK,
    1407              :                              &cred,
    1408              :                              &run,
    1409              :                              NULL);
    1410              : }
    1411              : 
    1412              : 
    1413              : /* end of test_exchange_api.c */
        

Generated by: LCOV version 2.0-1