From cce67665f702fe10df64c1bad6a1bf6cf19c06ab Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 1 May 2019 02:41:40 +0200 Subject: [PATCH 1/9] save and restore CFLAGS/LDFLAGS/LIBS when checking for gnurl/curl --- configure.ac | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 842f24a55..3c1d9dd3e 100644 --- a/configure.ac +++ b/configure.ac @@ -180,6 +180,10 @@ AS_IF([test $libgnunetjson != 1], *** ]])]) +# Save before checking libgnurl/libcurl +CFLAGS_SAVE=$CFLAGS +LDFLAGS_SAVE=$LDFLAGS +LIBS_SAVE=$LIBS # check for libgnurl # libgnurl @@ -240,6 +244,10 @@ AS_IF([test $libgnunetcurl != 1], *** ]])]) +# Restore after gnurl/curl checks messed up these values +CFLAGS=$CFLAGS_SAVE +LDFLAGS=$LDFLAGS_SAVE +LIBS=$LIBS_SAVE # Check for GNUnet's libgnunetpq. libgnunetpq=0 @@ -325,9 +333,9 @@ else CFLAGS_SAVE=$CFLAGS LDFLAGS_SAVE=$LDFLAGS +LIBS_SAVE=$LIBS CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS" LDFLAGS="$LDFLAGS $LIBGCRYPT_LDFLAGS" -LIBS_SAVE="$LIBS" LIBS="-lgcrypt -lgpg-error $LIBS" From 8e391e8bfb0cd37181de8d1a921855ec798eaaad Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 1 May 2019 04:00:29 +0200 Subject: [PATCH 2/9] Don't free null strings. When running in client-only mode, this string will never be allocated, but the code tried to free it ... --- src/benchmark/taler-exchange-benchmark.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c index 59fcc6599..feaa203a9 100644 --- a/src/benchmark/taler-exchange-benchmark.c +++ b/src/benchmark/taler-exchange-benchmark.c @@ -816,8 +816,8 @@ int main (int argc, char *const *argv) { - char *exchange_url; - char *auditor_url; + char *exchange_url = NULL; + char *auditor_url = NULL; struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_option_mandatory @@ -1031,8 +1031,8 @@ main (int argc, NULL, cfg_filename, exchange_url); - GNUNET_free (exchange_url); - GNUNET_free (auditor_url); + GNUNET_free_non_null (exchange_url); + GNUNET_free_non_null (auditor_url); duration = GNUNET_TIME_absolute_get_duration (start_time); if (GNUNET_OK == result) { From 88f9e693f685993af9d5c4309a6f1d93716754c0 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 1 May 2019 19:44:00 +0200 Subject: [PATCH 3/9] benchmar: wait for exchange worker to terminate --- src/benchmark/taler-exchange-benchmark.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c index feaa203a9..3f3854a52 100644 --- a/src/benchmark/taler-exchange-benchmark.c +++ b/src/benchmark/taler-exchange-benchmark.c @@ -760,6 +760,8 @@ parallel_benchmark (TALER_TESTING_Main main_cb, { GNUNET_assert (NULL != exchange_slave); GNUNET_OS_process_kill (exchange_slave, SIGTERM); + GNUNET_break (GNUNET_OK == + GNUNET_OS_process_wait (exchange_slave)); GNUNET_OS_process_destroy (exchange_slave); } From feec6e30e6a6732b3005305f80ecdc30b01f7e4e Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 1 May 2019 20:52:43 +0200 Subject: [PATCH 4/9] benchmark: terminate exchange slave properly --- src/benchmark/taler-exchange-benchmark.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c index 3f3854a52..eed8f80d8 100644 --- a/src/benchmark/taler-exchange-benchmark.c +++ b/src/benchmark/taler-exchange-benchmark.c @@ -566,6 +566,7 @@ parallel_benchmark (TALER_TESTING_Main main_cb, struct GNUNET_OS_Process *exchanged = NULL; struct GNUNET_OS_Process *wirewatch = NULL; struct GNUNET_OS_Process *exchange_slave = NULL; + struct GNUNET_DISK_PipeHandle *exchange_slave_pipe; if ( (MODE_CLIENT == mode) || (MODE_BOTH == mode) ) { @@ -650,9 +651,14 @@ parallel_benchmark (TALER_TESTING_Main main_cb, "remote command: %s\n", remote_cmd); + GNUNET_assert (NULL != (exchange_slave_pipe = + GNUNET_DISK_pipe (GNUNET_YES, + GNUNET_YES, + 0, 0))); + exchange_slave = GNUNET_OS_start_process (GNUNET_NO, - GNUNET_OS_INHERIT_STD_ALL, - NULL, NULL, NULL, + GNUNET_OS_INHERIT_STD_OUT_AND_ERR, + exchange_slave_pipe, NULL, NULL, "ssh", "ssh", /* Don't ask for pw/passphrase, rather fail */ @@ -758,8 +764,17 @@ parallel_benchmark (TALER_TESTING_Main main_cb, if (MODE_CLIENT == mode) { + char c = 'q'; + GNUNET_assert (NULL != exchange_slave); - GNUNET_OS_process_kill (exchange_slave, SIGTERM); + + /* Write a character to the pipe to end the exchange slave. + * We can't send a signal here, as it would just kill SSH and + * not necessarily the process on the other machine. */ + GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle + (exchange_slave_pipe, GNUNET_DISK_PIPE_END_WRITE), + &c, sizeof (c)); + GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (exchange_slave)); GNUNET_OS_process_destroy (exchange_slave); From d821ecc3bb23df1a326fcbdf4cb08841322db7aa Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 1 May 2019 23:13:18 +0200 Subject: [PATCH 5/9] Remove bogus ifdef for tcp fast open --- src/lib/auditor_api_curl_defaults.c | 2 -- src/lib/exchange_api_curl_defaults.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/lib/auditor_api_curl_defaults.c b/src/lib/auditor_api_curl_defaults.c index d5b924008..507ae0e55 100644 --- a/src/lib/auditor_api_curl_defaults.c +++ b/src/lib/auditor_api_curl_defaults.c @@ -44,12 +44,10 @@ TAL_curl_easy_get (const char *url) curl_easy_setopt (eh, CURLOPT_ENCODING, "deflate")); -#ifdef CURLOPT_TCP_FASTOPEN GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_TCP_FASTOPEN, 1L)); -#endif { /* Unfortunately libcurl needs chunk to be alive until after curl_easy_perform. To avoid manual cleanup, we keep diff --git a/src/lib/exchange_api_curl_defaults.c b/src/lib/exchange_api_curl_defaults.c index 3ac1dfdbe..57fae166d 100644 --- a/src/lib/exchange_api_curl_defaults.c +++ b/src/lib/exchange_api_curl_defaults.c @@ -49,11 +49,9 @@ TEL_curl_easy_get (const char *url) curl_easy_setopt (eh, CURLOPT_FOLLOWLOCATION, 1L)); -#ifdef CURLOPT_TCP_FASTOPEN GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_TCP_FASTOPEN, 1L)); -#endif return eh; } From de9fdf860af9bdeadee4ed21a2c03dc34d58dd86 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 2 May 2019 21:16:51 +0200 Subject: [PATCH 6/9] replace denom_pub with denom_pub_hash in exchange API to reduce bandwidth --- ChangeLog | 5 ++ src/auditor/taler-auditor.c | 57 ++++++++----- src/exchange/taler-exchange-httpd_deposit.c | 19 +++-- src/exchange/taler-exchange-httpd_keystate.c | 8 +- src/exchange/taler-exchange-httpd_keystate.h | 2 +- src/exchange/taler-exchange-httpd_payback.c | 21 +++-- .../taler-exchange-httpd_refresh_melt.c | 40 +++++---- .../taler-exchange-httpd_refresh_reveal.c | 1 - src/exchange/taler-exchange-httpd_refund.c | 6 +- .../taler-exchange-httpd_reserve_withdraw.c | 22 ++--- src/exchange/taler-exchange-httpd_responses.c | 5 +- src/exchange/test_taler_exchange_aggregator.c | 3 +- src/exchangedb/perf_taler_exchangedb_init.c | 28 ++----- .../perf_taler_exchangedb_interpreter.c | 5 +- src/exchangedb/plugin_exchangedb_common.c | 10 --- src/exchangedb/plugin_exchangedb_postgres.c | 82 ++++++++----------- src/exchangedb/test_exchangedb.c | 28 ++++--- src/include/taler_crypto_lib.h | 10 ++- src/include/taler_exchangedb_plugin.h | 9 +- src/lib/exchange_api_deposit.c | 13 ++- src/lib/exchange_api_handle.c | 2 +- src/lib/exchange_api_payback.c | 5 +- src/lib/exchange_api_refresh.c | 7 +- src/lib/exchange_api_reserve.c | 11 ++- src/util/crypto.c | 15 +++- 25 files changed, 219 insertions(+), 195 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5fce75ec5..c7bf8b7f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu 02 May 2019 09:15:37 PM CEST + Pass hash of denomination public key in operations from + clients to exchange instead of the (larger) full public key. + Breaks protocol compatibility, bumping protocol to v3. -CG + Mon Mar 11 03:24:07 CET 2019 Completed implementation of #5536 (delete private keys once we no longer need them). -CG diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c index 9d629d1e5..0cd84523e 100644 --- a/src/auditor/taler-auditor.c +++ b/src/auditor/taler-auditor.c @@ -562,25 +562,18 @@ static struct GNUNET_CONTAINER_MultiHashMap *denominations; /** * Obtain information about a @a denom_pub. * - * @param denom_pub key to look up + * @param dh hash of the denomination public key to look up * @param[out] dki set to detailed information about @a denom_pub, NULL if not found, must * NOT be freed by caller - * @param[out] dh set to the hash of @a denom_pub, may be NULL * @return transaction status code */ static enum GNUNET_DB_QueryStatus -get_denomination_info (const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyInformationP **dki, - struct GNUNET_HashCode *dh) +get_denomination_info_by_hash (const struct GNUNET_HashCode *dh, + const struct TALER_EXCHANGEDB_DenominationKeyInformationP **dki) { - struct GNUNET_HashCode hc; struct TALER_EXCHANGEDB_DenominationKeyInformationP *dkip; enum GNUNET_DB_QueryStatus qs; - if (NULL == dh) - dh = &hc; - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, - dh); if (NULL == denominations) denominations = GNUNET_CONTAINER_multihashmap_create (256, GNUNET_NO); @@ -594,9 +587,9 @@ get_denomination_info (const struct TALER_DenominationPublicKey *denom_pub, } dkip = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformationP); qs = edb->get_denomination_info (edb->cls, - esession, - denom_pub, - dkip); + esession, + dh, + dkip); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { GNUNET_free (dkip); @@ -623,6 +616,31 @@ get_denomination_info (const struct TALER_DenominationPublicKey *denom_pub, } +/** + * Obtain information about a @a denom_pub. + * + * @param denom_pub key to look up + * @param[out] dki set to detailed information about @a denom_pub, NULL if not found, must + * NOT be freed by caller + * @param[out] dh set to the hash of @a denom_pub, may be NULL + * @return transaction status code + */ +static enum GNUNET_DB_QueryStatus +get_denomination_info (const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyInformationP **dki, + struct GNUNET_HashCode *dh) +{ + struct GNUNET_HashCode hc; + + if (NULL == dh) + dh = &hc; + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, + dh); + return get_denomination_info_by_hash (dh, + dki); +} + + /** * Free denomination key information. * @@ -1065,6 +1083,7 @@ handle_payback_by_reserve (void *cls, const struct TALER_Amount *amount, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_CoinPublicInfo *coin, + const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind) { @@ -1081,11 +1100,12 @@ handle_payback_by_reserve (void *cls, /* should be monotonically increasing */ GNUNET_assert (rowid >= ppr.last_reserve_payback_serial_id); ppr.last_reserve_payback_serial_id = rowid + 1; - GNUNET_CRYPTO_rsa_public_key_hash (coin->denom_pub.rsa_public_key, - &pr.h_denom_pub); + // FIXME: should probably check that denom_pub hashes to this hash code! + pr.h_denom_pub = coin->denom_pub_hash; if (GNUNET_OK != - TALER_test_coin_valid (coin)) + TALER_test_coin_valid (coin, + denom_pub)) { report (report_bad_sig_losses, json_pack ("{s:s, s:I, s:o, s:o}", @@ -2263,9 +2283,8 @@ wire_transfer_information_cb (void *cls, break; } GNUNET_assert (NULL != coin); /* hard check that switch worked */ - qs = get_denomination_info (&coin->denom_pub, - &dki, - NULL); + qs = get_denomination_info_by_hash (&coin->denom_pub_hash, + &dki); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 530cff770..5a1bf4963 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -246,7 +246,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, struct TALER_Amount amount_without_fee; struct DepositContext dc; struct TEH_KS_StateHandle *mks; - struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; + const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; /* check signature */ dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); @@ -282,9 +282,9 @@ verify_and_execute_deposit (struct MHD_Connection *connection, TALER_EC_EXCHANGE_BAD_CONFIGURATION, "no keys"); } - dki = TEH_KS_denomination_key_lookup (mks, - &deposit->coin.denom_pub, - TEH_KS_DKU_DEPOSIT); + dki = TEH_KS_denomination_key_lookup_by_hash (mks, + &deposit->coin.denom_pub_hash, + TEH_KS_DKU_DEPOSIT); if (NULL == dki) { TEH_KS_release (mks); @@ -392,7 +392,7 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_json ("wire", &wire), TALER_JSON_spec_amount ("contribution", &deposit.amount_with_fee), - TALER_JSON_spec_denomination_public_key ("denom_pub", &deposit.coin.denom_pub), + GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", &deposit.coin.denom_pub_hash), TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig), GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub), GNUNET_JSON_spec_fixed_auto ("merchant_pub", &deposit.merchant_pub), @@ -487,9 +487,9 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, TALER_EC_EXCHANGE_BAD_CONFIGURATION, "no keys"); } - dki = TEH_KS_denomination_key_lookup (key_state, - &deposit.coin.denom_pub, - TEH_KS_DKU_DEPOSIT); + dki = TEH_KS_denomination_key_lookup_by_hash (key_state, + &deposit.coin.denom_pub_hash, + TEH_KS_DKU_DEPOSIT); if (NULL == dki) { /* FIXME: #3887: if DK was revoked, we might want to give a 403 and not a 404! */ @@ -504,7 +504,8 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, &dki->issue.properties.fee_deposit); /* check coin signature */ if (GNUNET_YES != - TALER_test_coin_valid (&deposit.coin)) + TALER_test_coin_valid (&deposit.coin, + &dki->denom_pub)) { TALER_LOG_WARNING ("Invalid coin passed for /deposit\n"); TEH_KS_release (key_state); diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index 901ab6fa6..a452a1246 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -39,7 +39,7 @@ * release version, and the format is NOT the same that semantic * versioning uses either. */ -#define TALER_PROTOCOL_VERSION "2:0:0" +#define TALER_PROTOCOL_VERSION "3:0:0" /** @@ -674,7 +674,7 @@ add_denomination_transaction (void *cls, qs = TEH_plugin->get_denomination_info (TEH_plugin->cls, session, - &dki->denom_pub, + &dki->issue.properties.denom_hash, &issue_exists); if (0 > qs) return qs; @@ -789,7 +789,7 @@ revocations_iter (void *cls, struct TEH_KS_StateHandle *key_state = rfc->key_state; struct AddRevocationContext arc; struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; - + dki = GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map, denom_hash); if (NULL == dki) @@ -1613,7 +1613,7 @@ make_fresh_key_state (struct GNUNET_TIME_Absolute now) json_decref (rfc.sign_keys_array); return NULL; } - + /* Initialize `current_sign_key_issue` and `rfc.sign_keys_array` */ TALER_EXCHANGEDB_signing_keys_iterate (TEH_exchange_directory, &reload_keys_sign_iter, diff --git a/src/exchange/taler-exchange-httpd_keystate.h b/src/exchange/taler-exchange-httpd_keystate.h index 62d693731..c9b982306 100644 --- a/src/exchange/taler-exchange-httpd_keystate.h +++ b/src/exchange/taler-exchange-httpd_keystate.h @@ -127,7 +127,7 @@ enum TEH_KS_DenominationKeyUse { struct TALER_EXCHANGEDB_DenominationKeyIssueInformation * TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state, const struct TALER_DenominationPublicKey *denom_pub, - enum TEH_KS_DenominationKeyUse use); + enum TEH_KS_DenominationKeyUse use); /** diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index 2164863ee..06181519f 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -326,9 +326,9 @@ verify_and_execute_payback (struct MHD_Connection *connection, TALER_EC_EXCHANGE_BAD_CONFIGURATION, "no keys"); } - dki = TEH_KS_denomination_key_lookup (key_state, - &coin->denom_pub, - TEH_KS_DKU_PAYBACK); + dki = TEH_KS_denomination_key_lookup_by_hash (key_state, + &coin->denom_pub_hash, + TEH_KS_DKU_PAYBACK); if (NULL == dki) { TEH_KS_release (key_state); @@ -342,7 +342,8 @@ verify_and_execute_payback (struct MHD_Connection *connection, /* check denomination signature */ if (GNUNET_YES != - TALER_test_coin_valid (coin)) + TALER_test_coin_valid (coin, + &dki->denom_pub)) { TALER_LOG_WARNING ("Invalid coin passed for /payback\n"); TEH_KS_release (key_state); @@ -358,8 +359,6 @@ verify_and_execute_payback (struct MHD_Connection *connection, pr.h_denom_pub = dki->issue.properties.denom_hash; pr.coin_blind = *coin_bks; - TEH_KS_release (key_state); - if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_PAYBACK, &pr.purpose, @@ -367,6 +366,7 @@ verify_and_execute_payback (struct MHD_Connection *connection, &coin->coin_pub.eddsa_pub)) { TALER_LOG_WARNING ("Invalid signature on /payback request\n"); + TEH_KS_release (key_state); return TEH_RESPONSE_reply_signature_invalid (connection, TALER_EC_PAYBACK_SIGNATURE_INVALID, "coin_sig"); @@ -378,15 +378,18 @@ verify_and_execute_payback (struct MHD_Connection *connection, if (GNUNET_YES != GNUNET_CRYPTO_rsa_blind (&c_hash, &coin_bks->bks, - coin->denom_pub.rsa_public_key, + dki->denom_pub.rsa_public_key, &coin_ev, &coin_ev_size)) { GNUNET_break (0); + TEH_KS_release (key_state); + return TEH_RESPONSE_reply_internal_error (connection, TALER_EC_PAYBACK_BLINDING_FAILED, "coin_bks"); } + TEH_KS_release (key_state); GNUNET_CRYPTO_hash (coin_ev, coin_ev_size, &pc.h_blind); @@ -454,8 +457,8 @@ TEH_PAYBACK_handler_payback (struct TEH_RequestHandler *rh, struct TALER_DenominationBlindingKeyP coin_bks; struct TALER_CoinSpendSignatureP coin_sig; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_denomination_public_key ("denom_pub", - &coin.denom_pub), + GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", + &coin.denom_pub_hash), TALER_JSON_spec_denomination_signature ("denom_sig", &coin.denom_sig), GNUNET_JSON_spec_fixed_auto ("coin_pub", diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index 8e776c77b..1b8e04a07 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -412,8 +412,8 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, &rmc.refresh_session.coin.coin_pub), TALER_JSON_spec_denomination_signature ("denom_sig", &rmc.refresh_session.coin.denom_sig), - TALER_JSON_spec_denomination_public_key ("denom_pub", - &rmc.refresh_session.coin.denom_pub), + GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", + &rmc.refresh_session.coin.denom_pub_hash), GNUNET_JSON_spec_fixed_auto ("confirm_sig", &rmc.refresh_session.coin_sig), TALER_JSON_spec_amount ("value_with_fee", @@ -444,17 +444,6 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, if (GNUNET_OK != res) return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - if (GNUNET_OK != - TALER_test_coin_valid (&rmc.refresh_session.coin)) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID, - "denom_sig"); - } - - /* run actual logic, now that the request was parsed */ key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == key_state) { @@ -464,9 +453,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, "no keys"); goto cleanup; } - rmc.dki = TEH_KS_denomination_key_lookup (key_state, - &rmc.refresh_session.coin.denom_pub, - TEH_KS_DKU_DEPOSIT); + rmc.dki = TEH_KS_denomination_key_lookup_by_hash (key_state, + &rmc.refresh_session.coin.denom_pub_hash, + TEH_KS_DKU_DEPOSIT); if (NULL == rmc.dki) { TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n"); @@ -476,6 +465,20 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, goto cleanup; } + if (GNUNET_OK != + TALER_test_coin_valid (&rmc.refresh_session.coin, + &rmc.dki->denom_pub)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + TEH_KS_release (key_state); + return TEH_RESPONSE_reply_signature_invalid (connection, + TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID, + "denom_sig"); + } + + /* run actual logic, now that the request was parsed */ + /* make sure coin is 'known' in database */ { struct TEH_DB_KnowCoinContext kcc; @@ -502,11 +505,6 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, TEH_KS_release (key_state); key_state = NULL; } - if (NULL != rmc.refresh_session.coin.denom_pub.rsa_public_key) - { - GNUNET_CRYPTO_rsa_public_key_free (rmc.refresh_session.coin.denom_pub.rsa_public_key); - rmc.refresh_session.coin.denom_pub.rsa_public_key = NULL; - } if (NULL != rmc.refresh_session.coin.denom_sig.rsa_signature) { GNUNET_CRYPTO_rsa_signature_free (rmc.refresh_session.coin.denom_sig.rsa_signature); diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index bdf59c37b..25de5f1fe 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -265,7 +265,6 @@ static void free_refresh_melt (struct TALER_EXCHANGEDB_RefreshMelt *refresh_melt) { GNUNET_CRYPTO_rsa_signature_free (refresh_melt->session.coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (refresh_melt->session.coin.denom_pub.rsa_public_key); } diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index 92dd54e9f..ee6aac1bd 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -342,9 +342,9 @@ refund_transaction (void *cls, "no keys"); return GNUNET_DB_STATUS_HARD_ERROR; } - dki = TEH_KS_denomination_key_lookup (mks, - &dep->coin.denom_pub, - TEH_KS_DKU_DEPOSIT); + dki = TEH_KS_denomination_key_lookup_by_hash (mks, + &dep->coin.denom_pub_hash, + TEH_KS_DKU_DEPOSIT); if (NULL == dki) { /* DKI not found, but we do have a coin with this DK in our database; diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c index 370916b00..c988cde68 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c @@ -116,9 +116,9 @@ struct WithdrawContext struct TALER_Amount amount_required; /** - * Denomination public key. + * Hash of the denomination public key. */ - struct TALER_DenominationPublicKey denomination_pub; + struct GNUNET_HashCode denom_pub_hash; /** * Signature over the request. @@ -229,7 +229,7 @@ withdraw_transaction (void *cls, */ { #define PUBSIZE 80 - char pub_s[PUBSIZE]; + char pub_s[PUBSIZE]; GNUNET_break (NULL != GNUNET_STRINGS_data_to_string (&r.pub, @@ -312,7 +312,7 @@ withdraw_transaction (void *cls, #endif TALER_amount_ntoh (&fee_withdraw, &wc->dki->issue.properties.fee_withdraw); - wc->collectable.denom_pub = wc->denomination_pub; + wc->collectable.denom_pub_hash = wc->denom_pub_hash; wc->collectable.amount_with_fee = wc->amount_required; wc->collectable.withdraw_fee = fee_withdraw; wc->collectable.reserve_pub = wc->wsrd.reserve_pub; @@ -370,8 +370,8 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, &wc.wsrd.reserve_pub), GNUNET_JSON_spec_fixed_auto ("reserve_sig", &wc.signature), - TALER_JSON_spec_denomination_public_key ("denom_pub", - &wc.denomination_pub), + GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", + &wc.denom_pub_hash), GNUNET_JSON_spec_end () }; @@ -399,9 +399,9 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, TALER_EC_EXCHANGE_BAD_CONFIGURATION, "no keys"); } - wc.dki = TEH_KS_denomination_key_lookup (wc.key_state, - &wc.denomination_pub, - TEH_KS_DKU_WITHDRAW); + wc.dki = TEH_KS_denomination_key_lookup_by_hash (wc.key_state, + &wc.denom_pub_hash, + TEH_KS_DKU_WITHDRAW); if (NULL == wc.dki) { GNUNET_JSON_parse_free (spec); @@ -435,8 +435,8 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, = htonl (sizeof (struct TALER_WithdrawRequestPS)); wc.wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW); - GNUNET_CRYPTO_rsa_public_key_hash (wc.denomination_pub.rsa_public_key, - &wc.wsrd.h_denomination_pub); + wc.wsrd.h_denomination_pub + = wc.denom_pub_hash; GNUNET_CRYPTO_hash (wc.blinded_msg, wc.blinded_msg_len, &wc.wsrd.h_coin_envelope); diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 21046ef93..21394337d 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -750,7 +750,6 @@ TEH_RESPONSE_compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHisto break; case TALER_EXCHANGEDB_RO_WITHDRAW_COIN: { - struct GNUNET_HashCode h_denom_pub; struct TALER_Amount value; value = pos->details.withdraw->amount_with_fee; @@ -771,15 +770,13 @@ TEH_RESPONSE_compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHisto } } ret |= 2; - GNUNET_CRYPTO_rsa_public_key_hash (pos->details.withdraw->denom_pub.rsa_public_key, - &h_denom_pub); GNUNET_assert (0 == json_array_append_new (json_history, json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}", "type", "WITHDRAW", "reserve_sig", GNUNET_JSON_from_data_auto (&pos->details.withdraw->reserve_sig), "h_coin_envelope", GNUNET_JSON_from_data_auto (&pos->details.withdraw->h_coin_envelope), - "h_denom_pub", GNUNET_JSON_from_data_auto (&h_denom_pub), + "h_denom_pub", GNUNET_JSON_from_data_auto (&pos->details.withdraw->denom_pub_hash), "withdraw_fee", TALER_JSON_from_amount (&pos->details.withdraw->withdraw_fee), "amount", TALER_JSON_from_amount (&value)))); } diff --git a/src/exchange/test_taler_exchange_aggregator.c b/src/exchange/test_taler_exchange_aggregator.c index 0ba8152df..c0d3d912f 100644 --- a/src/exchange/test_taler_exchange_aggregator.c +++ b/src/exchange/test_taler_exchange_aggregator.c @@ -383,7 +383,8 @@ fake_coin (struct TALER_CoinPublicInfo *coin) { struct GNUNET_HashCode hc; - coin->denom_pub.rsa_public_key = coin_pub; + GNUNET_CRYPTO_rsa_public_key_hash (coin_pub, + &coin->denom_pub_hash); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &hc); coin->denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh (coin_pk, diff --git a/src/exchangedb/perf_taler_exchangedb_init.c b/src/exchangedb/perf_taler_exchangedb_init.c index 789aaea00..089536a45 100644 --- a/src/exchangedb/perf_taler_exchangedb_init.c +++ b/src/exchangedb/perf_taler_exchangedb_init.c @@ -263,9 +263,7 @@ PERF_TALER_EXCHANGEDB_deposit_init (const struct PERF_TALER_EXCHANGEDB_Coin *coi &deposit_fee)); { deposit->coin.coin_pub = coin->public_info.coin_pub; - deposit->coin.denom_pub.rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup ( - coin->public_info.denom_pub.rsa_public_key); - GNUNET_assert (NULL != coin->public_info.denom_pub.rsa_public_key); + deposit->coin.denom_pub_hash = coin->public_info.denom_pub_hash; deposit->coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup ( coin->public_info.denom_sig.rsa_signature); GNUNET_assert (NULL != coin->public_info.denom_sig.rsa_signature); @@ -298,8 +296,6 @@ PERF_TALER_EXCHANGEDB_deposit_copy (const struct TALER_EXCHANGEDB_Deposit *depos copy = GNUNET_new (struct TALER_EXCHANGEDB_Deposit); *copy = *deposit; copy->receiver_wire_account = json_incref (deposit->receiver_wire_account); - copy->coin.denom_pub.rsa_public_key = - GNUNET_CRYPTO_rsa_public_key_dup (deposit->coin.denom_pub.rsa_public_key); copy->coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (deposit->coin.denom_sig.rsa_signature); return copy; @@ -315,7 +311,6 @@ PERF_TALER_EXCHANGEDB_deposit_free (struct TALER_EXCHANGEDB_Deposit *deposit) { if (NULL == deposit) return GNUNET_OK; - GNUNET_CRYPTO_rsa_public_key_free (deposit->coin.denom_pub.rsa_public_key); GNUNET_CRYPTO_rsa_signature_free (deposit->coin.denom_sig.rsa_signature); json_decref (deposit->receiver_wire_account); GNUNET_free (deposit); @@ -350,24 +345,21 @@ PERF_TALER_EXCHANGEDB_coin_init ( /* public_info */ GNUNET_CRYPTO_eddsa_key_get_public (&coin->priv, &coin->public_info.coin_pub.eddsa_pub); - coin->public_info.denom_pub.rsa_public_key = - GNUNET_CRYPTO_rsa_public_key_dup (dki->denom_pub.rsa_public_key); + GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key, + &coin->public_info.denom_pub_hash); GNUNET_CRYPTO_hash (&coin->public_info.coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP), &hc); coin->public_info.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh (dki->denom_priv.rsa_private_key, &hc); - GNUNET_assert (NULL != coin->public_info.denom_pub.rsa_public_key); GNUNET_assert (NULL != coin->public_info.denom_sig.rsa_signature); /* blind */ coin->blind.sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (coin->public_info.denom_sig.rsa_signature); - coin->blind.denom_pub.rsa_public_key = - GNUNET_CRYPTO_rsa_public_key_dup (dki->denom_pub.rsa_public_key); + coin->blind.denom_pub_hash = coin->public_info.denom_pub_hash; GNUNET_assert (NULL != coin->blind.sig.rsa_signature); - GNUNET_assert (NULL != coin->blind.denom_pub.rsa_public_key); TALER_amount_ntoh (&coin->blind.amount_with_fee, &dki->issue.properties.value); TALER_amount_ntoh (&coin->blind.withdraw_fee, @@ -396,16 +388,14 @@ PERF_TALER_EXCHANGEDB_coin_copy (const struct PERF_TALER_EXCHANGEDB_Coin *coin) copy->priv = coin->priv; /* public_info */ copy->public_info.coin_pub = coin->public_info.coin_pub; - copy->public_info.denom_pub.rsa_public_key = - GNUNET_CRYPTO_rsa_public_key_dup (coin->public_info.denom_pub.rsa_public_key); + copy->public_info.denom_pub_hash = coin->public_info.denom_pub_hash; copy->public_info.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (coin->public_info.denom_sig.rsa_signature); /* blind */ copy->blind.sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (coin->blind.sig.rsa_signature); - copy->blind.denom_pub.rsa_public_key = - GNUNET_CRYPTO_rsa_public_key_dup (coin->blind.denom_pub.rsa_public_key); + copy->blind.denom_pub_hash = coin->blind.denom_pub_hash; copy->blind.amount_with_fee = coin->blind.amount_with_fee; copy->blind.withdraw_fee = coin->blind.withdraw_fee; copy->blind.reserve_pub = coin->blind.reserve_pub; @@ -426,10 +416,8 @@ PERF_TALER_EXCHANGEDB_coin_free (struct PERF_TALER_EXCHANGEDB_Coin *coin) { if (NULL == coin) return GNUNET_OK; - GNUNET_CRYPTO_rsa_public_key_free (coin->public_info.denom_pub.rsa_public_key); GNUNET_CRYPTO_rsa_signature_free (coin->public_info.denom_sig.rsa_signature); GNUNET_CRYPTO_rsa_signature_free (coin->blind.sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (coin->blind.denom_pub.rsa_public_key); GNUNET_free (coin); return GNUNET_OK; } @@ -475,9 +463,7 @@ PERF_TALER_EXCHANGEDB_refresh_melt_init (struct TALER_RefreshCommitmentP *rc, melt->session.coin.coin_pub = coin->public_info.coin_pub; melt->session.coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (coin->public_info.denom_sig.rsa_signature); - melt->session.coin.denom_pub.rsa_public_key = - GNUNET_CRYPTO_rsa_public_key_dup (coin->public_info.denom_pub.rsa_public_key); - GNUNET_assert (NULL != melt->session.coin.denom_pub.rsa_public_key); + melt->session.coin.denom_pub_hash = coin->public_info.denom_pub_hash; GNUNET_assert (NULL != melt->session.coin.denom_sig.rsa_signature); melt->session.coin_sig = coin_sig; melt->session.rc = *rc; diff --git a/src/exchangedb/perf_taler_exchangedb_interpreter.c b/src/exchangedb/perf_taler_exchangedb_interpreter.c index cdd5a5fc1..6c968410b 100644 --- a/src/exchangedb/perf_taler_exchangedb_interpreter.c +++ b/src/exchangedb/perf_taler_exchangedb_interpreter.c @@ -1342,12 +1342,15 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state) unsigned int denom_index; enum GNUNET_DB_QueryStatus qs; struct PERF_TALER_EXCHANGEDB_Data *data; + struct GNUNET_HashCode hc; denom_index = state->cmd[state->i].details.get_denomination.index_denom; data = &state->cmd[denom_index].exposed; + GNUNET_CRYPTO_rsa_public_key_hash (data->data.dki->denom_pub.rsa_public_key, + &hc); qs = state->plugin->get_denomination_info (state->plugin->cls, state->session, - &data->data.dki->denom_pub, + &hc, &data->data.dki->issue); GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); } diff --git a/src/exchangedb/plugin_exchangedb_common.c b/src/exchangedb/plugin_exchangedb_common.c index 26515670a..fd2620c7b 100644 --- a/src/exchangedb/plugin_exchangedb_common.c +++ b/src/exchangedb/plugin_exchangedb_common.c @@ -49,13 +49,11 @@ common_free_reserve_history (void *cls, case TALER_EXCHANGEDB_RO_WITHDRAW_COIN: cbc = rh->details.withdraw; GNUNET_CRYPTO_rsa_signature_free (cbc->sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub.rsa_public_key); GNUNET_free (cbc); break; case TALER_EXCHANGEDB_RO_PAYBACK_COIN: payback = rh->details.payback; GNUNET_CRYPTO_rsa_signature_free (payback->coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (payback->coin.denom_pub.rsa_public_key); GNUNET_free (payback); break; case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK: @@ -92,29 +90,21 @@ common_free_coin_transaction_list (void *cls, case TALER_EXCHANGEDB_TT_DEPOSIT: if (NULL != list->details.deposit->receiver_wire_account) json_decref (list->details.deposit->receiver_wire_account); - if (NULL != list->details.deposit->coin.denom_pub.rsa_public_key) - GNUNET_CRYPTO_rsa_public_key_free (list->details.deposit->coin.denom_pub.rsa_public_key); if (NULL != list->details.deposit->coin.denom_sig.rsa_signature) GNUNET_CRYPTO_rsa_signature_free (list->details.deposit->coin.denom_sig.rsa_signature); GNUNET_free (list->details.deposit); break; case TALER_EXCHANGEDB_TT_REFRESH_MELT: - if (NULL != list->details.melt->session.coin.denom_pub.rsa_public_key) - GNUNET_CRYPTO_rsa_public_key_free (list->details.melt->session.coin.denom_pub.rsa_public_key); if (NULL != list->details.melt->session.coin.denom_sig.rsa_signature) GNUNET_CRYPTO_rsa_signature_free (list->details.melt->session.coin.denom_sig.rsa_signature); GNUNET_free (list->details.melt); break; case TALER_EXCHANGEDB_TT_REFUND: - if (NULL != list->details.refund->coin.denom_pub.rsa_public_key) - GNUNET_CRYPTO_rsa_public_key_free (list->details.refund->coin.denom_pub.rsa_public_key); if (NULL != list->details.refund->coin.denom_sig.rsa_signature) GNUNET_CRYPTO_rsa_signature_free (list->details.refund->coin.denom_sig.rsa_signature); GNUNET_free (list->details.refund); break; case TALER_EXCHANGEDB_TT_PAYBACK: - if (NULL != list->details.payback->coin.denom_pub.rsa_public_key) - GNUNET_CRYPTO_rsa_public_key_free (list->details.payback->coin.denom_pub.rsa_public_key); if (NULL != list->details.payback->coin.denom_sig.rsa_signature) GNUNET_CRYPTO_rsa_signature_free (list->details.payback->coin.denom_sig.rsa_signature); GNUNET_free (list->details.payback); diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 82308ea86..9dc8eb2f3 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -766,7 +766,7 @@ postgres_prepare (PGconn *db_conn) make sure /reserve/withdraw requests are idempotent. */ GNUNET_PQ_make_prepare ("get_withdraw_info", "SELECT" - " denom.denom_pub" + " denom_pub_hash" ",denom_sig" ",reserve_sig" ",reserve_pub" @@ -790,7 +790,7 @@ postgres_prepare (PGconn *db_conn) GNUNET_PQ_make_prepare ("get_reserves_out", "SELECT" " h_blind_ev" - ",denom.denom_pub" + ",denom_pub_hash" ",denom_sig" ",reserve_sig" ",execution_date" @@ -838,11 +838,9 @@ postgres_prepare (PGconn *db_conn) a coin known to the exchange. */ GNUNET_PQ_make_prepare ("get_known_coin", "SELECT" - " denom.denom_pub" + " denom_pub_hash" ",denom_sig" " FROM known_coins" - " JOIN denominations denom" - " USING (denom_pub_hash)" " WHERE coin_pub=$1" " FOR UPDATE;", 1), @@ -876,7 +874,7 @@ postgres_prepare (PGconn *db_conn) high-level information about a melt operation */ GNUNET_PQ_make_prepare ("get_melt", "SELECT" - " denom.denom_pub" + " kc.denom_pub_hash" ",denom.fee_refresh_val" ",denom.fee_refresh_frac" ",denom.fee_refresh_curr" @@ -1518,6 +1516,7 @@ postgres_prepare (PGconn *db_conn) ",coin_sig" ",coin_blind" ",h_blind_ev" + ",coins.denom_pub_hash" ",denoms.denom_pub" ",coins.denom_sig" ",amount_val" @@ -1526,10 +1525,10 @@ postgres_prepare (PGconn *db_conn) " FROM payback" " JOIN known_coins coins" " USING (coin_pub)" - " JOIN denominations denoms" - " USING (denom_pub_hash)" " JOIN reserves_out ro" " USING (h_blind_ev)" + " JOIN denominations denoms" + " ON (coins.denom_pub_hash = denoms.denom_pub_hash)" " WHERE payback_uuid>=$1" " ORDER BY payback_uuid ASC;", 1), @@ -1563,13 +1562,11 @@ postgres_prepare (PGconn *db_conn) ",amount_frac" ",amount_curr" ",timestamp" - ",denoms.denom_pub" + ",coins.denom_pub_hash" ",coins.denom_sig" " FROM payback" " JOIN known_coins coins" " USING (coin_pub)" - " JOIN denominations denoms" - " USING (denom_pub_hash)" " JOIN reserves_out ro" " USING (h_blind_ev)" " WHERE ro.reserve_pub=$1" @@ -1618,13 +1615,11 @@ postgres_prepare (PGconn *db_conn) ",amount_frac" ",amount_curr" ",timestamp" - ",denoms.denom_pub" + ",coins.denom_pub_hash" ",coins.denom_sig" " FROM payback" " JOIN known_coins coins" " USING (coin_pub)" - " JOIN denominations denoms" - " USING (denom_pub_hash)" " JOIN reserves_out ro" " USING (h_blind_ev)" " WHERE payback.coin_pub=$1;", @@ -1947,20 +1942,19 @@ postgres_insert_denomination_info (void *cls, * * @param cls the @e cls of this struct with the plugin-specific state * @param session connection to use - * @param denom_pub the public key used for signing coins of this denomination + * @param denom_pub_hash hash of the public key used for signing coins of this denomination * @param[out] issue set to issue information with value, fees and other info about the coin * @return transaction status code */ static enum GNUNET_DB_QueryStatus postgres_get_denomination_info (void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_DenominationPublicKey *denom_pub, + const struct GNUNET_HashCode *denom_pub_hash, struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue) { enum GNUNET_DB_QueryStatus qs; - struct GNUNET_HashCode dph; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&dph), + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { @@ -1989,8 +1983,6 @@ postgres_get_denomination_info (void *cls, GNUNET_PQ_result_spec_end }; - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, - &dph); qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn, "denomination_get", params, @@ -1999,8 +1991,7 @@ postgres_get_denomination_info (void *cls, return qs; issue->properties.purpose.size = htonl (sizeof (struct TALER_DenominationKeyValidityPS)); issue->properties.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY); - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, - &issue->properties.denom_hash); + issue->properties.denom_hash = *denom_pub_hash; return qs; } @@ -2394,10 +2385,10 @@ postgres_get_withdraw_info (void *cls, GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &collectable->denom_pub.rsa_public_key), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &collectable->denom_pub_hash), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", - &collectable->sig.rsa_signature), + &collectable->sig.rsa_signature), GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", &collectable->reserve_sig), GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", @@ -2434,12 +2425,11 @@ postgres_insert_withdraw_info (void *cls, { struct PostgresClosure *pg = cls; struct TALER_EXCHANGEDB_Reserve reserve; - struct GNUNET_HashCode denom_pub_hash; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute expiry; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (&collectable->h_coin_envelope), - GNUNET_PQ_query_param_auto_from_type (&denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&collectable->denom_pub_hash), GNUNET_PQ_query_param_rsa_signature (collectable->sig.rsa_signature), GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub), GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_sig), @@ -2451,8 +2441,6 @@ postgres_insert_withdraw_info (void *cls, now = GNUNET_TIME_absolute_get (); (void) GNUNET_TIME_round_abs (&now); - GNUNET_CRYPTO_rsa_public_key_hash (collectable->denom_pub.rsa_public_key, - &denom_pub_hash); qs = GNUNET_PQ_eval_prepared_non_select (session->conn, "insert_withdraw_info", params); @@ -2638,8 +2626,8 @@ add_withdraw_coin (void *cls, struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", &cbc->h_coin_envelope), - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &cbc->denom_pub.rsa_public_key), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &cbc->denom_pub_hash), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", &cbc->sig.rsa_signature), GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", @@ -2692,7 +2680,7 @@ add_payback (void *cls, payback = GNUNET_new (struct TALER_EXCHANGEDB_Payback); { struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_amount ("amount", + TALER_PQ_result_spec_amount ("amount", &payback->value), GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &payback->coin.coin_pub), @@ -2702,10 +2690,10 @@ add_payback (void *cls, &payback->coin_sig), TALER_PQ_result_spec_absolute_time ("timestamp", &payback->timestamp), - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &payback->coin.denom_pub.rsa_public_key), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &payback->coin.denom_pub_hash), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", - &payback->coin.denom_sig.rsa_signature), + &payback->coin.denom_sig.rsa_signature), GNUNET_PQ_result_spec_end }; @@ -3291,8 +3279,8 @@ get_known_coin (void *cls, GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &coin_info->denom_pub.rsa_public_key), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &coin_info->denom_pub_hash), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", &coin_info->denom_sig.rsa_signature), GNUNET_PQ_result_spec_end @@ -3324,10 +3312,9 @@ insert_known_coin (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct TALER_CoinPublicInfo *coin_info) { - struct GNUNET_HashCode denom_pub_hash; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (&coin_info->coin_pub), - GNUNET_PQ_query_param_auto_from_type (&denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin_info->denom_pub_hash), GNUNET_PQ_query_param_rsa_signature (coin_info->denom_sig.rsa_signature), GNUNET_PQ_query_param_end }; @@ -3335,8 +3322,6 @@ insert_known_coin (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating known coin %s\n", TALER_B2S (&coin_info->coin_pub)); - GNUNET_CRYPTO_rsa_public_key_hash (coin_info->denom_pub.rsa_public_key, - &denom_pub_hash); return GNUNET_PQ_eval_prepared_non_select (session->conn, "insert_known_coin", params); @@ -3407,7 +3392,6 @@ postgres_ensure_coin_known (void *cls, } if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) { - GNUNET_CRYPTO_rsa_public_key_free (known_coin.denom_pub.rsa_public_key); GNUNET_CRYPTO_rsa_signature_free (known_coin.denom_sig.rsa_signature); return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; /* no change! */ } @@ -3647,8 +3631,8 @@ postgres_get_melt (void *cls, GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &refresh_melt->session.coin.denom_pub.rsa_public_key), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &refresh_melt->session.coin.denom_pub_hash), TALER_PQ_result_spec_amount ("fee_refresh", &refresh_melt->melt_fee), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", @@ -4470,8 +4454,8 @@ add_coin_payback (void *cls, &payback->coin_sig), TALER_PQ_result_spec_absolute_time ("timestamp", &payback->timestamp), - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &payback->coin.denom_pub.rsa_public_key), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &payback->coin.denom_pub_hash), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", &payback->coin.denom_sig.rsa_signature), GNUNET_PQ_result_spec_end @@ -6356,6 +6340,7 @@ payback_serial_helper_cb (void *cls, struct TALER_CoinPublicInfo coin; struct TALER_CoinSpendSignatureP coin_sig; struct TALER_DenominationBlindingKeyP coin_blind; + struct TALER_DenominationPublicKey denom_pub; struct TALER_Amount amount; struct GNUNET_HashCode h_blind_ev; struct GNUNET_TIME_Absolute timestamp; @@ -6374,8 +6359,10 @@ payback_serial_helper_cb (void *cls, &coin_blind), GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", &h_blind_ev), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &coin.denom_pub_hash), GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &coin.denom_pub.rsa_public_key), + &denom_pub.rsa_public_key), GNUNET_PQ_result_spec_rsa_signature ("denom_sig", &coin.denom_sig.rsa_signature), TALER_PQ_result_spec_amount ("amount", @@ -6399,6 +6386,7 @@ payback_serial_helper_cb (void *cls, &amount, &reserve_pub, &coin, + &denom_pub, &coin_sig, &coin_blind); GNUNET_PQ_cleanup_result (rs); diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index c8d4fa041..66ccb4c79 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -271,7 +271,7 @@ create_denom_key_pair (unsigned int size, if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_denomination_info (plugin->cls, session, - &dki.denom_pub, + &dki.issue.properties.denom_hash, &issue2)) { GNUNET_break(0); @@ -574,7 +574,8 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key, &hc); GNUNET_assert (NULL != refresh_session.coin.denom_sig.rsa_signature); - refresh_session.coin.denom_pub = dkp->pub; + GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, + &refresh_session.coin.denom_pub_hash); refresh_session.amount_with_fee = amount_with_fee; } @@ -616,10 +617,9 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) &ret_refresh_session.session.coin.coin_pub, sizeof (refresh_session.coin.coin_pub))); FAILIF (0 != - GNUNET_CRYPTO_rsa_public_key_cmp (refresh_session.coin.denom_pub.rsa_public_key, - ret_refresh_session.session.coin.denom_pub.rsa_public_key)); + GNUNET_memcmp (&refresh_session.coin.denom_pub_hash, + &ret_refresh_session.session.coin.denom_pub_hash)); GNUNET_CRYPTO_rsa_signature_free (ret_refresh_session.session.coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (ret_refresh_session.session.coin.denom_pub.rsa_public_key); /* test 'select_refreshs_above_serial_id' */ auditor_row_cnt = 0; @@ -1057,6 +1057,7 @@ test_gc (struct TALER_EXCHANGEDB_Session *session) struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute past; struct TALER_EXCHANGEDB_DenominationKeyInformationP issue2; + struct GNUNET_HashCode denom_hash; now = GNUNET_TIME_absolute_get (); GNUNET_TIME_round_abs (&now); @@ -1079,10 +1080,13 @@ test_gc (struct TALER_EXCHANGEDB_Session *session) destroy_denom_key_pair (dkp); return GNUNET_SYSERR; } + GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, + &denom_hash); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->get_denomination_info (plugin->cls, session, - &dkp->pub, + &denom_hash, &issue2)) { GNUNET_break(0); @@ -1376,6 +1380,7 @@ payback_cb (void *cls, const struct TALER_Amount *amount, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_CoinPublicInfo *coin, + const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind) { @@ -1700,7 +1705,7 @@ run (void *cls) &dkp_pub_hash); RND_BLK(&cbc.h_coin_envelope); RND_BLK(&cbc.reserve_sig); - cbc.denom_pub = dkp->pub; + cbc.denom_pub_hash = dkp_pub_hash; cbc.sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key, &cbc.h_coin_envelope); @@ -1732,7 +1737,6 @@ run (void *cls) session, &cbc.h_coin_envelope, &cbc2)); - FAILIF (NULL == cbc2.denom_pub.rsa_public_key); FAILIF(0 != GNUNET_memcmp(&cbc2.reserve_sig, &cbc.reserve_sig)); FAILIF(0 != GNUNET_memcmp(&cbc2.reserve_pub, &cbc.reserve_pub)); result = 6; @@ -1745,7 +1749,8 @@ run (void *cls) RND_BLK (&coin_sig); RND_BLK (&coin_blind); RND_BLK (&deposit.coin.coin_pub); - deposit.coin.denom_pub = dkp->pub; + GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, + &deposit.coin.denom_pub_hash); deposit.coin.denom_sig = cbc.sig; deadline = GNUNET_TIME_absolute_get (); (void) GNUNET_TIME_round_abs (&deadline); @@ -1885,7 +1890,8 @@ run (void *cls) 0, sizeof (deposit)); RND_BLK (&deposit.coin.coin_pub); - deposit.coin.denom_pub = dkp->pub; + GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, + &deposit.coin.denom_pub_hash); deposit.coin.denom_sig = cbc.sig; RND_BLK (&deposit.csig); RND_BLK (&deposit.merchant_pub); @@ -2259,8 +2265,6 @@ run (void *cls) destroy_denom_key_pair (dkp); if (NULL != cbc.sig.rsa_signature) GNUNET_CRYPTO_rsa_signature_free (cbc.sig.rsa_signature); - if (NULL != cbc2.denom_pub.rsa_public_key) - GNUNET_CRYPTO_rsa_public_key_free (cbc2.denom_pub.rsa_public_key); if (NULL != cbc2.sig.rsa_signature) GNUNET_CRYPTO_rsa_signature_free (cbc2.sig.rsa_signature); dkp = NULL; diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index f12516177..18c214e19 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -354,10 +354,10 @@ struct TALER_CoinPublicInfo struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Public key representing the denomination of the coin - * that is being deposited. + * Hash of the public key representing the denomination of the coin that is + * being deposited. */ - struct TALER_DenominationPublicKey denom_pub; + struct GNUNET_HashCode denom_pub_hash; /** * (Unblinded) signature over @e coin_pub with @e denom_pub, @@ -401,12 +401,14 @@ struct TALER_TrackTransferDetails * is not expired, and the signature is correct. * * @param coin_public_info the coin public info to check for validity + * @param denom_pub denomination key, must match @a coin_public_info's `denom_pub_hash` * @return #GNUNET_YES if the coin is valid, * #GNUNET_NO if it is invalid * #GNUNET_SYSERR if an internal error occured */ int -TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info); +TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, + const struct TALER_DenominationPublicKey *denom_pub); GNUNET_NETWORK_STRUCT_BEGIN diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 2d9f14208..0a46c7264 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -147,9 +147,9 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin struct TALER_DenominationSignature sig; /** - * Denomination key (which coin was generated). + * Hash of the denomination key (which coin was generated). */ - struct TALER_DenominationPublicKey denom_pub; + struct GNUNET_HashCode denom_pub_hash; /** * Value of the coin being exchangeed (matching the denomination key) @@ -1045,6 +1045,7 @@ typedef int const struct TALER_Amount *amount, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_CoinPublicInfo *coin, + const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_DenominationBlindingKeyP *coin_blind); @@ -1274,14 +1275,14 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param session connection to use - * @param denom_pub the public key used for signing coins of this denomination + * @param denom_pub_hash hash of the public key used for signing coins of this denomination * @param[out] issue set to issue information with value, fees and other info about the coin * @return transaction status code */ enum GNUNET_DB_QueryStatus (*get_denomination_info) (void *cls, struct TALER_EXCHANGEDB_Session *session, - const struct TALER_DenominationPublicKey *denom_pub, + const struct GNUNET_HashCode *denom_pub_hash, struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue); diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c index 3f72ad956..4033cc2ee 100644 --- a/src/lib/exchange_api_deposit.c +++ b/src/lib/exchange_api_deposit.c @@ -359,6 +359,7 @@ handle_deposit_finished (void *cls, * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) * @param coin_pub coin’s public key * @param denom_pub denomination key with which the coin is signed + * @param denom_pub_hash hash of @a denom_pub * @param denom_sig exchange’s unblinded signature of the coin * @param timestamp timestamp when the deposit was finalized * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) @@ -374,6 +375,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_DenominationSignature *denom_sig, const struct TALER_DenominationPublicKey *denom_pub, + const struct GNUNET_HashCode *denom_pub_hash, struct GNUNET_TIME_Absolute timestamp, const struct TALER_MerchantPublicKeyP *merchant_pub, struct GNUNET_TIME_Absolute refund_deadline, @@ -414,10 +416,11 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki, /* check coin signature */ coin_info.coin_pub = *coin_pub; - coin_info.denom_pub = *denom_pub; + coin_info.denom_pub_hash = *denom_pub_hash; coin_info.denom_sig = *denom_sig; if (GNUNET_YES != - TALER_test_coin_valid (&coin_info)) + TALER_test_coin_valid (&coin_info, + denom_pub)) { GNUNET_break_op (0); TALER_LOG_WARNING ("Invalid coin passed for /deposit\n"); @@ -489,6 +492,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, json_t *deposit_obj; CURL *eh; struct GNUNET_HashCode h_wire; + struct GNUNET_HashCode denom_pub_hash; struct TALER_Amount amount_without_fee; (void) GNUNET_TIME_round_abs (&wire_deadline); @@ -512,6 +516,8 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, TALER_amount_subtract (&amount_without_fee, amount, &dki->fee_deposit)); + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, + &denom_pub_hash); if (GNUNET_OK != verify_signatures (dki, amount, @@ -520,6 +526,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, coin_pub, denom_sig, denom_pub, + &denom_pub_hash, timestamp, merchant_pub, refund_deadline, @@ -541,7 +548,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, "H_wire", GNUNET_JSON_from_data_auto (&h_wire), "h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms), "coin_pub", GNUNET_JSON_from_data_auto (coin_pub), - "denom_pub", GNUNET_JSON_from_rsa_public_key (denom_pub->rsa_public_key), + "denom_pub_hash", GNUNET_JSON_from_data_auto (&denom_pub_hash), "ub_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature), "timestamp", GNUNET_JSON_from_time_abs (timestamp), "merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub), diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index cbcde724d..93fe798c3 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -432,7 +432,7 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key, */ static int parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key, - int check_sigs, + int check_sigs, json_t *denom_key_obj, struct TALER_MasterPublicKeyP *master_key, struct GNUNET_HashContext *hash_context) diff --git a/src/lib/exchange_api_payback.c b/src/lib/exchange_api_payback.c index 6c1772aff..b3624f737 100644 --- a/src/lib/exchange_api_payback.c +++ b/src/lib/exchange_api_payback.c @@ -280,6 +280,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, struct GNUNET_CURL_Context *ctx; struct TALER_PaybackRequestPS pr; struct TALER_CoinSpendSignatureP coin_sig; + struct GNUNET_HashCode h_denom_pub; json_t *payback_obj; CURL *eh; @@ -289,6 +290,8 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, pr.purpose.size = htonl (sizeof (struct TALER_PaybackRequestPS)); GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv, &pr.coin_pub.eddsa_pub); + GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key, + &h_denom_pub); pr.h_denom_pub = pk->h_key; pr.coin_blind = ps->blinding_key; GNUNET_assert (GNUNET_OK == @@ -299,7 +302,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, payback_obj = json_pack ("{s:o, s:o," /* denom pub/sig */ " s:o, s:o," /* coin pub/sig */ " s:o}", /* coin_bks */ - "denom_pub", GNUNET_JSON_from_rsa_public_key (pk->key.rsa_public_key), + "denom_pub_hash", GNUNET_JSON_from_data_auto (&h_denom_pub), "denom_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature), "coin_pub", GNUNET_JSON_from_data_auto (&pr.coin_pub), "coin_sig", GNUNET_JSON_from_data_auto (&coin_sig), diff --git a/src/lib/exchange_api_refresh.c b/src/lib/exchange_api_refresh.c index 230f445e6..4b2de2f45 100644 --- a/src/lib/exchange_api_refresh.c +++ b/src/lib/exchange_api_refresh.c @@ -1151,6 +1151,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, struct MeltData *md; struct TALER_CoinSpendSignatureP confirm_sig; struct TALER_RefreshMeltCoinAffirmationPS melt; + struct GNUNET_HashCode h_denom_pub; GNUNET_assert (GNUNET_YES == TEAH_handle_is_ready (exchange)); @@ -1174,11 +1175,13 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, GNUNET_CRYPTO_eddsa_sign (&md->melted_coin.coin_priv.eddsa_priv, &melt.purpose, &confirm_sig.eddsa_signature); + GNUNET_CRYPTO_rsa_public_key_hash (md->melted_coin.pub_key.rsa_public_key, + &h_denom_pub); melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}", "coin_pub", GNUNET_JSON_from_data_auto (&melt.coin_pub), - "denom_pub", - GNUNET_JSON_from_rsa_public_key (md->melted_coin.pub_key.rsa_public_key), + "denom_pub_hash", + GNUNET_JSON_from_data_auto (&h_denom_pub), "denom_sig", GNUNET_JSON_from_rsa_signature (md->melted_coin.sig.rsa_signature), "confirm_sig", diff --git a/src/lib/exchange_api_reserve.c b/src/lib/exchange_api_reserve.c index 4aa5794fa..66509bc53 100644 --- a/src/lib/exchange_api_reserve.c +++ b/src/lib/exchange_api_reserve.c @@ -187,8 +187,8 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle *exchange, struct GNUNET_JSON_Specification withdraw_spec[] = { GNUNET_JSON_spec_fixed_auto ("reserve_sig", &sig), - TALER_JSON_spec_amount_nbo ("withdraw_fee", - &withdraw_purpose.withdraw_fee), + TALER_JSON_spec_amount_nbo ("withdraw_fee", + &withdraw_purpose.withdraw_fee), GNUNET_JSON_spec_fixed_auto ("h_denom_pub", &withdraw_purpose.h_denomination_pub), GNUNET_JSON_spec_fixed_auto ("h_coin_envelope", @@ -1001,6 +1001,7 @@ reserve_withdraw_internal (struct TALER_EXCHANGE_Handle *exchange, struct GNUNET_CURL_Context *ctx; json_t *withdraw_obj; CURL *eh; + struct GNUNET_HashCode h_denom_pub; wsh = GNUNET_new (struct TALER_EXCHANGE_ReserveWithdrawHandle); wsh->exchange = exchange; @@ -1009,9 +1010,11 @@ reserve_withdraw_internal (struct TALER_EXCHANGE_Handle *exchange, wsh->pk = pk; wsh->reserve_pub = *reserve_pub; wsh->c_hash = pd->c_hash; - withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */ + GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key, + &h_denom_pub); + withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub_hash and coin_ev */ " s:o, s:o}",/* reserve_pub and reserve_sig */ - "denom_pub", GNUNET_JSON_from_rsa_public_key (pk->key.rsa_public_key), + "denom_pub_hash", GNUNET_JSON_from_data_auto (&h_denom_pub), "coin_ev", GNUNET_JSON_from_data (pd->coin_ev, pd->coin_ev_size), "reserve_pub", GNUNET_JSON_from_data_auto (reserve_pub), diff --git a/src/util/crypto.c b/src/util/crypto.c index b44c31ff7..95eb11eba 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -77,22 +77,33 @@ TALER_gcrypt_init () * is not expired, and the signature is correct. * * @param coin_public_info the coin public info to check for validity + * @param denom_pub denomination key, must match @a coin_public_info's `denom_pub_hash` * @return #GNUNET_YES if the coin is valid, * #GNUNET_NO if it is invalid * #GNUNET_SYSERR if an internal error occured */ int -TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info) +TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, + const struct TALER_DenominationPublicKey *denom_pub) { struct GNUNET_HashCode c_hash; +#if 1 /* sanity check of invariant, could probably be disabled in production + for slightly more performance */ + struct GNUNET_HashCode d_hash; + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, + &d_hash); + GNUNET_assert (0 == + GNUNET_memcmp (&d_hash, + &coin_public_info->denom_pub_hash)); +#endif GNUNET_CRYPTO_hash (&coin_public_info->coin_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &c_hash); if (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (&c_hash, coin_public_info->denom_sig.rsa_signature, - coin_public_info->denom_pub.rsa_public_key)) + denom_pub->rsa_public_key)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "coin signature is invalid\n"); From 9c194f79a5d9fdba4d5cb9a0379bb8cae4778b95 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 2 May 2019 22:25:47 +0200 Subject: [PATCH 7/9] adapt to GNUnet API change --- src/auditor/taler-auditor-httpd_parsing.c | 1 + src/bank-lib/fakebank.c | 10 ++++++---- src/exchange/taler-exchange-httpd_parsing.c | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/auditor/taler-auditor-httpd_parsing.c b/src/auditor/taler-auditor-httpd_parsing.c index ebbe50eee..6c4bece94 100644 --- a/src/auditor/taler-auditor-httpd_parsing.c +++ b/src/auditor/taler-auditor-httpd_parsing.c @@ -70,6 +70,7 @@ TAH_PARSE_post_json (struct MHD_Connection *connection, enum GNUNET_JSON_PostResult pr; pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, + connection, con_cls, upload_data, upload_data_size, diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c index 27cf6b8b9..71dd8bace 100644 --- a/src/bank-lib/fakebank.c +++ b/src/bank-lib/fakebank.c @@ -397,6 +397,7 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h, uint64_t row_id; pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, + connection, con_cls, upload_data, upload_data_size, @@ -523,6 +524,7 @@ handle_reject (struct TALER_FAKEBANK_Handle *h, int found; pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, + connection, con_cls, upload_data, upload_data_size, @@ -604,7 +606,7 @@ handle_home_page (struct TALER_FAKEBANK_Handle *h, int ret; struct MHD_Response *resp; #define HELLOMSG "Hello, Fakebank!" - + resp = MHD_create_response_from_buffer (strlen (HELLOMSG), HELLOMSG, @@ -721,8 +723,8 @@ handle_history_range (struct TALER_FAKEBANK_Handle *h, struct HistoryRangeDates hrd; const char *start; const char *end; - long long unsigned int start_stamp; - long long unsigned int end_stamp; + long long unsigned int start_stamp; + long long unsigned int end_stamp; struct Transaction *pos; if (GNUNET_OK != TFH_parse_history_common_args (connection, @@ -760,7 +762,7 @@ handle_history_range (struct TALER_FAKEBANK_Handle *h, pos = pos->next) { if (hrd.start.abs_value_us <= pos->date.abs_value_us) - break; + break; } return TFH_build_history_response (connection, pos, diff --git a/src/exchange/taler-exchange-httpd_parsing.c b/src/exchange/taler-exchange-httpd_parsing.c index 4d7b5ab60..2a9f7a5a7 100644 --- a/src/exchange/taler-exchange-httpd_parsing.c +++ b/src/exchange/taler-exchange-httpd_parsing.c @@ -70,6 +70,7 @@ TEH_PARSE_post_json (struct MHD_Connection *connection, enum GNUNET_JSON_PostResult pr; pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, + connection, con_cls, upload_data, upload_data_size, From 5dd3c2191af0bb28a95fe4dac09eae7ed672cd48 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 2 May 2019 23:45:31 +0200 Subject: [PATCH 8/9] benchmark: don't print result as exchange worker --- src/benchmark/taler-exchange-benchmark.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c index eed8f80d8..569283516 100644 --- a/src/benchmark/taler-exchange-benchmark.c +++ b/src/benchmark/taler-exchange-benchmark.c @@ -1048,8 +1048,14 @@ main (int argc, NULL, cfg_filename, exchange_url); + GNUNET_free_non_null (exchange_url); GNUNET_free_non_null (auditor_url); + + /* If we're the exchange worker, we're done now. No need to print results */ + if (MODE_EXCHANGE == mode) + return (GNUNET_OK == result) ? 0 : result; + duration = GNUNET_TIME_absolute_get_duration (start_time); if (GNUNET_OK == result) { From a16c32a4745634b77439200ee4831fed2811fd8a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 3 May 2019 17:36:58 +0200 Subject: [PATCH 9/9] add compression support for bodies of POST/PUT operations --- ChangeLog | 4 + src/lib/Makefile.am | 6 +- src/lib/auditor_api_deposit_confirmation.c | 39 ++++---- src/lib/auditor_api_handle.c | 12 ++- src/lib/auditor_api_handle.h | 2 +- src/lib/exchange_api_deposit.c | 30 +++--- src/lib/exchange_api_handle.c | 8 ++ src/lib/exchange_api_handle.h | 2 +- src/lib/exchange_api_payback.c | 29 +++--- src/lib/exchange_api_refresh.c | 60 ++++++------ src/lib/exchange_api_refund.c | 30 +++--- src/lib/exchange_api_reserve.c | 32 ++++--- src/lib/exchange_api_track_transaction.c | 32 ++++--- src/lib/teah_common.c | 105 +++++++++++++++++++++ src/lib/teah_common.h | 74 +++++++++++++++ 15 files changed, 338 insertions(+), 127 deletions(-) create mode 100644 src/lib/teah_common.c create mode 100644 src/lib/teah_common.h diff --git a/ChangeLog b/ChangeLog index c7bf8b7f9..a5ab93af3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Fri 03 May 2019 05:36:10 PM CEST + Add support for compressing bodies during HTTP uploads to + exchange and auditor. -CG + Thu 02 May 2019 09:15:37 PM CEST Pass hash of denomination public key in operations from clients to exchange instead of the (larger) full public key. diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 8b20860b7..0aa78d7b8 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -27,7 +27,8 @@ libtalerexchange_la_SOURCES = \ exchange_api_reserve.c \ exchange_api_track_transaction.c \ exchange_api_track_transfer.c \ - exchange_api_wire.c + exchange_api_wire.c \ + teah_common.c teah_common.h libtalerexchange_la_LIBADD = \ libtalerauditor.la \ $(top_builddir)/src/json/libtalerjson.la \ @@ -46,7 +47,8 @@ libtalerauditor_la_SOURCES = \ auditor_api_curl_defaults.c auditor_api_curl_defaults.h \ auditor_api_handle.c auditor_api_handle.h \ auditor_api_deposit_confirmation.c \ - auditor_api_exchanges.c + auditor_api_exchanges.c \ + teah_common.c teah_common.h libtalerauditor_la_LIBADD = \ $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/util/libtalerutil.la \ diff --git a/src/lib/auditor_api_deposit_confirmation.c b/src/lib/auditor_api_deposit_confirmation.c index c34890e63..bb637797a 100644 --- a/src/lib/auditor_api_deposit_confirmation.c +++ b/src/lib/auditor_api_deposit_confirmation.c @@ -49,9 +49,10 @@ struct TALER_AUDITOR_DepositConfirmationHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Handle for the request. @@ -338,26 +339,26 @@ TALER_AUDITOR_deposit_confirmation (struct TALER_AUDITOR_Handle *auditor, dh->url = MAH_path_to_url (auditor, "/deposit-confirmation"); eh = TAL_curl_easy_get (dh->url); - GNUNET_assert (NULL != (dh->json_enc = - json_dumps (deposit_confirmation_obj, - JSON_COMPACT))); - json_decref (deposit_confirmation_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for deposit-confirmation: `%s'\n", - dh->url); - GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_CUSTOMREQUEST, "PUT")); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - dh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (dh->json_enc))); + if (GNUNET_OK != + TEAH_curl_easy_post (&dh->ctx, + eh, + deposit_confirmation_obj)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (deposit_confirmation_obj); + GNUNET_free (dh->url); + GNUNET_free (dh); + return NULL; + } + json_decref (deposit_confirmation_obj); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "URL for deposit-confirmation: `%s'\n", + dh->url); ctx = MAH_handle_to_context (auditor); dh->job = GNUNET_CURL_job_add (ctx, eh, @@ -383,7 +384,7 @@ TALER_AUDITOR_deposit_confirmation_cancel (struct TALER_AUDITOR_DepositConfirmat deposit_confirmation->job = NULL; } GNUNET_free (deposit_confirmation->url); - GNUNET_free (deposit_confirmation->json_enc); + TEAH_curl_easy_post_finished (&deposit_confirmation->ctx); GNUNET_free (deposit_confirmation); } diff --git a/src/lib/auditor_api_handle.c b/src/lib/auditor_api_handle.c index 70bf6f715..870eed83d 100644 --- a/src/lib/auditor_api_handle.c +++ b/src/lib/auditor_api_handle.c @@ -15,7 +15,7 @@ */ /** - * @file auditor-lib/auditor_api_handle.c + * @file lib/auditor_api_handle.c * @brief Implementation of the "handle" component of the auditor's HTTP API * @author Sree Harsha Totakura * @author Christian Grothoff @@ -462,6 +462,16 @@ TALER_AUDITOR_connect (struct GNUNET_CURL_Context *ctx, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to auditor at URL `%s'.\n", url); + /* Disable 100 continue processing */ + GNUNET_break (GNUNET_OK == + GNUNET_CURL_append_header (ctx, + "Expect:")); +#if COMPRESS_BODIES + /* Tell auditor we compress bodies */ + GNUNET_break (GNUNET_OK == + GNUNET_CURL_append_header (ctx, + "Content-encoding: deflate")); +#endif auditor = GNUNET_new (struct TALER_AUDITOR_Handle); auditor->ctx = ctx; auditor->url = GNUNET_strdup (url); diff --git a/src/lib/auditor_api_handle.h b/src/lib/auditor_api_handle.h index c3c73f5c3..c053cbbc0 100644 --- a/src/lib/auditor_api_handle.h +++ b/src/lib/auditor_api_handle.h @@ -22,7 +22,7 @@ #include "platform.h" #include #include "taler_auditor_service.h" - +#include "teah_common.h" /** * Get the context of a auditor. diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c index 4033cc2ee..b99c7a93f 100644 --- a/src/lib/exchange_api_deposit.c +++ b/src/lib/exchange_api_deposit.c @@ -60,9 +60,10 @@ struct TALER_EXCHANGE_DepositHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Handle for the request. @@ -581,21 +582,22 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, dh->coin_value = dki->value; eh = TEL_curl_easy_get (dh->url); - GNUNET_assert (NULL != (dh->json_enc = - json_dumps (deposit_obj, - JSON_COMPACT))); + if (GNUNET_OK != + TEAH_curl_easy_post (&dh->ctx, + eh, + deposit_obj)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (deposit_obj); + GNUNET_free (dh->url); + GNUNET_free (dh); + return NULL; + } json_decref (deposit_obj); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for deposit: `%s'\n", dh->url); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - dh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (dh->json_enc))); ctx = TEAH_handle_to_context (exchange); dh->job = GNUNET_CURL_job_add (ctx, eh, @@ -621,7 +623,7 @@ TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit) deposit->job = NULL; } GNUNET_free (deposit->url); - GNUNET_free (deposit->json_enc); + TEAH_curl_easy_post_finished (&deposit->ctx); GNUNET_free (deposit); } diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index 93fe798c3..0f3cfe0ae 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -33,6 +33,7 @@ #include "exchange_api_handle.h" #include "exchange_api_curl_defaults.h" #include "backoff.h" +#include "teah_common.h" /** * Which revision of the Taler protocol is implemented @@ -1783,6 +1784,12 @@ TALER_EXCHANGE_connect GNUNET_break (GNUNET_OK == GNUNET_CURL_append_header (ctx, "Expect:")); +#if COMPRESS_BODIES + /* Tell exchange we compress bodies */ + GNUNET_break (GNUNET_OK == + GNUNET_CURL_append_header (ctx, + "Content-encoding: deflate")); +#endif exchange = GNUNET_new (struct TALER_EXCHANGE_Handle); exchange->ctx = ctx; exchange->url = GNUNET_strdup (url); @@ -1816,6 +1823,7 @@ TALER_EXCHANGE_connect } + /** * Initiate download of /keys from the exchange. * diff --git a/src/lib/exchange_api_handle.h b/src/lib/exchange_api_handle.h index 2c01e319a..6bb3fff28 100644 --- a/src/lib/exchange_api_handle.h +++ b/src/lib/exchange_api_handle.h @@ -24,7 +24,7 @@ #include "taler_auditor_service.h" #include "taler_exchange_service.h" #include "taler_crypto_lib.h" - +#include "teah_common.h" /** * Entry in DLL of auditors used by an exchange. diff --git a/src/lib/exchange_api_payback.c b/src/lib/exchange_api_payback.c index b3624f737..325263d71 100644 --- a/src/lib/exchange_api_payback.c +++ b/src/lib/exchange_api_payback.c @@ -49,9 +49,10 @@ struct TALER_EXCHANGE_PaybackHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Denomination key of the coin. @@ -321,29 +322,23 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, ph->cb = payback_cb; ph->cb_cls = payback_cb_cls; ph->url = TEAH_path_to_url (exchange, "/payback"); - - ph->json_enc = json_dumps (payback_obj, - JSON_COMPACT); - json_decref (payback_obj); - if (NULL == ph->json_enc) + eh = TEL_curl_easy_get (ph->url); + if (GNUNET_OK != + TEAH_curl_easy_post (&ph->ctx, + eh, + payback_obj)) { GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (payback_obj); GNUNET_free (ph->url); GNUNET_free (ph); return NULL; } - eh = TEL_curl_easy_get (ph->url); + json_decref (payback_obj); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for payback: `%s'\n", ph->url); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - ph->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (ph->json_enc))); ctx = TEAH_handle_to_context (exchange); ph->job = GNUNET_CURL_job_add (ctx, eh, @@ -369,7 +364,7 @@ TALER_EXCHANGE_payback_cancel (struct TALER_EXCHANGE_PaybackHandle *ph) ph->job = NULL; } GNUNET_free (ph->url); - GNUNET_free (ph->json_enc); + TEAH_curl_easy_post_finished (&ph->ctx); GNUNET_free (ph); } diff --git a/src/lib/exchange_api_refresh.c b/src/lib/exchange_api_refresh.c index 4b2de2f45..30025d778 100644 --- a/src/lib/exchange_api_refresh.c +++ b/src/lib/exchange_api_refresh.c @@ -834,9 +834,10 @@ struct TALER_EXCHANGE_RefreshMeltHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Handle for the request. @@ -1206,18 +1207,19 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, rmh->url = TEAH_path_to_url (exchange, "/refresh/melt"); eh = TEL_curl_easy_get (rmh->url); - GNUNET_assert (NULL != (rmh->json_enc = - json_dumps (melt_obj, - JSON_COMPACT))); + if (GNUNET_OK != + TEAH_curl_easy_post (&rmh->ctx, + eh, + melt_obj)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (melt_obj); + GNUNET_free (rmh->url); + GNUNET_free (rmh); + return NULL; + } json_decref (melt_obj); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - rmh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (rmh->json_enc))); ctx = TEAH_handle_to_context (exchange); rmh->job = GNUNET_CURL_job_add (ctx, eh, @@ -1245,7 +1247,7 @@ TALER_EXCHANGE_refresh_melt_cancel (struct TALER_EXCHANGE_RefreshMeltHandle *rmh free_melt_data (rmh->md); /* does not free 'md' itself */ GNUNET_free (rmh->md); GNUNET_free (rmh->url); - GNUNET_free (rmh->json_enc); + TEAH_curl_easy_post_finished (&rmh->ctx); GNUNET_free (rmh); } @@ -1270,9 +1272,10 @@ struct TALER_EXCHANGE_RefreshRevealHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Handle for the request. @@ -1634,18 +1637,19 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange, "/refresh/reveal"); eh = TEL_curl_easy_get (rrh->url); - GNUNET_assert (NULL != (rrh->json_enc = - json_dumps (reveal_obj, - JSON_COMPACT))); + if (GNUNET_OK != + TEAH_curl_easy_post (&rrh->ctx, + eh, + reveal_obj)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (reveal_obj); + GNUNET_free (rrh->url); + GNUNET_free (rrh); + return NULL; + } json_decref (reveal_obj); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - rrh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (rrh->json_enc))); ctx = TEAH_handle_to_context (rrh->exchange); rrh->job = GNUNET_CURL_job_add (ctx, eh, @@ -1671,7 +1675,7 @@ TALER_EXCHANGE_refresh_reveal_cancel (struct TALER_EXCHANGE_RefreshRevealHandle rrh->job = NULL; } GNUNET_free (rrh->url); - GNUNET_free (rrh->json_enc); + TEAH_curl_easy_post_finished (&rrh->ctx); free_melt_data (rrh->md); /* does not free 'md' itself */ GNUNET_free (rrh->md); GNUNET_free (rrh); diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c index 75ebdc4e3..142213177 100644 --- a/src/lib/exchange_api_refund.c +++ b/src/lib/exchange_api_refund.c @@ -49,9 +49,10 @@ struct TALER_EXCHANGE_RefundHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Handle for the request. @@ -368,21 +369,22 @@ refund_obj = json_pack ("{s:o, s:o," /* amount/fee */ refund_fee); eh = TEL_curl_easy_get (rh->url); - GNUNET_assert (NULL != (rh->json_enc = - json_dumps (refund_obj, - JSON_COMPACT))); + if (GNUNET_OK != + TEAH_curl_easy_post (&rh->ctx, + eh, + refund_obj)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (refund_obj); + GNUNET_free (rh->url); + GNUNET_free (rh); + return NULL; + } json_decref (refund_obj); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for refund: `%s'\n", rh->url); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - rh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (rh->json_enc))); ctx = TEAH_handle_to_context (exchange); rh->job = GNUNET_CURL_job_add (ctx, eh, @@ -408,7 +410,7 @@ TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund) refund->job = NULL; } GNUNET_free (refund->url); - GNUNET_free (refund->json_enc); + TEAH_curl_easy_post_finished (&refund->ctx); GNUNET_free (refund); } diff --git a/src/lib/exchange_api_reserve.c b/src/lib/exchange_api_reserve.c index 66509bc53..ae0bd01d0 100644 --- a/src/lib/exchange_api_reserve.c +++ b/src/lib/exchange_api_reserve.c @@ -677,9 +677,10 @@ struct TALER_EXCHANGE_ReserveWithdrawHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Handle for the request. @@ -1022,25 +1023,26 @@ reserve_withdraw_internal (struct TALER_EXCHANGE_Handle *exchange, if (NULL == withdraw_obj) { GNUNET_break (0); + GNUNET_free (wsh); return NULL; } wsh->ps = *ps; wsh->url = TEAH_path_to_url (exchange, "/reserve/withdraw"); - eh = TEL_curl_easy_get (wsh->url); - GNUNET_assert (NULL != (wsh->json_enc = - json_dumps (withdraw_obj, - JSON_COMPACT))); + if (GNUNET_OK != + TEAH_curl_easy_post (&wsh->ctx, + eh, + withdraw_obj)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (withdraw_obj); + GNUNET_free (wsh->url); + GNUNET_free (wsh); + return NULL; + } json_decref (withdraw_obj); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - wsh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (wsh->json_enc))); ctx = TEAH_handle_to_context (exchange); wsh->job = GNUNET_CURL_job_add (ctx, eh, @@ -1199,7 +1201,7 @@ TALER_EXCHANGE_reserve_withdraw_cancel (struct TALER_EXCHANGE_ReserveWithdrawHan sign->job = NULL; } GNUNET_free (sign->url); - GNUNET_free (sign->json_enc); + TEAH_curl_easy_post_finished (&sign->ctx); GNUNET_free (sign); } diff --git a/src/lib/exchange_api_track_transaction.c b/src/lib/exchange_api_track_transaction.c index 0942ce84a..67efd77af 100644 --- a/src/lib/exchange_api_track_transaction.c +++ b/src/lib/exchange_api_track_transaction.c @@ -49,9 +49,10 @@ struct TALER_EXCHANGE_TrackTransactionHandle char *url; /** - * JSON encoding of the request to POST. + * Context for #TEH_curl_easy_post(). Keeps the data that must + * persist for Curl to make the upload. */ - char *json_enc; + struct TEAH_PostContext ctx; /** * Handle for the request. @@ -322,18 +323,19 @@ TALER_EXCHANGE_track_transaction (struct TALER_EXCHANGE_Handle *exchange, dwh->depconf.coin_pub = *coin_pub; eh = TEL_curl_easy_get (dwh->url); - GNUNET_assert (NULL != (dwh->json_enc = - json_dumps (deposit_wtid_obj, - JSON_COMPACT))); + if (GNUNET_OK != + TEAH_curl_easy_post (&dwh->ctx, + eh, + deposit_wtid_obj)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (deposit_wtid_obj); + GNUNET_free (dwh->url); + GNUNET_free (dwh); + return NULL; + } json_decref (deposit_wtid_obj); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - dwh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (dwh->json_enc))); ctx = TEAH_handle_to_context (exchange); dwh->job = GNUNET_CURL_job_add (ctx, eh, @@ -359,9 +361,9 @@ TALER_EXCHANGE_track_transaction_cancel (struct TALER_EXCHANGE_TrackTransactionH dwh->job = NULL; } GNUNET_free (dwh->url); - GNUNET_free (dwh->json_enc); + TEAH_curl_easy_post_finished (&dwh->ctx); GNUNET_free (dwh); } -/* end of exchange_api_deposit_wtid.c */ +/* end of exchange_api_track_transaction.c */ diff --git a/src/lib/teah_common.c b/src/lib/teah_common.c new file mode 100644 index 000000000..8f994ef36 --- /dev/null +++ b/src/lib/teah_common.c @@ -0,0 +1,105 @@ +/* + This file is part of TALER + Copyright (C) 2019 GNUnet e.V. + + 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 Foundation; either version 3, or (at your + option) any later version. + + TALER is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with TALER; see the file COPYING. If not, see + +*/ + +/** + * @file lib/teah_common.c + * @brief Helper routines shared by libtalerexchange and libtalerauditor + * @author Christian Grothoff + */ +#include "platform.h" +#include "teah_common.h" + +#if COMPRESS_BODIES +#include +#endif + + +/** + * Add the @a body as POST data to the easy handle in + * @a ctx. + * + * @param ctx[in,out] a request context (updated) + * @param eh easy handle to use + * @param body JSON body to add to @e ctx + * @return #GNUNET_OK on success #GNUNET_SYSERR on failure + */ +int +TEAH_curl_easy_post (struct TEAH_PostContext *ctx, + CURL *eh, + const json_t *body) +{ + char *str; + size_t slen; + + str = json_dumps (body, + JSON_COMPACT); + if (NULL == str) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + slen = strlen (str); +#if COMPRESS_BODIES + { + Bytef *cbuf; + uLongf cbuf_size; + int ret; + + cbuf_size = compressBound (slen); + cbuf = GNUNET_malloc (cbuf_size); + ret = compress (cbuf, + &cbuf_size, + (const Bytef *) str, + slen); + if (Z_OK != ret) + { + /* compression failed!? */ + GNUNET_break (0); + GNUNET_free (cbuf); + return GNUNET_SYSERR; + } + free (str); + slen = (size_t) cbuf_size; + ctx->json_enc = (char *) cbuf; + } +#else + ctx->json_enc = str; +#endif + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_POSTFIELDS, + ctx->json_enc)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_POSTFIELDSIZE, + slen)); + return GNUNET_OK; +} + + +/** + * Free the data in @a ctx. + * + * @param ctx[in] a request context (updated) + */ +void +TEAH_curl_easy_post_finished (struct TEAH_PostContext *ctx) +{ + GNUNET_free_non_null (ctx->json_enc); +} diff --git a/src/lib/teah_common.h b/src/lib/teah_common.h new file mode 100644 index 000000000..66937a261 --- /dev/null +++ b/src/lib/teah_common.h @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2019 GNUnet e.V. + + 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 Foundation; either version 3, or (at your + option) any later version. + + TALER is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with TALER; see the file COPYING. If not, see + +*/ +/** + * @file lib/teah_common.h + * @brief Helper routines shared by libtalerexchange and libtalerauditor + * @author Christian Grothoff + */ +#ifndef TEAH_COMMON_H +#define TEAH_COMMON_H + +#include +#include "taler_json_lib.h" + +/** + * Should we compress PUT/POST bodies with 'deflate' encoding? + */ +#define COMPRESS_BODIES 0 + +/** + * State used for #TEAL_curl_easy_post() and + * #TEAL_curl_easy_post_finished(). + */ +struct TEAH_PostContext +{ + /** + * JSON encoding of the request to POST. + */ + char *json_enc; + +}; + + +/** + * Add the @a body as POST data to the easy handle in + * @a ctx. + * + * @param ctx[in,out] a request context (updated) + * @param eh easy handle to use + * @param body JSON body to add to @e ctx + * @return #GNUNET_OK on success #GNUNET_SYSERR on failure + */ +int +TEAH_curl_easy_post (struct TEAH_PostContext *ctx, + CURL *eh, + const json_t *body); + + +/** + * Free the data in @a ctx. + * + * @param ctx[in] a request context (updated) + */ +void +TEAH_curl_easy_post_finished (struct TEAH_PostContext *ctx); + + + +#endif