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 */