exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test_exchange_api_age_restriction.c (12653B)


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