LCOV - code coverage report
Current view: top level - testing - test_exchange_api.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 196 196 100.0 %
Date: 2025-06-05 21:03:14 Functions: 2 2 100.0 %

          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 "platform.h"
      27             : #include "taler_util.h"
      28             : #include "taler_signatures.h"
      29             : #include "taler_exchange_service.h"
      30             : #include "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_bank_service.h"
      35             : #include "taler_fakebank_lib.h"
      36             : #include "taler_testing_lib.h"
      37             : #include "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             :                             "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 1.16