diff --git a/src/auditor/test-auditor.sh b/src/auditor/test-auditor.sh index 44b3c7b59..45498d69a 100755 --- a/src/auditor/test-auditor.sh +++ b/src/auditor/test-auditor.sh @@ -472,7 +472,7 @@ echo "===========4: deposit wire target wrong=================" # Original target bank account was 43, changing to 44 SERIAL=`echo "SELECT deposit_serial_id FROM deposits WHERE amount_with_fee_val=3 AND amount_with_fee_frac=0 ORDER BY deposit_serial_id LIMIT 1" | psql $DB -Aqt` OLD_WIRE=`echo "SELECT wire FROM deposits WHERE deposit_serial_id=${SERIAL};" | psql $DB -Aqt` -echo "UPDATE deposits SET wire='{\"payto_uri\":\"payto://x-taler-bank/localhost:8082/44\",\"salt\":\"test-salt\"}' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB +echo "UPDATE deposits SET wire='{\"payto_uri\":\"payto://x-taler-bank/localhost:8082/44\",\"salt\":\"9PE256FT5N3YX8H3F1QCHXVNGWAGG3MHDN4J360TSVWTA6WSSMNB8MY4GN5HQAP89TDZH8ANKEG1FB1FJZMN7ZC6NH6QRB0CDDR4TJ8\"}' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB run_audit @@ -1500,7 +1500,7 @@ echo "===========26: deposit wire target malformed =================" # Expects 'payto_uri', not 'url' (also breaks signature, but we cannot even check that). SERIAL=`echo "SELECT deposit_serial_id FROM deposits WHERE amount_with_fee_val=3 AND amount_with_fee_frac=0 ORDER BY deposit_serial_id LIMIT 1" | psql $DB -Aqt` OLD_WIRE=`echo "SELECT wire FROM deposits WHERE deposit_serial_id=${SERIAL};" | psql $DB -Aqt` -echo "UPDATE deposits SET wire='{\"url\":\"payto://x-taler-bank/localhost:8082/44\",\"salt\":\"test-salt\"}' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB +echo "UPDATE deposits SET wire='{\"url\":\"payto://x-taler-bank/localhost:8082/44\",\"salt\":\"9PE256FT5N3YX8H3F1QCHXVNGWAGG3MHDN4J360TSVWTA6WSSMNB8MY4GN5HQAP89TDZH8ANKEG1FB1FJZMN7ZC6NH6QRB0CDDR4TJ8\"}' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB run_audit diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index b332cd6d2..655d2f53e 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -1303,12 +1303,16 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit) putting in the WTID into the wire_out table */ { json_t *wire_out_account; + struct TALER_WireSalt salt; + memset (&salt, + 44, + sizeof (salt)); wire_out_account = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("payto_uri", "payto://x-taler-bank/localhost:8080/1"), - GNUNET_JSON_pack_string ("salt", - "this-is-my-salt")); + GNUNET_JSON_pack_data_auto ("salt", + &salt)); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->store_wire_transfer_out (plugin->cls, wire_out_date, @@ -1513,15 +1517,19 @@ run (void *cls) uint64_t rr; enum GNUNET_DB_QueryStatus qs; struct GNUNET_TIME_Absolute now; + struct TALER_WireSalt salt; dkp = NULL; rh = NULL; deposit.coin.denom_sig.rsa_signature = NULL; + memset (&salt, + 45, + sizeof (salt)); wire = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("payto_uri", "payto://iban/DE67830654080004822650?receiver-name=Test"), - GNUNET_JSON_pack_string ("salt", - "this-is-a-salt-value")); + GNUNET_JSON_pack_data_auto ("salt", + &salt)); ZR_BLK (&cbc); ZR_BLK (&cbc2); if (NULL == diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index d5cc00eaf..d861dbe85 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -793,23 +793,78 @@ TALER_EXCHANGE_deposit_permission_sign ( struct TALER_EXCHANGE_DepositHandle; +/** + * Structure with information about a deposit + * operation's result. + */ +struct TALER_EXCHANGE_DepositResult +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + union + { + + /** + * Information returned if the HTTP status is + * #MHD_HTTP_OK. + */ + struct + { + /** + * Time when the exchange generated the deposit confirmation + */ + struct GNUNET_TIME_Absolute deposit_timestamp; + + /** + * signature provided by the exchange + */ + const struct TALER_ExchangeSignatureP *exchange_sig; + + /** + * exchange key used to sign @a exchange_sig. + */ + const struct TALER_ExchangePublicKeyP *exchange_pub; + + /** + * Base URL for looking up wire transfers, or + * NULL to use the default base URL. + */ + const char *transaction_base_url; + + /** + * Payment target that the merchant should use + * to check for its KYC status. + */ + uint64_t payment_target_uuid; + } success; + + /** + * Information returned if the HTTP status is + * #MHD_HTTP_CONFLICT. + */ + struct + { + /* TODO: returning full details is not implemented */ + } conflict; + + } details; +}; + + /** * Callbacks of this type are used to serve the result of submitting a * deposit permission request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param deposit_timestamp time when the exchange generated the deposit confirmation - * @param exchange_sig signature provided by the exchange - * @param exchange_pub exchange key used to sign @a obj, or NULL + * @param dr deposit response details */ typedef void (*TALER_EXCHANGE_DepositResultCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - struct GNUNET_TIME_Absolute deposit_timestamp, - const struct TALER_ExchangeSignatureP *exchange_sig, - const struct TALER_ExchangePublicKeyP *exchange_pub); + const struct TALER_EXCHANGE_DepositResult *dr); /** @@ -1200,19 +1255,75 @@ TALER_EXCHANGE_reserves_get_cancel ( struct TALER_EXCHANGE_WithdrawHandle; +/** + * Details about a response for a withdraw request. + */ +struct TALER_EXCHANGE_WithdrawResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response. + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Signature over the coin. + */ + struct TALER_DenominationSignature sig; + } success; + + /** + * Details if the status is #MHD_HTTP_ACCEPTED. + */ + struct + { + /** + * Payment target that the merchant should use + * to check for its KYC status. + */ + uint64_t payment_target_uuid; + } accepted; + + /** + * Details if the status is #MHD_HTTP_CONFLICT. + */ + struct + { + /* TODO: returning full details is not implemented */ + } conflict; + + /** + * Details if the status is #MHD_HTTP_GONE. + */ + struct + { + /* TODO: returning full details is not implemented */ + } gone; + + } details; +}; + + /** * Callbacks of this type are used to serve the result of submitting a * withdraw request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param sig signature over the coin, NULL on error + * @param wr response details */ typedef void (*TALER_EXCHANGE_WithdrawCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_DenominationSignature *sig); + const struct TALER_EXCHANGE_WithdrawResponse *wr); /** @@ -1684,41 +1795,82 @@ struct TALER_EXCHANGE_DepositGetHandle; /** - * Data returned for a successful GET /deposits/ request. Note that - * most fields are only set if the status is #MHD_HTTP_OK. Only - * the @e execution_time is available if the status is #MHD_HTTP_ACCEPTED. + * Data returned for a successful GET /deposits/ request. */ -struct TALER_EXCHANGE_DepositData +struct TALER_EXCHANGE_GetDepositResponse { /** - * exchange key used to sign, all zeros if exchange did not - * yet execute the transaction + * HTTP response data. */ - struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_EXCHANGE_HttpResponse hr; /** - * signature from the exchange over the deposit data, all zeros if exchange did not - * yet execute the transaction + * Details about the response. */ - struct TALER_ExchangeSignatureP exchange_sig; + union + { - /** - * wire transfer identifier used by the exchange, all zeros if exchange did not - * yet execute the transaction - */ - struct TALER_WireTransferIdentifierRawP wtid; + /** + * Response if the status was #MHD_HTTP_OK + */ + struct TALER_EXCHANGE_DepositData + { + /** + * exchange key used to sign, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_ExchangePublicKeyP exchange_pub; - /** - * actual or planned execution time for the wire transfer - */ - struct GNUNET_TIME_Absolute execution_time; + /** + * signature from the exchange over the deposit data, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_ExchangeSignatureP exchange_sig; - /** - * contribution to the total amount by this coin, all zeros if exchange did not - * yet execute the transaction - */ - struct TALER_Amount coin_contribution; + /** + * wire transfer identifier used by the exchange, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * actual execution time for the wire transfer + */ + struct GNUNET_TIME_Absolute execution_time; + + /** + * contribution to the total amount by this coin, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_Amount coin_contribution; + + /** + * Payment target that the merchant should use + * to check for its KYC status. + */ + uint64_t payment_target_uuid; + } success; + + /** + * Response if the status was #MHD_HTTP_ACCEPTED + */ + struct + { + + /** + * planned execution time for the wire transfer + */ + struct GNUNET_TIME_Absolute execution_time; + + /** + * Payment target that the merchant should use + * to check for its KYC status. + */ + uint64_t payment_target_uuid; + } accepted; + + } details; }; @@ -1732,8 +1884,7 @@ struct TALER_EXCHANGE_DepositData typedef void (*TALER_EXCHANGE_DepositGetCallback)( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_EXCHANGE_DepositData *dd); + const struct TALER_EXCHANGE_GetDepositResponse *dr); /** diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c index b945f6b76..7f7095f40 100644 --- a/src/lib/exchange_api_deposit.c +++ b/src/lib/exchange_api_deposit.c @@ -324,19 +324,17 @@ handle_deposit_finished (void *cls, struct TALER_EXCHANGE_DepositHandle *dh = cls; struct TALER_ExchangeSignatureP exchange_sig; struct TALER_ExchangePublicKeyP exchange_pub; - struct TALER_ExchangeSignatureP *es = NULL; - struct TALER_ExchangePublicKeyP *ep = NULL; const json_t *j = response; - struct TALER_EXCHANGE_HttpResponse hr = { - .reply = j, - .http_status = (unsigned int) response_code + struct TALER_EXCHANGE_DepositResult dr = { + .hr.reply = j, + .hr.http_status = (unsigned int) response_code }; dh->job = NULL; switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: if (GNUNET_OK != @@ -346,31 +344,35 @@ handle_deposit_finished (void *cls, &exchange_pub)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; } else { - es = &exchange_sig; - ep = &exchange_pub; + dr.details.success.exchange_sig = &exchange_sig; + dr.details.success.exchange_pub = &exchange_pub; + dr.details.success.deposit_timestamp + = GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp); + dr.details.success.transaction_base_url; // FIXME + dr.details.success.payment_target_uuid; // FIXME } break; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_FORBIDDEN: - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); /* Nothing really to verify, this should never happen, we should pass the JSON reply to the application */ break; @@ -381,13 +383,13 @@ handle_deposit_finished (void *cls, j)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; } else { - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); } break; case MHD_HTTP_GONE: @@ -395,31 +397,28 @@ handle_deposit_finished (void *cls, /* Note: one might want to check /keys for revocation signature here, alas tricky in case our /keys is outdated => left to clients */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_INTERNAL_SERVER_ERROR: - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); /* Server had an internal issue; we should retry, but this API leaves this to the application */ break; default: /* unexpected response code */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d for exchange deposit\n", (unsigned int) response_code, - hr.ec); + dr.hr.ec); GNUNET_break_op (0); break; } dh->cb (dh->cb_cls, - &hr, - GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp), - es, - ep); + &dr); TALER_EXCHANGE_deposit_cancel (dh); } diff --git a/src/lib/exchange_api_deposits_get.c b/src/lib/exchange_api_deposits_get.c index efe9070f1..6c2aa1cb1 100644 --- a/src/lib/exchange_api_deposits_get.c +++ b/src/lib/exchange_api_deposits_get.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2021 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 published by the Free Software @@ -88,7 +88,7 @@ struct TALER_EXCHANGE_DepositGetHandle * @param exchange_sig the exchange's signature * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not */ -static int +static enum GNUNET_GenericReturnValue verify_deposit_wtid_signature_ok ( const struct TALER_EXCHANGE_DepositGetHandle *dwh, const json_t *json, @@ -133,26 +133,30 @@ handle_deposit_wtid_finished (void *cls, { struct TALER_EXCHANGE_DepositGetHandle *dwh = cls; const json_t *j = response; - struct TALER_EXCHANGE_HttpResponse hr = { - .reply = j, - .http_status = (unsigned int) response_code + struct TALER_EXCHANGE_GetDepositResponse dr = { + .hr.reply = j, + .hr.http_status = (unsigned int) response_code }; dwh->job = NULL; switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: { - struct TALER_EXCHANGE_DepositData dd; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("wtid", &dwh->depconf.wtid), - TALER_JSON_spec_absolute_time ("execution_time", &dd.execution_time), - TALER_JSON_spec_amount_any ("coin_contribution", &dd.coin_contribution), - GNUNET_JSON_spec_fixed_auto ("exchange_sig", &dd.exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", &dd.exchange_pub), + GNUNET_JSON_spec_fixed_auto ("wtid", + &dr.details.success.wtid), + TALER_JSON_spec_absolute_time ("execution_time", + &dr.details.success.execution_time), + TALER_JSON_spec_amount_any ("coin_contribution", + &dr.details.success.coin_contribution), + GNUNET_JSON_spec_fixed_auto ("exchange_sig", + &dr.details.success.exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", + &dr.details.success.exchange_pub), GNUNET_JSON_spec_end () }; @@ -162,41 +166,37 @@ handle_deposit_wtid_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } dwh->depconf.execution_time = GNUNET_TIME_absolute_hton ( - dd.execution_time); + dr.details.success.execution_time); + dwh->depconf.wtid = dr.details.success.wtid; TALER_amount_hton (&dwh->depconf.coin_contribution, - &dd.coin_contribution); + &dr.details.success.coin_contribution); if (GNUNET_OK != verify_deposit_wtid_signature_ok (dwh, j, - &dd.exchange_pub, - &dd.exchange_sig)) + &dr.details.success.exchange_pub, + &dr.details.success.exchange_sig)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE; - } - else - { - dd.wtid = dwh->depconf.wtid; - dwh->cb (dwh->cb_cls, - &hr, - &dd); - TALER_EXCHANGE_deposits_get_cancel (dwh); - return; + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE; + break; } + dwh->cb (dwh->cb_cls, + &dr); + TALER_EXCHANGE_deposits_get_cancel (dwh); + return; } - break; case MHD_HTTP_ACCEPTED: { /* Transaction known, but not executed yet */ - struct GNUNET_TIME_Absolute execution_time; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_absolute_time ("execution_time", &execution_time), + TALER_JSON_spec_absolute_time ("execution_time", + &dr.details.accepted.execution_time), GNUNET_JSON_spec_end () }; @@ -206,63 +206,54 @@ handle_deposit_wtid_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - else - { - struct TALER_EXCHANGE_DepositData dd = { - .execution_time = execution_time - }; - - dwh->cb (dwh->cb_cls, - &hr, - &dd); - TALER_EXCHANGE_deposits_get_cancel (dwh); - return; - } + dr.details.accepted.payment_target_uuid; // FIXME + dwh->cb (dwh->cb_cls, + &dr); + TALER_EXCHANGE_deposits_get_cancel (dwh); + return; } - break; case MHD_HTTP_BAD_REQUEST: - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; case MHD_HTTP_FORBIDDEN: - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); /* Exchange does not know about transaction; we should pass the reply to the application */ break; case MHD_HTTP_INTERNAL_SERVER_ERROR: - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); /* Server had an internal issue; we should retry, but this API leaves this to the application */ break; default: /* unexpected response code */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + dr.hr.ec = TALER_JSON_get_error_code (j); + dr.hr.hint = TALER_JSON_get_error_hint (j); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d for exchange GET deposits\n", (unsigned int) response_code, - (int) hr.ec); + (int) dr.hr.ec); GNUNET_break_op (0); break; } dwh->cb (dwh->cb_cls, - &hr, - NULL); + &dr); TALER_EXCHANGE_deposits_get_cancel (dwh); } diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c index b96adacd4..aa1468247 100644 --- a/src/lib/exchange_api_withdraw.c +++ b/src/lib/exchange_api_withdraw.c @@ -91,44 +91,41 @@ handle_reserve_withdraw_finished ( const struct GNUNET_CRYPTO_RsaSignature *blind_sig) { struct TALER_EXCHANGE_WithdrawHandle *wh = cls; + struct TALER_EXCHANGE_WithdrawResponse wr = { + .hr = *hr + }; wh->wh2 = NULL; - if (MHD_HTTP_OK != hr->http_status) + switch (hr->http_status) { - wh->cb (wh->cb_cls, - hr, - NULL); - } - else - { - struct TALER_FreshCoin fc; - - if (GNUNET_OK != - TALER_planchet_to_coin (&wh->pk.key, - blind_sig, - &wh->ps, - &wh->c_hash, - &fc)) + case MHD_HTTP_OK: { - struct TALER_EXCHANGE_HttpResponse hrx = { - .reply = hr->reply, - .http_status = 0, - .ec = TALER_EC_EXCHANGE_WITHDRAW_UNBLIND_FAILURE - }; + struct TALER_FreshCoin fc; - wh->cb (wh->cb_cls, - &hrx, - NULL); + if (GNUNET_OK != + TALER_planchet_to_coin (&wh->pk.key, + blind_sig, + &wh->ps, + &wh->c_hash, + &fc)) + { + wr.hr.http_status = 0; + wr.hr.ec = TALER_EC_EXCHANGE_WITHDRAW_UNBLIND_FAILURE; + break; + } + wr.details.success.sig = fc.sig; + break; } - else - { - wh->cb (wh->cb_cls, - hr, - &fc.sig); - GNUNET_CRYPTO_rsa_signature_free (fc.sig.rsa_signature); - } - + case MHD_HTTP_ACCEPTED: + wr.details.accepted.payment_target_uuid; // FIXME + break; + default: + break; } + wh->cb (wh->cb_cls, + &wr); + if (MHD_HTTP_OK == hr->http_status) + GNUNET_CRYPTO_rsa_signature_free (wr.details.success.sig.rsa_signature); TALER_EXCHANGE_withdraw_cancel (wh); } diff --git a/src/testing/testing_api_cmd_deposit.c b/src/testing/testing_api_cmd_deposit.c index a392884a0..58322b1d1 100644 --- a/src/testing/testing_api_cmd_deposit.c +++ b/src/testing/testing_api_cmd_deposit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2018-2020 Taler Systems SA + Copyright (C) 2018-2021 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 published by @@ -207,38 +207,30 @@ do_retry (void *cls) * check if the response code is acceptable. * * @param cls closure. - * @param hr HTTP response details - * @param exchange_timestamp when did the exchange receive the deposit permission - * @param exchange_sig signature provided by the exchange - * (NULL on errors) - * @param exchange_pub public key of the exchange, - * used for signing the response. + * @param dr deposit response details */ static void deposit_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct GNUNET_TIME_Absolute exchange_timestamp, - const struct TALER_ExchangeSignatureP *exchange_sig, - const struct TALER_ExchangePublicKeyP *exchange_pub) + const struct TALER_EXCHANGE_DepositResult *dr) { struct DepositState *ds = cls; ds->dh = NULL; - if (ds->expected_response_code != hr->http_status) + if (ds->expected_response_code != dr->hr.http_status) { if (0 != ds->do_retry) { ds->do_retry--; - if ( (0 == hr->http_status) || - (TALER_EC_GENERIC_DB_SOFT_FAILURE == hr->ec) || - (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) ) + if ( (0 == dr->hr.http_status) || + (TALER_EC_GENERIC_DB_SOFT_FAILURE == dr->hr.ec) || + (MHD_HTTP_INTERNAL_SERVER_ERROR == dr->hr.http_status) ) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retrying deposit failed with %u/%d\n", - hr->http_status, - (int) hr->ec); + dr->hr.http_status, + (int) dr->hr.ec); /* on DB conflicts, do not use backoff */ - if (TALER_EC_GENERIC_DB_SOFT_FAILURE == hr->ec) + if (TALER_EC_GENERIC_DB_SOFT_FAILURE == dr->hr.ec) ds->backoff = GNUNET_TIME_UNIT_ZERO; else ds->backoff = GNUNET_TIME_randomized_backoff (ds->backoff, @@ -253,22 +245,22 @@ deposit_cb (void *cls, } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u to command %s in %s:%u\n", - hr->http_status, + dr->hr.http_status, ds->is->commands[ds->is->ip].label, __FILE__, __LINE__); - json_dumpf (hr->reply, + json_dumpf (dr->hr.reply, stderr, 0); TALER_TESTING_interpreter_fail (ds->is); return; } - if (MHD_HTTP_OK == hr->http_status) + if (MHD_HTTP_OK == dr->hr.http_status) { ds->deposit_succeeded = GNUNET_YES; - ds->exchange_timestamp = exchange_timestamp; - ds->exchange_pub = *exchange_pub; - ds->exchange_sig = *exchange_sig; + ds->exchange_timestamp = dr->details.success.deposit_timestamp; + ds->exchange_pub = *dr->details.success.exchange_pub; + ds->exchange_sig = *dr->details.success.exchange_sig; } TALER_TESTING_interpreter_next (ds->is); } diff --git a/src/testing/testing_api_cmd_deposits_get.c b/src/testing/testing_api_cmd_deposits_get.c index f2f3f0e39..61358291b 100644 --- a/src/testing/testing_api_cmd_deposits_get.c +++ b/src/testing/testing_api_cmd_deposits_get.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2021 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 @@ -80,38 +80,36 @@ struct TrackTransactionState * line matches our expectations. * * @param cls closure. - * @param hr HTTP response details - * @param dd data about the wire transfer associated with the deposit + * @param dr GET deposit response details */ static void deposit_wtid_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_EXCHANGE_DepositData *dd) + const struct TALER_EXCHANGE_GetDepositResponse *dr) { struct TrackTransactionState *tts = cls; struct TALER_TESTING_Interpreter *is = tts->is; struct TALER_TESTING_Command *cmd = &is->commands[is->ip]; tts->tth = NULL; - if (tts->expected_response_code != hr->http_status) + if (tts->expected_response_code != dr->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d to command %s in %s:%u\n", - hr->http_status, - (int) hr->ec, + dr->hr.http_status, + (int) dr->hr.ec, cmd->label, __FILE__, __LINE__); - json_dumpf (hr->reply, + json_dumpf (dr->hr.reply, stderr, 0); TALER_TESTING_interpreter_fail (is); return; } - switch (hr->http_status) + switch (dr->hr.http_status) { case MHD_HTTP_OK: - tts->wtid = dd->wtid; + tts->wtid = dr->details.success.wtid; if (NULL != tts->bank_transfer_reference) { const struct TALER_TESTING_Command *bank_transfer_cmd; @@ -139,7 +137,7 @@ deposit_wtid_cb (void *cls, } /* Compare that expected and gotten subjects match. */ - if (0 != GNUNET_memcmp (&dd->wtid, + if (0 != GNUNET_memcmp (&dr->details.success.wtid, wtid_want)) { GNUNET_break (0); @@ -147,8 +145,6 @@ deposit_wtid_cb (void *cls, return; } } - - break; case MHD_HTTP_ACCEPTED: /* allowed, nothing to check here */ diff --git a/src/testing/testing_api_cmd_insert_deposit.c b/src/testing/testing_api_cmd_insert_deposit.c index 0d57ab6c4..0a0d5db2f 100644 --- a/src/testing/testing_api_cmd_insert_deposit.c +++ b/src/testing/testing_api_cmd_insert_deposit.c @@ -200,14 +200,18 @@ insert_deposit_run (void *cls, &hc); { char *str; + struct TALER_WireSalt salt; GNUNET_asprintf (&str, "payto://x-taler-bank/localhost/%s", ids->merchant_account); + memset (&salt, + 46, + sizeof (salt)); deposit.receiver_wire_account = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("salt", - "this-is-a-salt-value"), + GNUNET_JSON_pack_data_auto ("salt", + &salt), GNUNET_JSON_pack_string ("payto_uri", str)); GNUNET_free (str); diff --git a/src/testing/testing_api_cmd_withdraw.c b/src/testing/testing_api_cmd_withdraw.c index cfbdc177d..23beb6065 100644 --- a/src/testing/testing_api_cmd_withdraw.c +++ b/src/testing/testing_api_cmd_withdraw.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2018-2020 Taler Systems SA + Copyright (C) 2018-2021 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 published by @@ -178,38 +178,36 @@ do_retry (void *cls) * in the state. * * @param cls closure. - * @param hr HTTP response details - * @param sig signature over the coin, NULL on error. + * @param wr withdraw response details */ static void reserve_withdraw_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_DenominationSignature *sig) + const struct TALER_EXCHANGE_WithdrawResponse *wr) { struct WithdrawState *ws = cls; struct TALER_TESTING_Interpreter *is = ws->is; ws->wsh = NULL; - if (ws->expected_response_code != hr->http_status) + if (ws->expected_response_code != wr->hr.http_status) { if (0 != ws->do_retry) { - if (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN != hr->ec) + if (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN != wr->hr.ec) ws->do_retry--; /* we don't count reserve unknown as failures here */ - if ( (0 == hr->http_status) || - (TALER_EC_GENERIC_DB_SOFT_FAILURE == hr->ec) || - (TALER_EC_EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS == hr->ec) || - (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN == hr->ec) || - (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) ) + if ( (0 == wr->hr.http_status) || + (TALER_EC_GENERIC_DB_SOFT_FAILURE == wr->hr.ec) || + (TALER_EC_EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS == wr->hr.ec) || + (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN == wr->hr.ec) || + (MHD_HTTP_INTERNAL_SERVER_ERROR == wr->hr.http_status) ) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retrying withdraw failed with %u/%d\n", - hr->http_status, - (int) hr->ec); + wr->hr.http_status, + (int) wr->hr.ec); /* on DB conflicts, do not use backoff */ - if (TALER_EC_GENERIC_DB_SOFT_FAILURE == hr->ec) + if (TALER_EC_GENERIC_DB_SOFT_FAILURE == wr->hr.ec) ws->backoff = GNUNET_TIME_UNIT_ZERO; - else if (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN != hr->ec) + else if (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN != wr->hr.ec) ws->backoff = EXCHANGE_LIB_BACKOFF (ws->backoff); else ws->backoff = GNUNET_TIME_relative_max (UNKNOWN_MIN_BACKOFF, @@ -227,29 +225,23 @@ reserve_withdraw_cb (void *cls, } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d to command %s in %s:%u\n", - hr->http_status, - (int) hr->ec, + wr->hr.http_status, + (int) wr->hr.ec, TALER_TESTING_interpreter_get_current_label (is), __FILE__, __LINE__); - json_dumpf (hr->reply, + json_dumpf (wr->hr.reply, stderr, 0); GNUNET_break (0); TALER_TESTING_interpreter_fail (is); return; } - switch (hr->http_status) + switch (wr->hr.http_status) { case MHD_HTTP_OK: - if (NULL == sig) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; - } ws->sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup ( - sig->rsa_signature); + wr->details.success.sig.rsa_signature); if (0 != ws->total_backoff.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -259,23 +251,27 @@ reserve_withdraw_cb (void *cls, GNUNET_YES)); } break; + case MHD_HTTP_ACCEPTED: + /* nothing to check */ + /* TODO: trait for returned uuid! */ + break; case MHD_HTTP_FORBIDDEN: /* nothing to check */ break; + case MHD_HTTP_NOT_FOUND: + /* nothing to check */ + break; case MHD_HTTP_CONFLICT: /* nothing to check */ break; case MHD_HTTP_GONE: /* theoretically could check that the key was actually */ break; - case MHD_HTTP_NOT_FOUND: - /* nothing to check */ - break; default: /* Unsupported status code (by test harness) */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Withdraw test command does not support status code %u\n", - hr->http_status); + wr->hr.http_status); GNUNET_break (0); break; } diff --git a/src/testing/testing_api_helpers_bank.c b/src/testing/testing_api_helpers_bank.c index d7cce01bb..2876c2470 100644 --- a/src/testing/testing_api_helpers_bank.c +++ b/src/testing/testing_api_helpers_bank.c @@ -670,11 +670,17 @@ TALER_TESTING_prepare_fakebank (const char *config_filename, json_t * TALER_TESTING_make_wire_details (const char *payto) { + struct TALER_WireSalt salt; + + /* salt must be constant for aggregation tests! */ + memset (&salt, + 47, + sizeof (salt)); return GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("payto_uri", payto), - GNUNET_JSON_pack_string ("salt", - "test-salt (must be constant for aggregation tests)")); + GNUNET_JSON_pack_data_auto ("salt", + &salt)); } diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c index af5b6d5e4..27e48b9e3 100644 --- a/src/util/test_crypto.c +++ b/src/util/test_crypto.c @@ -158,21 +158,24 @@ static int test_merchant_sigs () { const char *pt = "payto://x-taler-bank/localhost/Account"; - const char *salt = "my test salt"; + struct TALER_WireSalt salt; struct TALER_MerchantPrivateKeyP priv; struct TALER_MerchantPublicKeyP pub; struct TALER_MerchantSignatureP sig; GNUNET_CRYPTO_eddsa_key_create (&priv.eddsa_priv); + memset (&salt, + 42, + sizeof (salt)); TALER_merchant_wire_signature_make (pt, - salt, + &salt, &priv, &sig); GNUNET_CRYPTO_eddsa_key_get_public (&priv.eddsa_priv, &pub.eddsa_pub); if (GNUNET_OK != TALER_merchant_wire_signature_check (pt, - salt, + &salt, &pub, &sig)) { @@ -182,16 +185,19 @@ test_merchant_sigs () if (GNUNET_OK == TALER_merchant_wire_signature_check ( "payto://x-taler-bank/localhost/Other", - salt, + &salt, &pub, &sig)) { GNUNET_break (0); return 1; } + memset (&salt, + 43, + sizeof (salt)); if (GNUNET_OK == TALER_merchant_wire_signature_check (pt, - "other salt", + &salt, &pub, &sig)) {