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

Generated by: LCOV version 2.0-1