diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-06-06 11:26:01 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-06-06 11:26:01 +0200 |
commit | 048684728159fba1c7417fd9ee881de97dc6949d (patch) | |
tree | af6c1d4b8d27073ff9f6d7f5c6754b6ab806b906 /src | |
parent | bf16c6e29031e828c946a23002c323aa6f0d78de (diff) |
-fix tests: add receiver-name to payto
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/merchant_api_post_order_pay.c | 220 | ||||
-rw-r--r-- | src/testing/test_kyc_api.c | 28 | ||||
-rw-r--r-- | src/testing/test_kyc_api.conf | 2 | ||||
-rw-r--r-- | src/testing/test_merchant_api-cs.conf | 2 | ||||
-rw-r--r-- | src/testing/test_merchant_api-rsa.conf | 2 | ||||
-rw-r--r-- | src/testing/test_merchant_api.c | 24 | ||||
-rw-r--r-- | src/testing/test_template.conf | 4 |
7 files changed, 203 insertions, 79 deletions
diff --git a/src/lib/merchant_api_post_order_pay.c b/src/lib/merchant_api_post_order_pay.c index bd6fca6f..4310838f 100644 --- a/src/lib/merchant_api_post_order_pay.c +++ b/src/lib/merchant_api_post_order_pay.c @@ -91,6 +91,29 @@ struct TALER_MERCHANT_OrderPayHandle struct TALER_MerchantPublicKeyP merchant_pub; /** + * JSON with the full reply, used during async + * processing. + */ + json_t *full_reply; + + /** + * Pointer into @e coins array for the coin that + * created a conflict (that we are checking). + */ + const struct TALER_MERCHANT_PaidCoin *error_pc; + + /** + * Coin history that proves a conflict. + */ + json_t *error_history; + + /** + * Handle to the exchange that issued a problematic + * coin (if any). + */ + struct TALER_EXCHANGE_Handle *exchange; + + /** * Number of @e coins we are paying with. */ unsigned int num_coins; @@ -109,38 +132,28 @@ struct TALER_MERCHANT_OrderPayHandle * Now we need to check the provided cryptographic proof that the * coin was actually already spent! * - * @param pc handle of the original coin we paid with - * @param json cryptographic proof of coin's transaction - * history as was returned by the exchange/merchant - * @return #GNUNET_OK if proof checks out + * @param oph operation handle + * @param keys key data from the exchange + * @return #GNUNET_OK if conflict is valid */ static enum GNUNET_GenericReturnValue -check_coin_history (const struct TALER_MERCHANT_PaidCoin *pc, - json_t *json) +check_conflict (struct TALER_MERCHANT_OrderPayHandle *oph, + const struct TALER_EXCHANGE_Keys *keys) { -#if FIXME struct TALER_Amount spent; struct TALER_Amount spent_plus_contrib; struct TALER_DenominationHashP h_denom_pub_pc; const struct TALER_EXCHANGE_DenomPublicKey *dpk; - const struct TALER_EXCHANGE_Keys *keys; - struct TALER_EXCHANGE_Handle *exchange; - exchange = TALER_EXCHANGE_connect (ctx, - pc->exchange_url, - &cert_cb, - ctx, - TALER_EXCHANGE_OPTION_END); - keys = TALER_EXCHANGE_get_keys (exchange); - TALER_denom_pub_hash (&pc->denom_pub, + TALER_denom_pub_hash (&oph->error_pc->denom_pub, &h_denom_pub_pc); dpk = TALER_EXCHANGE_get_denomination_key_by_hash ( keys, &h_denom_pub_pc); if (GNUNET_OK != TALER_EXCHANGE_verify_coin_history (dpk, - &pc->coin_pub, - json, + &oph->error_pc->coin_pub, + oph->error_history, &spent)) { /* Exchange's history fails to verify */ @@ -150,13 +163,13 @@ check_coin_history (const struct TALER_MERCHANT_PaidCoin *pc, if (0 > TALER_amount_add (&spent_plus_contrib, &spent, - &pc->amount_with_fee)) + &oph->error_pc->amount_with_fee)) { /* We got an integer overflow? Bad application! */ GNUNET_break (0); return GNUNET_SYSERR; } - if (-1 != TALER_amount_cmp (&pc->denom_value, + if (-1 != TALER_amount_cmp (&oph->error_pc->denom_value, &spent_plus_contrib)) { /* according to our calculations, the transaction should @@ -165,7 +178,6 @@ check_coin_history (const struct TALER_MERCHANT_PaidCoin *pc, GNUNET_break_op (0); return GNUNET_SYSERR; } -#endif GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Accepting proof of double-spending (or coin public key re-use)\n"); return GNUNET_OK; @@ -173,6 +185,91 @@ check_coin_history (const struct TALER_MERCHANT_PaidCoin *pc, /** + * We got the fee structure from the exchange. Now + * validate the conflict error. + * + * @param cls a `struct TALER_MERCHANT_OrderPayHandle` + * @param ehr reply from the exchange + * @param keys the key structure + * @param compat protocol compatibility indication + */ +static void +cert_cb (void *cls, + const struct TALER_EXCHANGE_HttpResponse *ehr, + const struct TALER_EXCHANGE_Keys *keys, + enum TALER_EXCHANGE_VersionCompatibility compat) +{ + struct TALER_MERCHANT_OrderPayHandle *oph = cls; + + if (TALER_EXCHANGE_VC_INCOMPATIBLE & compat) + { + struct TALER_MERCHANT_HttpResponse hr = { + .http_status = MHD_HTTP_CONFLICT, + .exchange_http_status = 0, + .ec = TALER_EC_WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE, + .reply = oph->full_reply, + .exchange_reply = ehr->reply, + .hint = "could not check error: incompatible exchange version" + }; + + oph->pay_cb (oph->pay_cb_cls, + &hr, + NULL); + TALER_MERCHANT_order_pay_cancel (oph); + return; + } + if ( (MHD_HTTP_OK != ehr->http_status) || + (NULL == keys) ) + { + struct TALER_MERCHANT_HttpResponse hr = { + .http_status = MHD_HTTP_CONFLICT, + .exchange_http_status = ehr->http_status, + .ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, + .reply = oph->full_reply, + .exchange_reply = ehr->reply, + .hint = "failed to download /keys from the exchange" + }; + + oph->pay_cb (oph->pay_cb_cls, + &hr, + NULL); + TALER_MERCHANT_order_pay_cancel (oph); + return; + } + + if (GNUNET_OK != + check_conflict (oph, + keys)) + { + struct TALER_MERCHANT_HttpResponse hr = { + .http_status = 0, + .ec = TALER_EC_GENERIC_INVALID_RESPONSE, + .reply = oph->full_reply + }; + + oph->pay_cb (oph->pay_cb_cls, + &hr, + NULL); + TALER_MERCHANT_order_pay_cancel (oph); + return; + } + + { + struct TALER_MERCHANT_HttpResponse hr = { + .http_status = MHD_HTTP_CONFLICT, + .ec = TALER_JSON_get_error_code (oph->full_reply), + .reply = oph->full_reply + }; + + oph->pay_cb (oph->pay_cb_cls, + &hr, + NULL); + TALER_MERCHANT_order_pay_cancel (oph); + } +} + + +/** * We got a 409 response back from the exchange (or the merchant). * Now we need to check the provided cryptograophic proof that the * coin was actually already spent! @@ -180,22 +277,26 @@ check_coin_history (const struct TALER_MERCHANT_PaidCoin *pc, * @param oph handle of the original pay operation * @param json cryptograophic proof returned by the * exchange/merchant - * @return #GNUNET_OK if proof checks out + * @return #GNUNET_OK if proof checks out, + * #GNUNET_SYSERR if it is wrong, + * #GNUNET_NO if checking continues asynchronously */ static enum GNUNET_GenericReturnValue -check_conflict (struct TALER_MERCHANT_OrderPayHandle *oph, +parse_conflict (struct TALER_MERCHANT_OrderPayHandle *oph, const json_t *json) { - json_t *history; json_t *ereply; struct TALER_CoinSpendPublicKeyP coin_pub; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("exchange_reply", &ereply), - GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin_pub), + GNUNET_JSON_spec_json ("exchange_reply", + &ereply), + GNUNET_JSON_spec_fixed_auto ("coin_pub", + &coin_pub), GNUNET_JSON_spec_end () }; struct GNUNET_JSON_Specification hspec[] = { - GNUNET_JSON_spec_json ("history", &history), + GNUNET_JSON_spec_json ("history", + &oph->error_history), GNUNET_JSON_spec_end () }; @@ -224,12 +325,14 @@ check_conflict (struct TALER_MERCHANT_OrderPayHandle *oph, GNUNET_memcmp (&oph->coins[i].coin_pub, &coin_pub)) { - enum GNUNET_GenericReturnValue ret; - - ret = check_coin_history (&oph->coins[i], - history); - GNUNET_JSON_parse_free (hspec); - return ret; + oph->error_pc = &oph->coins[i]; + oph->full_reply = json_incref ((json_t *) json); + oph->exchange = TALER_EXCHANGE_connect (oph->ctx, + oph->error_pc->exchange_url, + &cert_cb, + oph, + TALER_EXCHANGE_OPTION_END); + return GNUNET_NO; } } GNUNET_break_op (0); /* complaint is not about any of the coins @@ -338,15 +441,6 @@ handle_pay_finished (void *cls, happen, we should pass the JSON reply to the application */ break; - case MHD_HTTP_PRECONDITION_FAILED: - TALER_MERCHANT_parse_error_details_ (json, - response_code, - &hr); - /* Nothing really to verify, the merchant is blaming us for failing to - satisfy some constraint (likely it does not like our exchange because - of some disagreement on the PKI). We should pass the JSON reply to the - application */ - break; case MHD_HTTP_REQUEST_TIMEOUT: hr.ec = TALER_JSON_get_error_code (json); hr.hint = TALER_JSON_get_error_hint (json); @@ -355,15 +449,27 @@ handle_pay_finished (void *cls, Pass on to application. */ break; case MHD_HTTP_CONFLICT: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - if (GNUNET_OK != check_conflict (oph, - json)) { - GNUNET_break_op (0); - response_code = 0; + enum GNUNET_GenericReturnValue ret; + + hr.ec = TALER_JSON_get_error_code (json); + hr.hint = TALER_JSON_get_error_hint (json); + ret = parse_conflict (oph, + json); + switch (ret) + { + case GNUNET_OK: + break; + case GNUNET_NO: + /* handled asynchronously! */ + return; /* ! */ + case GNUNET_SYSERR: + GNUNET_break_op (0); + response_code = 0; + break; + } + break; } - break; case MHD_HTTP_GONE: hr.ec = TALER_JSON_get_error_code (json); hr.hint = TALER_JSON_get_error_hint (json); @@ -371,6 +477,15 @@ handle_pay_finished (void *cls, denomination key of a coin involved has expired. Might be a disagreement in timestamps? Still, pass on to application. */ break; + case MHD_HTTP_PRECONDITION_FAILED: + TALER_MERCHANT_parse_error_details_ (json, + response_code, + &hr); + /* Nothing really to verify, the merchant is blaming us for failing to + satisfy some constraint (likely it does not like our exchange because + of some disagreement on the PKI). We should pass the JSON reply to the + application */ + break; case MHD_HTTP_INTERNAL_SERVER_ERROR: hr.ec = TALER_JSON_get_error_code (json); hr.hint = TALER_JSON_get_error_hint (json); @@ -670,7 +785,14 @@ TALER_MERCHANT_order_pay_cancel (struct TALER_MERCHANT_OrderPayHandle *oph) GNUNET_CURL_job_cancel (oph->job); oph->job = NULL; } + if (NULL != oph->exchange) + { + TALER_EXCHANGE_disconnect (oph->exchange); + oph->exchange = NULL; + } TALER_curl_easy_post_finished (&oph->post_ctx); + json_decref (oph->error_history); + json_decref (oph->full_reply); GNUNET_free (oph->coins); GNUNET_free (oph->url); GNUNET_free (oph); diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c index c1bc0d56..490aa6e4 100644 --- a/src/testing/test_kyc_api.c +++ b/src/testing/test_kyc_api.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -17,7 +17,7 @@ <http://www.gnu.org/licenses/> */ /** - * @file test_merchant_api.c + * @file test_kyc_api.c * @brief testcase to test exchange's HTTP API interface * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff @@ -43,7 +43,7 @@ */ #define CONFIG_FILE "test_kyc_api.conf" -#define PAYTO_I1 "payto://x-taler-bank/localhost/3" +#define PAYTO_I1 "payto://x-taler-bank/localhost/3?receiver-name=3" /** * Exchange base URL. Could also be taken from config. @@ -272,7 +272,7 @@ run (void *cls, MHD_HTTP_NO_CONTENT, false), TALER_TESTING_cmd_wire_add ("add-wire-account", - "payto://x-taler-bank/localhost/2", + "payto://x-taler-bank/localhost/2?receiver-name=2", MHD_HTTP_NO_CONTENT, false), TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys", @@ -305,7 +305,7 @@ int main (int argc, char *const *argv) { - unsigned int ret; + enum GNUNET_GenericReturnValue ret; /* These environment variables get in the way... */ unsetenv ("XDG_DATA_HOME"); @@ -319,14 +319,19 @@ main (int argc, &bc)) return 77; - payer_payto = ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME); - exchange_payto = ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME); - merchant_payto = ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME); + payer_payto = + ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME "?receiver-name=" + USER_ACCOUNT_NAME); + exchange_payto = + ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME "?receiver-name=" + EXCHANGE_ACCOUNT_NAME); + merchant_payto = + ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME "?receiver-name=" + MERCHANT_ACCOUNT_NAME); if (NULL == (merchant_url = TALER_TESTING_prepare_merchant (CONFIG_FILE))) return 77; - GNUNET_asprintf (&merchant_url_i1a, "%sinstances/i1a/", merchant_url); @@ -341,23 +346,18 @@ main (int argc, return 1; case GNUNET_NO: return 77; - case GNUNET_OK: - if (NULL == (merchantd = TALER_TESTING_run_merchant (CONFIG_FILE, merchant_url))) return 1; - ret = TALER_TESTING_setup_with_exchange (&run, NULL, CONFIG_FILE); - GNUNET_OS_process_kill (merchantd, SIGTERM); GNUNET_OS_process_wait (merchantd); GNUNET_OS_process_destroy (merchantd); GNUNET_free (merchant_url); - if (GNUNET_OK != ret) return 1; break; diff --git a/src/testing/test_kyc_api.conf b/src/testing/test_kyc_api.conf index eea5538c..e28cd641 100644 --- a/src/testing/test_kyc_api.conf +++ b/src/testing/test_kyc_api.conf @@ -132,7 +132,7 @@ CONFIG = postgres:///talercheck # Account of the EXCHANGE [exchange-account-exchange] # What is the exchange's bank account (with the "Taler Bank" demo system)? -PAYTO_URI = "payto://x-taler-bank/localhost/2" +PAYTO_URI = "payto://x-taler-bank/localhost/2?receiver-name=2" ENABLE_DEBIT = YES ENABLE_CREDIT = YES diff --git a/src/testing/test_merchant_api-cs.conf b/src/testing/test_merchant_api-cs.conf index 006fb644..502d807a 100644 --- a/src/testing/test_merchant_api-cs.conf +++ b/src/testing/test_merchant_api-cs.conf @@ -114,7 +114,7 @@ CONFIG = postgres:///talercheck # Account of the EXCHANGE [exchange-account-exchange] # What is the exchange's bank account (with the "Taler Bank" demo system)? -PAYTO_URI = "payto://x-taler-bank/localhost/2" +PAYTO_URI = "payto://x-taler-bank/localhost/2?receiver-name=2" ENABLE_DEBIT = YES ENABLE_CREDIT = YES diff --git a/src/testing/test_merchant_api-rsa.conf b/src/testing/test_merchant_api-rsa.conf index b0f2b49e..5246fc40 100644 --- a/src/testing/test_merchant_api-rsa.conf +++ b/src/testing/test_merchant_api-rsa.conf @@ -114,7 +114,7 @@ CONFIG = postgres:///talercheck # Account of the EXCHANGE [exchange-account-exchange] # What is the exchange's bank account (with the "Taler Bank" demo system)? -PAYTO_URI = "payto://x-taler-bank/localhost/2" +PAYTO_URI = "payto://x-taler-bank/localhost/2?receiver-name=2" ENABLE_DEBIT = YES ENABLE_CREDIT = YES diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c index 8fc0f4ad..27129066 100644 --- a/src/testing/test_merchant_api.c +++ b/src/testing/test_merchant_api.c @@ -59,7 +59,7 @@ */ static char *config_file; -#define PAYTO_I1 "payto://x-taler-bank/localhost/3" +#define PAYTO_I1 "payto://x-taler-bank/localhost/3?receiver-name=3" /** * Exchange base URL. Could also be taken from config. @@ -1278,7 +1278,7 @@ run (void *cls, MHD_HTTP_NO_CONTENT, false), TALER_TESTING_cmd_wire_add ("add-wire-account", - "payto://x-taler-bank/localhost/2", + "payto://x-taler-bank/localhost/2?receiver-name=2", MHD_HTTP_NO_CONTENT, false), TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys", @@ -1458,7 +1458,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_post_instances ("instance-create-i2-non-idem", merchant_url, "i2", - "payto://other-method/", + "payto://other-method/?receiver-name=X", "EUR", MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_delete_instance ("instance-delete-i2", @@ -1640,12 +1640,11 @@ main (int argc, char *const *argv) { char *cipher; - unsigned int ret; + enum GNUNET_GenericReturnValue ret; /* These environment variables get in the way... */ unsetenv ("XDG_DATA_HOME"); unsetenv ("XDG_CONFIG_HOME"); - GNUNET_log_setup (argv[0], "DEBUG", NULL); @@ -1661,19 +1660,23 @@ main (int argc, &bc)) return 77; - payer_payto = ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME); - exchange_payto = ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME); - merchant_payto = ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME); + payer_payto = + ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME "?receiver-name=" + USER_ACCOUNT_NAME); + exchange_payto = + ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME "?receiver-name=" + EXCHANGE_ACCOUNT_NAME); + merchant_payto = + ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME "?receiver-name=" + MERCHANT_ACCOUNT_NAME); if (NULL == (merchant_url = TALER_TESTING_prepare_merchant (config_file))) return 77; - GNUNET_asprintf (&merchant_url_i1a, "%sinstances/i1a/", merchant_url); TALER_TESTING_cleanup_files (config_file); - switch (TALER_TESTING_prepare_exchange (config_file, GNUNET_YES, &ec)) @@ -1697,7 +1700,6 @@ main (int argc, GNUNET_OS_process_wait (merchantd); GNUNET_OS_process_destroy (merchantd); GNUNET_free (merchant_url); - if (GNUNET_OK != ret) return 1; break; diff --git a/src/testing/test_template.conf b/src/testing/test_template.conf index 20fee4b8..e9b94761 100644 --- a/src/testing/test_template.conf +++ b/src/testing/test_template.conf @@ -63,7 +63,7 @@ MAX_DEBT = TESTKUDOS:50.0 MAX_DEBT_BANK = TESTKUDOS:100000.0 HTTP_PORT = 8082 SUGGESTED_EXCHANGE = http://localhost:8081/ -SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/localhost/2 +SUGGESTED_EXCHANGE_PAYTO = "payto://x-taler-bank/localhost/2?receiver-name=2" ALLOW_REGISTRATIONS = YES SERVE = http @@ -72,7 +72,7 @@ IDLE_RESERVE_EXPIRATION_TIME = 4 weeks LEGAL_RESERVE_EXPIRATION_TIME = 7 years [exchange-account-1] -PAYTO_URI = payto://x-taler-bank/localhost/Exchange +PAYTO_URI = "payto://x-taler-bank/localhost/Exchange?receiver-name=Exchange" enable_debit = yes enable_credit = yes |