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

Generated by: LCOV version 2.0-1