LCOV - code coverage report
Current view: top level - testing - test_exchange_api_age_restriction.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 68 68
Test Date: 2026-06-14 14:19:22 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2023 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_age_restriction.c
      21              :  * @brief testcase to test exchange's age-restrictrition related HTTP API interfaces
      22              :  * @author Özgür Kesim
      23              :  */
      24              : #include "taler/taler_util.h"
      25              : #include "taler/taler_json_lib.h"
      26              : #include <gnunet/gnunet_util_lib.h>
      27              : #include <gnunet/gnunet_testing_lib.h>
      28              : #include <microhttpd.h>
      29              : #include "taler/taler_bank_service.h"
      30              : #include "taler/taler_testing_lib.h"
      31              : 
      32              : /**
      33              :  * Configuration file we use.  One (big) configuration is used
      34              :  * for the various components for this test.
      35              :  */
      36              : static char *config_file;
      37              : 
      38              : /**
      39              :  * Our credentials.
      40              :  */
      41              : static struct TALER_TESTING_Credentials cred;
      42              : 
      43              : /**
      44              :  * Some tests behave differently when using CS as we cannot
      45              :  * reuse the coin private key for different denominations
      46              :  * due to the derivation of it with the /csr values. Hence
      47              :  * some tests behave differently in CS mode, hence this
      48              :  * flag.
      49              :  */
      50              : static bool uses_cs;
      51              : 
      52              : /**
      53              :  * Execute the taler-exchange-wirewatch command with
      54              :  * our configuration file.
      55              :  *
      56              :  * @param label label to use for the command.
      57              :  */
      58              : #define CMD_EXEC_WIREWATCH(label) \
      59              :         TALER_TESTING_cmd_exec_wirewatch2 (label, config_file, \
      60              :                                            "exchange-account-2")
      61              : 
      62              : /**
      63              :  * Execute the taler-exchange-aggregator, closer and transfer commands with
      64              :  * our configuration file.
      65              :  *
      66              :  * @param label label to use for the command.
      67              :  */
      68              : #define CMD_EXEC_AGGREGATOR(label) \
      69              :         TALER_TESTING_cmd_sleep ("sleep-before-aggregator", 2), \
      70              :         TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \
      71              :         TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file)
      72              : 
      73              : 
      74              : /**
      75              :  * Run wire transfer of funds from some user's account to the
      76              :  * exchange.
      77              :  *
      78              :  * @param label label to use for the command.
      79              :  * @param amount amount to transfer, i.e. "EUR:1"
      80              :  */
      81              : #define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
      82              :         TALER_TESTING_cmd_admin_add_incoming (label, amount, \
      83              :                                               &cred.ba,                \
      84              :                                               cred.user42_payto)
      85              : 
      86              : /**
      87              :  * Main function that will tell the interpreter what commands to
      88              :  * run.
      89              :  *
      90              :  * @param cls closure
      91              :  * @param is interpreter we use to run commands
      92              :  */
      93              : static void
      94            2 : run (void *cls,
      95              :      struct TALER_TESTING_Interpreter *is)
      96              : {
      97              :   /**
      98              :    * Test withdrawal with age restriction.  Success is expected (because the
      99              :    * amount is below the kyc threshold ), so it MUST be
     100              :    * called age restriction is activated in the exchange!
     101              :    *
     102              :    * FIXME: create a test that tries to withdraw coins with age restriction but
     103              :    * (expectedly) fails because the exchange doesn't support age restrictions.
     104              :    */
     105              :   struct TALER_TESTING_Command withdraw_age[] = {
     106              :     /**
     107              :      * Move money to the exchange's bank account.
     108              :      */
     109            2 :     CMD_TRANSFER_TO_EXCHANGE (
     110              :       "create-reserve-age",
     111              :       "EUR:6.01"),
     112            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     113              :       "check-create-reserve-age",
     114              :       "EUR:6.01",
     115              :       cred.user42_payto,
     116              :       cred.exchange_payto,
     117              :       "create-reserve-age"),
     118              :     /**
     119              :      * Make a reserve exist, according to the previous
     120              :      * transfer.
     121              :      */
     122            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age"),
     123              :     /**
     124              :      * Withdraw EUR:5.
     125              :      */
     126            2 :     TALER_TESTING_cmd_withdraw_amount (
     127              :       "withdraw-coin-age-1",
     128              :       "create-reserve-age",
     129              :       "EUR:5",
     130              :       13,
     131              :       MHD_HTTP_OK),
     132              :     /**
     133              :      * Idempotent withdrawal.
     134              :      */
     135            2 :     TALER_TESTING_cmd_withdraw_amount_reuse_all_secrets (
     136              :       "withdraw-coin-age-idem-1",
     137              :       "create-reserve-age",
     138              :       "EUR:5",
     139              :       13,
     140              :       "withdraw-coin-age-1",
     141              :       MHD_HTTP_OK),
     142              : 
     143            2 :     TALER_TESTING_cmd_end ()
     144              :   };
     145              : 
     146              :   struct TALER_TESTING_Command spend_age[] = {
     147              :     /**
     148              :      * Spend the coin.
     149              :      */
     150            2 :     TALER_TESTING_cmd_set_var (
     151              :       "account-priv",
     152              :       TALER_TESTING_cmd_deposit (
     153              :         "deposit-simple-age-fail-kyc",
     154              :         "withdraw-coin-age-1",
     155              :         0,
     156              :         cred.user42_payto,
     157              :         "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
     158            2 :         GNUNET_TIME_UNIT_ZERO,
     159              :         "EUR:4.99",
     160              :         MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS)),
     161            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     162              :       "kyc-auth-transfer",
     163              :       "EUR:0.01",
     164              :       &cred.ba,
     165              :       cred.user42_payto,
     166              :       "deposit-simple-age-fail-kyc"),
     167            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     168              :       "kyc-auth-transfer",
     169              :       "EUR:0.01",
     170              :       &cred.ba,
     171              :       cred.user43_payto,
     172              :       "deposit-simple-age-fail-kyc"),
     173            2 :     CMD_EXEC_WIREWATCH (
     174              :       "import-kyc-account-withdraw"),
     175            2 :     TALER_TESTING_cmd_deposit (
     176              :       "deposit-simple-age",
     177              :       "withdraw-coin-age-1",
     178              :       0,
     179              :       cred.user42_payto,
     180              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}",
     181            2 :       GNUNET_TIME_UNIT_ZERO,
     182              :       "EUR:4.99",
     183              :       MHD_HTTP_OK),
     184            2 :     TALER_TESTING_cmd_deposit_replay (
     185              :       "deposit-simple-replay-age",
     186              :       "deposit-simple-age",
     187              :       MHD_HTTP_OK),
     188            2 :     TALER_TESTING_cmd_end ()
     189              :   };
     190              : 
     191              :   struct TALER_TESTING_Command refresh_age[] = {
     192              :     /* Fill reserve with EUR:5, 1ct is for fees. */
     193            2 :     CMD_TRANSFER_TO_EXCHANGE (
     194              :       "refresh-create-reserve-age-1",
     195              :       "EUR:6.01"),
     196            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     197              :       "ck-refresh-create-reserve-age-1",
     198              :       "EUR:6.01",
     199              :       cred.user42_payto,
     200              :       cred.exchange_payto,
     201              :       "refresh-create-reserve-age-1"),
     202              :     /**
     203              :      * Make previous command effective.
     204              :      */
     205            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age-2"),
     206              :     /**
     207              :      * Withdraw EUR:5 with age restriction for age 13.
     208              :      */
     209            2 :     TALER_TESTING_cmd_withdraw_amount (
     210              :       "refresh-withdraw-coin-age-1",
     211              :       "refresh-create-reserve-age-1",
     212              :       "EUR:5",
     213              :       13,
     214              :       MHD_HTTP_OK),
     215              :     /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin
     216              :      * (in full) (merchant would receive EUR:0.99 due to 1 ct
     217              :      * deposit fee)
     218              :      */
     219            2 :     TALER_TESTING_cmd_deposit (
     220              :       "refresh-deposit-partial-age",
     221              :       "refresh-withdraw-coin-age-1",
     222              :       0,
     223              :       cred.user42_payto,
     224              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:3\"}]}",
     225            2 :       GNUNET_TIME_UNIT_ZERO,
     226              :       "EUR:1",
     227              :       MHD_HTTP_OK),
     228              :     /**
     229              :      * Melt the rest of the coin's value
     230              :      * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
     231            2 :     TALER_TESTING_cmd_melt_double (
     232              :       "refresh-melt-age-1",
     233              :       "refresh-withdraw-coin-age-1",
     234              :       MHD_HTTP_OK,
     235              :       NULL),
     236              :     /**
     237              :      * Complete (successful) melt operation, and
     238              :      * withdraw the coins
     239              :      */
     240            2 :     TALER_TESTING_cmd_melt_reveal (
     241              :       "refresh-reveal-age-1",
     242              :       "refresh-melt-age-1",
     243              :       MHD_HTTP_OK),
     244              :     /**
     245              :      * Do it again to check idempotency
     246              :      */
     247            2 :     TALER_TESTING_cmd_melt_reveal (
     248              :       "refresh-reveal-age-1-idempotency",
     249              :       "refresh-melt-age-1",
     250              :       MHD_HTTP_OK),
     251              :     /**
     252              :      * Try to spend a refreshed EUR:1 coin
     253              :      */
     254            2 :     TALER_TESTING_cmd_deposit (
     255              :       "refresh-deposit-refreshed-age-1a",
     256              :       "refresh-reveal-age-1-idempotency",
     257              :       0,
     258              :       cred.user42_payto,
     259              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":4}]}",
     260            2 :       GNUNET_TIME_UNIT_ZERO,
     261              :       "EUR:1",
     262              :       MHD_HTTP_OK),
     263              :     /**
     264              :      * Try to spend a refreshed EUR:0.1 coin
     265              :      */
     266            2 :     TALER_TESTING_cmd_deposit (
     267              :       "refresh-deposit-refreshed-age-1b",
     268              :       "refresh-reveal-age-1",
     269              :       3,
     270              :       cred.user43_payto,
     271              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":5}]}",
     272            2 :       GNUNET_TIME_UNIT_ZERO,
     273              :       "EUR:0.1",
     274              :       MHD_HTTP_OK),
     275              :     /* Test running a failing melt operation (same operation
     276              :      * again must fail) */
     277            2 :     TALER_TESTING_cmd_melt (
     278              :       "refresh-melt-failing-age",
     279              :       "refresh-withdraw-coin-age-1",
     280              :       MHD_HTTP_CONFLICT,
     281              :       NULL),
     282              :     /* Test running a failing melt operation (on a coin that
     283              :        was itself revealed and subsequently deposited) */
     284            2 :     TALER_TESTING_cmd_melt (
     285              :       "refresh-melt-failing-age-2",
     286              :       "refresh-reveal-age-1",
     287              :       MHD_HTTP_CONFLICT,
     288              :       NULL),
     289            2 :     TALER_TESTING_cmd_end ()
     290              :   };
     291              : 
     292              :   /**
     293              :    * Test with age-withdraw, after kyc process has set a birthdate
     294              :    */
     295              :   struct TALER_TESTING_Command age_withdraw[] = {
     296            2 :     CMD_TRANSFER_TO_EXCHANGE (
     297              :       "create-reserve-kyc-1",
     298              :       "EUR:30.02"),
     299            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     300              :       "check-create-reserve-kyc-1",
     301              :       "EUR:30.02",
     302              :       cred.user42_payto,
     303              :       cred.exchange_payto,
     304              :       "create-reserve-kyc-1"),
     305            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age-withdraw-1"),
     306            2 :     TALER_TESTING_cmd_withdraw_amount (
     307              :       "withdraw-coin-1-lacking-kyc",
     308              :       "create-reserve-kyc-1",
     309              :       "EUR:10",
     310              :       0,    /* age restriction off */
     311              :       MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS),
     312            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     313              :       "setup-account-key",
     314              :       "EUR:0.01",
     315              :       &cred.ba,
     316              :       cred.user42_payto,
     317              :       NULL /* create new key */),
     318            2 :     CMD_EXEC_WIREWATCH (
     319              :       "import-kyc-account"),
     320            2 :     TALER_TESTING_cmd_check_kyc_get (
     321              :       "check-kyc-withdraw",
     322              :       "withdraw-coin-1-lacking-kyc",
     323              :       "setup-account-key",
     324              :       TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER,
     325              :       MHD_HTTP_ACCEPTED),
     326            2 :     TALER_TESTING_cmd_get_kyc_info (
     327              :       "get-kyc-info",
     328              :       "check-kyc-withdraw",
     329              :       MHD_HTTP_OK),
     330            2 :     TALER_TESTING_cmd_post_kyc_start (
     331              :       "start-kyc-process",
     332              :       "get-kyc-info",
     333              :       0,
     334              :       MHD_HTTP_OK),
     335            2 :     TALER_TESTING_cmd_proof_kyc_oauth2 (
     336              :       "proof-withdraw-kyc",
     337              :       "withdraw-coin-1-lacking-kyc",
     338              :       "test-oauth2",
     339              :       "pass",
     340              :       MHD_HTTP_SEE_OTHER),
     341            2 :     TALER_TESTING_cmd_withdraw_amount (
     342              :       "withdraw-coin-1-with-kyc",
     343              :       "create-reserve-kyc-1",
     344              :       "EUR:10",
     345              :       0,   /* age restriction off */
     346              :       MHD_HTTP_CONFLICT),
     347            2 :     TALER_TESTING_cmd_withdraw_with_age_proof (
     348              :       "age-withdraw-coin-1-too-low",
     349              :       "create-reserve-kyc-1",
     350              :       18,      /* Too high */
     351              :       MHD_HTTP_CONFLICT,
     352              :       "EUR:10",
     353              :       NULL),
     354            2 :     TALER_TESTING_cmd_withdraw_with_age_proof (
     355              :       "age-withdraw-coins-1",
     356              :       "create-reserve-kyc-1",
     357              :       8,
     358              :       MHD_HTTP_CREATED,
     359              :       "EUR:10",
     360              :       "EUR:10",
     361              :       "EUR:5",
     362              :       NULL),
     363            2 :     TALER_TESTING_cmd_withdraw_reveal_age_proof (
     364              :       "age-withdraw-coins-reveal-1",
     365              :       "age-withdraw-coins-1",
     366              :       MHD_HTTP_OK),
     367            2 :     TALER_TESTING_cmd_end (),
     368              :   };
     369              : 
     370              :   {
     371              :     struct TALER_TESTING_Command commands[] = {
     372            2 :       TALER_TESTING_cmd_run_fakebank (
     373              :         "run-fakebank",
     374            2 :         cred.cfg,
     375              :         "exchange-account-2"),
     376            2 :       TALER_TESTING_cmd_system_start (
     377              :         "start-taler",
     378              :         config_file,
     379              :         "-e",
     380              :         NULL),
     381            2 :       TALER_TESTING_cmd_get_exchange (
     382              :         "get-exchange",
     383            2 :         cred.cfg,
     384              :         NULL,
     385              :         true,
     386              :         true),
     387            2 :       TALER_TESTING_cmd_oauth_with_birthdate (
     388              :         "oauth-service-with-birthdate",
     389              :         "2015-00-00",    /* enough for a while */
     390              :         6666),
     391            2 :       TALER_TESTING_cmd_batch ("withdraw-age",
     392              :                                withdraw_age),
     393            2 :       TALER_TESTING_cmd_batch ("spend-age",
     394              :                                spend_age),
     395            2 :       TALER_TESTING_cmd_batch ("refresh-age",
     396              :                                refresh_age),
     397            2 :       TALER_TESTING_cmd_batch ("age-withdraw",
     398              :                                age_withdraw),
     399              :       /* End the suite. */
     400            2 :       TALER_TESTING_cmd_end ()
     401              :     };
     402              : 
     403              :     (void) cls;
     404            2 :     TALER_TESTING_run (is,
     405              :                        commands);
     406              :   }
     407            2 : }
     408              : 
     409              : 
     410              : int
     411            2 : main (int argc,
     412              :       char *const *argv)
     413              : {
     414              :   (void) argc;
     415              :   {
     416              :     char *cipher;
     417              : 
     418            2 :     cipher = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
     419            2 :     GNUNET_assert (NULL != cipher);
     420            2 :     uses_cs = (0 == strcmp (cipher,
     421            2 :                             "cs"));
     422            2 :     GNUNET_asprintf (
     423              :       &config_file,
     424              :       "test_exchange_api_age_restriction-%s.conf",
     425              :       cipher);
     426            2 :     GNUNET_free (cipher);
     427              :   }
     428            2 :   return TALER_TESTING_main (
     429              :     argv,
     430              :     "INFO",
     431              :     config_file,
     432              :     "exchange-account-2",
     433              :     TALER_TESTING_BS_FAKEBANK,
     434              :     &cred,
     435              :     &run,
     436              :     NULL);
     437              : }
     438              : 
     439              : 
     440              : /* end of test_exchange_api_age_restriction.c */
        

Generated by: LCOV version 2.0-1